<?php

namespace App\Http\Controllers;

use App\Http\Middleware\RedirectIfNotParmitted;
use App\Models\NavigationMenu;
use App\Services\NavigationMenuService;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Request;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Inertia\Inertia;

class NavigationMenusController extends Controller
{
    public function __construct(
        protected NavigationMenuService $navigationMenuService
    ) {
        $this->middleware(RedirectIfNotParmitted::class.':front_page');
    }

    public function index()
    {
        return Inertia::render('NavigationMenus/Index', [
            'title' => 'Navigation Menus',
            'filters' => Request::all(['search', 'location']),
            'menus' => NavigationMenu::orderBy('sort_order')
                ->orderBy('id')
                ->when(Request::input('location'), fn ($q, $location) => $q->where('location', $location))
                ->filter(Request::all(['search']))
                ->paginate(20)
                ->withQueryString()
                ->through(fn (NavigationMenu $menu) => $this->formatMenu($menu)),
            'locations' => [
                ['value' => NavigationMenuService::LOCATION_HEADER, 'label' => 'Header (Top Nav)'],
            ],
        ]);
    }

    public function create()
    {
        if ($response = $this->demoBlockedResponse('menus')) {
            return $response;
        }

        return Inertia::render('NavigationMenus/Create', [
            'title' => 'Create menu item',
            'route_options' => $this->navigationMenuService->routeOptionsForAdmin(),
            'feature_options' => $this->navigationMenuService->featureOptionsForAdmin(),
            'locations' => [
                ['value' => NavigationMenuService::LOCATION_HEADER, 'label' => 'Header (Top Nav)'],
            ],
        ]);
    }

    public function store()
    {
        if ($response = $this->demoBlockedResponse()) {
            return $response;
        }

        $data = $this->validatedData();
        $data['sort_order'] = $data['sort_order'] ?? (NavigationMenu::max('sort_order') + 1);

        NavigationMenu::create($data);
        $this->clearMenuCache();

        return Redirect::route('menus')->with('success', 'Menu item created.');
    }

    public function edit(NavigationMenu $menu)
    {
        if ($response = $this->demoBlockedResponse('menus')) {
            return $response;
        }

        return Inertia::render('NavigationMenus/Edit', [
            'title' => $menu->label,
            'menu' => $this->formatMenu($menu),
            'route_options' => $this->navigationMenuService->routeOptionsForAdmin(),
            'feature_options' => $this->navigationMenuService->featureOptionsForAdmin(),
            'locations' => [
                ['value' => NavigationMenuService::LOCATION_HEADER, 'label' => 'Header (Top Nav)'],
            ],
        ]);
    }

    public function update(NavigationMenu $menu)
    {
        if ($response = $this->demoBlockedResponse()) {
            return $response;
        }

        $menu->update($this->validatedData());
        $this->clearMenuCache();

        return Redirect::back()->with('success', 'Menu item updated.');
    }

    public function destroy(NavigationMenu $menu)
    {
        if ($response = $this->demoBlockedResponse()) {
            return $response;
        }

        $menu->delete();
        $this->clearMenuCache();

        return Redirect::route('menus')->with('success', 'Menu item deleted.');
    }

    public function reorder()
    {
        if ($response = $this->demoBlockedResponse()) {
            return $response;
        }

        Request::validate([
            'items' => ['required', 'array'],
            'items.*.id' => ['required', 'integer', 'exists:navigation_menus,id'],
            'items.*.sort_order' => ['required', 'integer', 'min:0'],
        ]);

        foreach (Request::input('items') as $item) {
            NavigationMenu::where('id', $item['id'])->update(['sort_order' => $item['sort_order']]);
        }
        $this->clearMenuCache();

        return Redirect::back()->with('success', 'Menu order updated.');
    }

    protected function clearMenuCache(): void
    {
        Cache::forget('navigation_menus.header');
    }

    protected function demoBlockedResponse(?string $fallbackRoute = null): ?\Illuminate\Http\RedirectResponse
    {
        if (! config('app.demo')) {
            return null;
        }

        $redirect = $fallbackRoute
            ? Redirect::route($fallbackRoute)
            : Redirect::back();

        return $redirect->with(
            'error',
            'Creating or updating navigation menus is not allowed in demo mode.'
        );
    }

    protected function validatedData(): array
    {
        $data = Request::validate([
            'location' => ['required', 'string', 'max:32'],
            'label' => ['required', 'string', 'max:100'],
            'route_name' => ['nullable', 'string', 'max:100', Rule::in($this->navigationMenuService->allowedRouteNames())],
            'route_params' => ['nullable', 'array'],
            'url' => ['nullable', 'string', 'max:500'],
            'icon' => ['nullable', 'string', 'max:50'],
            'active_key' => ['nullable', 'string', 'max:50'],
            'feature_slug' => ['nullable', 'string', 'max:50'],
            'target' => ['required', Rule::in(['_self', '_blank'])],
            'sort_order' => ['nullable', 'integer', 'min:0'],
            'is_active' => ['required', 'boolean'],
        ]);

        if (empty($data['route_name']) && empty($data['url'])) {
            throw ValidationException::withMessages([
                'route_name' => 'Either a route or URL is required.',
            ]);
        }

        if (!$this->navigationMenuService->validateUrl($data['url'] ?? null)) {
            throw ValidationException::withMessages([
                'url' => 'The URL must be a relative path (starting with /) or a valid http(s) link.',
            ]);
        }

        if (!empty($data['route_name'])) {
            $data['url'] = null;
        }

        if (empty($data['active_key']) && !empty($data['route_name'])) {
            $data['active_key'] = $this->defaultActiveKeyForRoute($data['route_name']);
        }

        return $data;
    }

    protected function defaultActiveKeyForRoute(string $routeName): string
    {
        return match ($routeName) {
            'home' => 'home',
            'ticket_open' => 'ticket',
            'services' => 'services',
            'kb' => 'kb',
            'faq' => 'faq',
            'blog' => 'blog',
            'contact' => 'contact',
            default => $routeName,
        };
    }

    protected function formatMenu(NavigationMenu $menu): array
    {
        return [
            'id' => $menu->id,
            'location' => $menu->location,
            'label' => $menu->label,
            'route_name' => $menu->route_name,
            'route_params' => $menu->route_params,
            'url' => $menu->url,
            'icon' => $menu->icon,
            'active_key' => $menu->active_key,
            'feature_slug' => $menu->feature_slug,
            'target' => $menu->target,
            'sort_order' => $menu->sort_order,
            'is_active' => $menu->is_active,
            'href' => $this->navigationMenuService->resolveHref($menu),
        ];
    }
}
