<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Arr;

use App\Models\Page;
use App\Http\Requests\PageValidation;
use App\Traits\PagesControllerTrait;
use Illuminate\Validation\Rule;
use App\Utilities\SearchResult;

class PagesController extends Controller
{
    use PagesControllerTrait;

    protected function getModel()
    {
        return new Page();
    }

    protected function getValidation()
    {
        return (new PageValidation());
    }

    protected function findPage($path)
    {
        return (new Page())->findByFullSlug($path);
    }

    public function userCanCreate($input)
    {
        Validator::make($input, [
            'version.parent_page_id' => 'required|exists:pages,id',
            'version.name' => 'required|string|max:255',
            'version.sort_order' => 'required|integer',
        ])->validate();
        $parent_page = Page::findOrFail(Arr::get($input, 'version.parent_page_id'));
        return auth()->user()->can('update', $parent_page);
    }

    /**
     * This returns a page tree for the editing side bar
     */
    public function index()
    {
        $page = Page::findOrFail(1);
        $page->load('version');
        $page->appendAttributes();

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

    public function sortPage($id)
    {
        if (!auth()->check()) {
            abort(401);
        }

        $page = Page::findOrFail($id);

        if (!auth()->user()->can('update', $page) || !auth()->user()->hasRole('pages-sort')) {
            return response()->json(['error' => 'You do not have permission to sort pages'], 403);
        }

        Validator::make(request()->all(), [
            'parent_page_id' => [
                'required',
                'integer',
                'min:1',
                'exists:pages,id',
                Rule::notIn([$page->id]),
            ],
            'sort_order' => [
                'required',
                'numeric',
            ],
        ])->validate();

        (new Page())->sortPages($page, requestInput());
        cache()->tags([cache_name($page)])->flush();

        return response()->json([
            'success' => $page->version->name.' Saved',
        ]);
    }

    public function remove($id)
    {
        $page = Page::findOrFail($id);

        if (!auth()->check()) {
            return abort(401);
        }

        if ($page->id === 1) {
            if (request()->expectsJson()) {
                return response()->json(['error' => 'The home page cannot be deleted'], 403);
            }
            return redirect('/')->with(['error' => 'The home page cannot be deleted']);
        }

        if (!auth()->user()->can('delete', $page)) {
            if (request()->expectsJson()) {
                return response()->json(['error' => 'You do not have permission to remove that page'], 403);
            }
            return redirect('/')->with(['error' => 'You do not have permission to remove that page']);
        }

        cache()->tags([cache_name($page)])->flush();
        $page->contentables()->delete();
        $page->delete();

        return response()->json(['success' => 'Page Removed']);
    }

    public function subPages($id)
    {
        $page = Page::findOrFail($id);

        if (!auth()->check()) {
            return abort(401);
        }

        if (!auth()->user()->can('update', $page) && !auth()->user()->hasRole('pages-editor')) {
            return response()->json(['error' => 'You do not have permission to load attributes'], 403);
        }

        $sub_pages = $page->getPages();

        $sub_pages->each(function ($sub) {
            $sub->appendAttributes();
            $sub->append('pages_count', 'parent_page_ids');
        });

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

    public function toggleExpanded()
    {
        if (!auth()->user()->hasRole('pages-editor')) {
            return response()->json(['error' => 'You do not have permission to expand pages'], 403);
        }

        $ids = request('ids');

        if (!is_array($ids)) {
            $ids = [$ids];
        }

        $page_ids = Page::whereIn('id', $ids)->get()->pluck('id');

        if (!session()->has('expanded_page_ids')) {
            session()->put('expanded_page_ids', $page_ids);
        } else {
            $expanded_page_ids = session()->get('expanded_page_ids');

            foreach ($page_ids as $page_id) {
                if ($expanded_page_ids->contains($page_id)) {
                    $expanded_page_ids = $expanded_page_ids->filter(function ($id) use ($page_id) {
                        return $id !== $page_id;
                    });
                } else {
                    $expanded_page_ids->push($page_id);
                }
            }

            session()->put('expanded_page_ids', $expanded_page_ids);
        }

        return response()->json([
            'expanded_page_ids' => session()->get('expanded_page_ids')->values()->all(),
        ]);
    }

    public function searchTree()
    {
        $input = request()->only('terms');
        Validator::make($input, [
            'terms' => 'required',
        ])->validate();

        $terms  = SearchResult::collectTerms();
        $pages = Page::searchForItems($terms);

        if (!session()->has('expanded_page_ids')) {
            session()->put('expanded_page_ids', collect());
        }

        $expanded_page_ids = session()->get('expanded_page_ids');

        foreach ($pages as $page) {
            $expanded_page_ids = $expanded_page_ids->merge($page->parent_page_ids);
        }

        session()->put('expanded_page_ids', $expanded_page_ids->unique());

        return response()->json([
            'expanded_page_ids' => session()->get('expanded_page_ids')->values()->all(),
        ]);
    }

    public function nxtForm($id)
    {
        return view('nxt-form', compact('id'));
    }

    public function siblingNav($id)
    {
        $page = Page::findOrFail($id);
        $page->load('parentPage');
        $page->parentPage->append(['full_slug', 'photo', 'name']);
        $page->append(['next_page', 'next_page2', 'previous_page', 'previous_page2']);
        return response()->json(['page' => $page]);
    }
}
