<?php

namespace App\Exceptions;

use App\Models\ClientDomain;
use App\Models\ClientProduct;
use App\Models\Contract;
use App\Models\Invoice;
use App\Models\Order;
use App\Models\Quote;
use App\Models\Ticket;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Route;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

class NotFoundResolver
{
    private const DEFAULT_ACTIONS = [
        'store'      => ['route' => 'store.index',           'label_key' => 'errors.404_action_home'],
        'clientarea' => ['route' => 'store.auth.dashboard',  'label_key' => 'errors.404_action_dashboard'],
        'admin'      => ['route' => 'admin.dashboard',       'label_key' => 'errors.404_action_dashboard'],
    ];

    /**
     * Map: model class => [title_key, message_key].
     */
    private const MODEL_MAP = [
        Invoice::class       => ['title_key' => 'errors.404_invoice_title',  'message_key' => 'errors.404_invoice_message'],
        ClientProduct::class => ['title_key' => 'errors.404_service_title',  'message_key' => 'errors.404_service_message'],
        ClientDomain::class  => ['title_key' => 'errors.404_domain_title',   'message_key' => 'errors.404_domain_message'],
        Order::class         => ['title_key' => 'errors.404_order_title',    'message_key' => 'errors.404_order_message'],
        Ticket::class        => ['title_key' => 'errors.404_ticket_title',   'message_key' => 'errors.404_ticket_message'],
        Quote::class         => ['title_key' => 'errors.404_quote_title',    'message_key' => 'errors.404_quote_message'],
        Contract::class      => ['title_key' => 'errors.404_contract_title', 'message_key' => 'errors.404_contract_message'],
    ];

    /**
     * Smart action route per [model][context]. Missing entry = no smart action in that context.
     */
    private const SMART_ACTIONS = [
        Invoice::class => [
            'clientarea' => ['route' => 'store.auth.invoices', 'label_key' => 'errors.404_action_my_invoices'],
            'admin'      => ['route' => 'admin.billing.index', 'label_key' => 'errors.404_action_admin_invoices'],
        ],
        ClientProduct::class => [
            'clientarea' => ['route' => 'store.auth.services', 'label_key' => 'errors.404_action_my_services'],
        ],
        ClientDomain::class => [
            'clientarea' => ['route' => 'store.auth.domains', 'label_key' => 'errors.404_action_my_domains'],
        ],
        Order::class => [
            'admin' => ['route' => 'admin.orders.index', 'label_key' => 'errors.404_action_admin_orders'],
        ],
        Ticket::class => [
            'clientarea' => ['route' => 'store.auth.tickets', 'label_key' => 'errors.404_action_my_tickets'],
            'admin'      => ['route' => 'admin.tickets.index', 'label_key' => 'errors.404_action_admin_tickets'],
        ],
        Quote::class => [
            'clientarea' => ['route' => 'store.auth.quotes', 'label_key' => 'errors.404_action_my_quotes'],
            'admin'      => ['route' => 'admin.quotes.index', 'label_key' => 'errors.404_action_admin_quotes'],
        ],
        Contract::class => [
            'admin' => ['route' => 'admin.contracts.index', 'label_key' => 'errors.404_action_admin_contracts'],
        ],
    ];

    /**
     * @return array{title:string,message:string,smart_action:?array{label:string,url:string},default_action:array{label:string,url:string}}
     */
    public function resolve(Throwable $e, string $context): array
    {
        [$title, $message] = $this->resolveTitleAndMessage($e, $context);

        return [
            'title'          => $title,
            'message'        => $message,
            'smart_action'   => $this->resolveSmartAction($e, $context),
            'default_action' => $this->resolveDefaultAction($context),
        ];
    }

    private function resolveTitleAndMessage(Throwable $e, string $context): array
    {
        if ($e instanceof ModelNotFoundException) {
            $modelClass = $e->getModel();
            if ($modelClass && isset(self::MODEL_MAP[$modelClass])) {
                $entry = self::MODEL_MAP[$modelClass];
                return [__($entry['title_key']), __($entry['message_key'])];
            }
        }

        if ($e instanceof NotFoundHttpException && $e->getMessage() !== '') {
            // Skip Laravel's auto-generated "The route X could not be found." message
            // — that's internal routing detail, not a user-facing message. Fall through
            // to per-context default. abort(404, 'human message') still passes through.
            if (! preg_match('/^The route .+ could not be found\.?$/', $e->getMessage())) {
                return [$e->getMessage(), ''];
            }
        }

        return [
            __('errors.404_default_title_' . $context),
            __('errors.404_default_message_' . $context),
        ];
    }

    private function resolveSmartAction(Throwable $e, string $context): ?array
    {
        if (! $e instanceof ModelNotFoundException) {
            return null;
        }

        $modelClass = $e->getModel();
        $entry      = self::SMART_ACTIONS[$modelClass][$context] ?? null;
        if ($entry === null) {
            return null;
        }

        if (! Route::has($entry['route'])) {
            return null;
        }

        return [
            'label' => __($entry['label_key']),
            'url'   => route($entry['route']),
        ];
    }

    private function resolveDefaultAction(string $context): array
    {
        $entry = self::DEFAULT_ACTIONS[$context] ?? self::DEFAULT_ACTIONS['store'];
        return [
            'label' => __($entry['label_key']),
            'url'   => route($entry['route']),
        ];
    }
}
