<?php

namespace Fivable\Buildable\Controllers;

use Fivable\Buildable\Builders\PageRenderer;
use Fivable\Buildable\Models\BuildableMenu;
use Fivable\Buildable\Models\BuildableSetting;
use Fivable\Buildable\Requests\BuildablePageRequest;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Fivable\Scaffolding\Controllers\ApiController;
use Fivable\Buildable\Models\BuildablePage;
use Illuminate\View\View;

use Log;

class BuildablePageController extends ApiController
{
    /**
     * Return all Buildable Pages
     * @param Request $request
     * @return JsonResponse
     */
    public function index(Request $request) : JsonResponse
    {
        $this->authorizeForUser($this->user(), 'viewIndex', BuildablePage::class);

        $pages = BuildablePage::indexFor($request->status_masks);

        return response()->json([
            'pages' => $pages,
        ]);
    }

    /**
     * Return a specific Buildable Page
     * @param  BuildablePage   $buildablePage
     * @return JsonResponse
     */
    public function show(BuildablePage $buildablePage) : JsonResponse
    {
        $this->authorizeForUser($this->user(), 'view', $buildablePage);

        $buildablePage = BuildablePage::where('id', $buildablePage->id)->with('components')->with('metas')->first();
        $otherPages = BuildablePage::where([['id', '<>', $buildablePage->id], ['parent_id', '<>', $buildablePage->id]])
            ->orWhere(function($query) use ($buildablePage) {
                $query->whereNull('parent_id')->where('id', '<>', $buildablePage->id);
            })->get();

        $buildablePage->update(['active_user_id' => $this->user()->id]);

        return response()->json([
            'page' => $buildablePage,
            'other_pages' => $otherPages,
        ]);
    }

    /**
     * Create a new Buildable Page
     * @param  Request $request
     * @return JsonResponse
     */
    public function store(BuildablePageRequest $request) : JsonResponse
    {
        $user = $this->user();
        $this->authorizeForUser($user, 'create', BuildablePage::class);

        $newPage = BuildablePage::createPage($request->all(), $user);
        $newPage = BuildablePage::where('id', $newPage->id)->with('components')->with('metas')->first();

        return response()->json([
            'new_page' => $newPage,
        ]);
    }

    /**
     * Update a specific Buildable Page
     * @param  BuildablePageRequest $request
     * @param  BuildablePage   $buildablePage
     * @return JsonResponse
     */
    public function update(BuildablePageRequest $request, BuildablePage $buildablePage) : JsonResponse
    {
        $this->authorizeForUser($this->user(), 'update', $buildablePage);

        $buildablePage->updatePage($request->all());
        $buildablePage = BuildablePage::where('id', $buildablePage->id)->with('components')->with('metas')->first();

        return response()->json([
            'updated_page' => $buildablePage,
        ]);
    }

    /**
     * Update a specific Buildable Page's status mask
     * @param Request $request
     * @param BuildablePage $buildablePage
     * @return JsonResponse
     */
    public function updateStatusMask(Request $request, BuildablePage $buildablePage)
    {
        $this->authorizeForUser($this->user(), 'update', $buildablePage);

        $buildablePage->update(['status_mask' => $request->status_mask]);

        return response()->json(['updated_page' => $buildablePage->fresh()]);
    }

    /**
     * Make a specific Buildable Page the home page
     * @param BuildablePage $buildablePage
     * @return JsonResponse
     */
    public function makeHomepage(BuildablePage $buildablePage) : JsonResponse
    {
        $buildablePage->makeHomepage();
        $newHomepage = BuildablePage::where('is_homepage', 1)->with('user')->first();

        return response()->json([
            'new_homepage' => $newHomepage,
        ]);
    }

    /**
     * Unset the current user as the active user of the given page (must be themselves)
     * @param BuildablePage $buildablePage
     * @return JsonResponse
     */
    public function unsetActiveUser(BuildablePage $buildablePage) : JsonResponse
    {
        $this->authorizeForUser($this->user(), 'unsetActive', $buildablePage);

        $buildablePage->update(['active_user_id' => NULL]);

        return response()->json(['updated_page' => $buildablePage->fresh()]);
    }

    /**
     * Delete a specific BuildablePage
     * @param  BuildablePage  $buildablePage
     * @return JsonResponse
     * @throws \Exception
     */
    public function destroy(BuildablePage $buildablePage) : JsonResponse
    {
        $this->authorizeForUser($this->user(), 'delete', $buildablePage);

        $buildablePage->delete();

        return response()->json([
            'deleted_page' => $buildablePage
        ]);
    }

    /**
     * Return the buildable-page view with
     * @param Request $request
     * @param string $slug
     * @param bool $isHomeRoute
     * @return View
     *
     * NOTE: $isHomeRoute indicates this is '/' route, not just that you're on the homepage
     */
    public function showPublic(Request $request, string $slug, bool $isHomeRoute = false) : View
    {
        // Why is status_mask & 1 not working???
        $buildablePage = BuildablePage::where('slug', $slug)->whereRaw('status_mask & 1')->first();

        $pageRenderer = !is_null($buildablePage) ? new PageRenderer($buildablePage) : NULL;
        $publicPageSettings = BuildableSetting::snailCaseSettings();
        $userLoggedIn = false; // TODO: Make this work

        $innerNav = !is_null($buildablePage) ? $buildablePage->inner_nav()->first() : NULL;
        $header = BuildableMenu::where('type', 'header')->first();
        $footer = BuildableMenu::where('type', 'footer')->first();
        $mobileMenu = BuildableMenu::where('type', 'mobile')->first();
        $homePage = BuildablePage::homePage();
        $homePageUrl = BuildablePage::homePageUrl();
        $homePageTitle = !is_null($homePage) ? $homePage->title : NULL;

        $viewVariables = compact('pageRenderer', 'buildablePage', 'userLoggedIn', 'userLoggedIn',
            'innerNav', 'header', 'footer', 'mobileMenu', 'homePageUrl', 'isHomeRoute', 'homePageTitle');

        $viewVariables = array_merge($viewVariables, $publicPageSettings);

        if (is_null($buildablePage)) {
            return view('buildable::return-404', $viewVariables);
        }

        return view('buildable::buildable-page', $viewVariables);
    }

    public function showHomepage(Request $request)
    {
        $homePage = BuildablePage::homePage();
        $homePageSlug = !is_null($homePage) ? $homePage->slug : NULL;
        if (!is_null($homePageSlug)) {
            return $this->showPublic($request, $homePageSlug, true);
        } else {
            return response()->json(['error' => 'no homepage set'], 404);
        }
    }
}
