<?php

namespace App\Support\Authorization;

use App\Models\Role;
use App\Models\User;

class PermissionCatalog
{
    public const GLOBAL_TEAM_ID = 0;

    public const PANEL_ADMIN = 'admin';

    public const PANEL_OWNER = 'owner';

    public static function actionLabels(): array
    {
        return [
            'view' => 'Ver',
            'create' => 'Crear',
            'edit' => 'Editar',
            'delete' => 'Eliminar',
        ];
    }

    public static function modulesFor(string $panel): array
    {
        return match ($panel) {
            self::PANEL_ADMIN => self::adminModules(),
            self::PANEL_OWNER => self::ownerModules(),
            default => [],
        };
    }

    public static function adminModules(): array
    {
        return [
            'dashboard' => ['label' => 'Dashboard', 'actions' => ['view']],
            'users' => ['label' => 'Propietarios', 'actions' => ['view', 'create', 'edit', 'delete']],
            'organizations' => ['label' => 'Grupos Mariachi', 'actions' => ['view', 'create', 'edit', 'delete']],
            'team' => ['label' => 'Equipo soporte', 'actions' => ['view', 'create', 'edit', 'delete']],
            'roles' => ['label' => 'Roles soporte', 'actions' => ['view', 'create', 'edit', 'delete']],
            'clients' => ['label' => 'Clientes demo', 'actions' => ['view']],
            'reservations' => ['label' => 'Reservas demo', 'actions' => ['view']],
            'groups' => ['label' => 'Grupos demo', 'actions' => ['view']],
            'catalogs' => ['label' => 'Catálogos demo', 'actions' => ['view']],
        ];
    }

    public static function ownerModules(): array
    {
        return [
            'dashboard' => ['label' => 'Dashboard', 'actions' => ['view']],
            'serenatas' => ['label' => 'Serenatas', 'actions' => ['view', 'create', 'edit', 'delete']],
            'planner' => ['label' => 'Planificador', 'actions' => ['view', 'edit']],
            'clients' => ['label' => 'Clientes', 'actions' => ['view', 'create', 'edit', 'delete']],
            'quotes' => ['label' => 'Cotizador', 'actions' => ['view', 'edit']],
            'reports' => ['label' => 'Reportes', 'actions' => ['view']],
            'external_partners' => ['label' => 'Externos (Cedidas)', 'actions' => ['view', 'create', 'edit']],
            'mariachi_groups' => ['label' => 'Grupos Mariachi', 'actions' => ['view', 'create', 'edit']],
            'packages' => ['label' => 'Paquetes', 'actions' => ['view', 'create', 'edit', 'delete']],
            'gifts' => ['label' => 'Obsequios', 'actions' => ['view', 'create', 'edit', 'delete']],
            'artists' => ['label' => 'Artistas', 'actions' => ['view', 'create', 'edit', 'delete']],
            'other_costs' => ['label' => 'Otros costos', 'actions' => ['view', 'create', 'edit', 'delete']],
            'payments' => ['label' => 'Pagos', 'actions' => ['view', 'create', 'edit', 'delete']],
            'quote_rules' => ['label' => 'Reglas de cotizador', 'actions' => ['view', 'create', 'edit', 'delete']],
            'price_rules' => ['label' => 'Reglas de precio', 'actions' => ['view', 'create', 'edit', 'delete']],
            'settings_general' => ['label' => 'Configuración general', 'actions' => ['view', 'edit']],
            'team' => ['label' => 'Equipo', 'actions' => ['view', 'create', 'edit', 'delete']],
            'roles' => ['label' => 'Roles', 'actions' => ['view', 'create', 'edit', 'delete']],
        ];
    }

    public static function permissionName(string $panel, string $module, string $action): string
    {
        return implode('.', [$panel, $module, $action]);
    }

    public static function allPermissionNames(): array
    {
        $permissions = [];

        foreach ([self::PANEL_ADMIN, self::PANEL_OWNER] as $panel) {
            foreach (self::modulesFor($panel) as $module => $config) {
                foreach ($config['actions'] as $action) {
                    $permissions[] = self::permissionName($panel, $module, $action);
                }
            }
        }

        return $permissions;
    }

    public static function permissionNamesForPanel(string $panel): array
    {
        $permissions = [];

        foreach (self::modulesFor($panel) as $module => $config) {
            foreach ($config['actions'] as $action) {
                $permissions[] = self::permissionName($panel, $module, $action);
            }
        }

        return $permissions;
    }

    public static function normalizeSubmittedPermissions(array $inputPermissions, string $panel): array
    {
        $permissions = [];

        foreach (self::modulesFor($panel) as $module => $config) {
            foreach ($config['actions'] as $action) {
                if ((bool) data_get($inputPermissions, $module.'.'.$action, false)) {
                    $permissions[] = self::permissionName($panel, $module, $action);
                }
            }
        }

        return $permissions;
    }

    public static function permissionMatrixForRole(Role $role, string $panel): array
    {
        $permissionNames = $role->permissions->pluck('name')->flip();
        $matrix = [];

        foreach (self::modulesFor($panel) as $module => $config) {
            foreach ($config['actions'] as $action) {
                $matrix[$module][$action] = $permissionNames->has(
                    self::permissionName($panel, $module, $action)
                );
            }
        }

        return $matrix;
    }

    public static function ownerSystemRoleCode(int $organizationId): string
    {
        return 'ORG'.$organizationId.'_OWNER';
    }

    public static function firstAccessibleRouteFor(User $user): string
    {
        $isAdminArea = in_array($user->role, User::adminRoles(), true);
        $routes = $isAdminArea
            ? self::adminNavigationRoutes()
            : self::ownerNavigationRoutes();

        setPermissionsTeamId($isAdminArea ? self::GLOBAL_TEAM_ID : ((int) ($user->organization_id ?? 0)));

        foreach ($routes as $routeName => $permission) {
            if ($user->can($permission)) {
                return route($routeName);
            }
        }

        return route($isAdminArea ? 'admin.dashboard' : 'owner.dashboard');
    }

    public static function permissionForRoute(?string $routeName): ?string
    {
        if (empty($routeName)) {
            return null;
        }

        return match (true) {
            str_starts_with($routeName, 'admin.') => self::adminPermissionForRoute($routeName),
            str_starts_with($routeName, 'owner.') => self::ownerPermissionForRoute($routeName),
            default => null,
        };
    }

    public static function adminNavigationRoutes(): array
    {
        return [
            'admin.dashboard' => self::permissionName(self::PANEL_ADMIN, 'dashboard', 'view'),
            'admin.users.index' => self::permissionName(self::PANEL_ADMIN, 'users', 'view'),
            'admin.mariachi-groups.index' => self::permissionName(self::PANEL_ADMIN, 'organizations', 'view'),
            'admin.team.index' => self::permissionName(self::PANEL_ADMIN, 'team', 'view'),
            'admin.roles.index' => self::permissionName(self::PANEL_ADMIN, 'roles', 'view'),
        ];
    }

    public static function ownerNavigationRoutes(): array
    {
        return [
            'owner.dashboard' => self::permissionName(self::PANEL_OWNER, 'dashboard', 'view'),
            'owner.serenatas.index' => self::permissionName(self::PANEL_OWNER, 'serenatas', 'view'),
            'owner.serenatas.planner' => self::permissionName(self::PANEL_OWNER, 'planner', 'view'),
            'owner.clients.index' => self::permissionName(self::PANEL_OWNER, 'clients', 'view'),
            'owner.quotes.calculator' => self::permissionName(self::PANEL_OWNER, 'quotes', 'view'),
            'owner.reports.index' => self::permissionName(self::PANEL_OWNER, 'reports', 'view'),
            'owner.settings.external-partners' => self::permissionName(self::PANEL_OWNER, 'external_partners', 'view'),
            'owner.settings.external-partners.show' => self::permissionName(self::PANEL_OWNER, 'external_partners', 'view'),
            'owner.settings.mariachi-groups' => self::permissionName(self::PANEL_OWNER, 'mariachi_groups', 'view'),
            'owner.settings.packages' => self::permissionName(self::PANEL_OWNER, 'packages', 'view'),
            'owner.settings.gifts' => self::permissionName(self::PANEL_OWNER, 'gifts', 'view'),
            'owner.settings.artists' => self::permissionName(self::PANEL_OWNER, 'artists', 'view'),
            'owner.settings.other-costs' => self::permissionName(self::PANEL_OWNER, 'other_costs', 'view'),
            'owner.settings.index' => self::permissionName(self::PANEL_OWNER, 'settings_general', 'view'),
            'owner.settings.team' => self::permissionName(self::PANEL_OWNER, 'team', 'view'),
            'owner.settings.roles' => self::permissionName(self::PANEL_OWNER, 'roles', 'view'),
            'owner.settings.payments' => self::permissionName(self::PANEL_OWNER, 'payments', 'view'),
            'owner.settings.quote-rules' => self::permissionName(self::PANEL_OWNER, 'quote_rules', 'view'),
        ];
    }

    public static function mapLegacyPermissions(array $legacyPermissions, string $panel): array
    {
        $mapped = [];

        $legacyMap = match ($panel) {
            self::PANEL_ADMIN => [
                'clients' => 'users',
            ],
            self::PANEL_OWNER => [
                'clients' => 'clients',
                'serenatas' => 'serenatas',
                'team' => 'team',
            ],
            default => [],
        };

        foreach ($legacyMap as $legacyModule => $newModule) {
            foreach (['read' => 'view', 'create' => 'create', 'edit' => 'edit', 'delete' => 'delete'] as $legacyAction => $newAction) {
                if ((bool) data_get($legacyPermissions, $legacyModule.'.'.$legacyAction, false)) {
                    $mapped[] = self::permissionName($panel, $newModule, $newAction);
                }
            }
        }

        return array_values(array_unique($mapped));
    }

    private static function adminPermissionForRoute(string $routeName): ?string
    {
        return match (true) {
            $routeName === 'admin.dashboard' => self::permissionName(self::PANEL_ADMIN, 'dashboard', 'view'),
            $routeName === 'admin.users.index' => self::permissionName(self::PANEL_ADMIN, 'users', 'view'),
            $routeName === 'admin.users.store' => self::permissionName(self::PANEL_ADMIN, 'users', 'create'),
            $routeName === 'admin.users.deactivate' => self::permissionName(self::PANEL_ADMIN, 'users', 'delete'),
            $routeName === 'admin.organizations.index',
            $routeName === 'admin.mariachi-groups.index',
            $routeName === 'admin.organizations.create',
            $routeName === 'admin.mariachi-groups.create' => self::permissionName(self::PANEL_ADMIN, 'organizations', 'view'),
            $routeName === 'admin.organizations.store',
            $routeName === 'admin.mariachi-groups.store' => self::permissionName(self::PANEL_ADMIN, 'organizations', 'create'),
            $routeName === 'admin.mariachi-groups.update',
            $routeName === 'admin.mariachi-groups.deactivate',
            $routeName === 'admin.mariachi-groups.merge' => self::permissionName(self::PANEL_ADMIN, 'organizations', 'edit'),
            $routeName === 'admin.mariachi-groups.destroy' => self::permissionName(self::PANEL_ADMIN, 'organizations', 'delete'),
            $routeName === 'admin.team.index' => self::permissionName(self::PANEL_ADMIN, 'team', 'view'),
            $routeName === 'admin.team.store' => self::permissionName(self::PANEL_ADMIN, 'team', 'create'),
            $routeName === 'admin.team.deactivate' => self::permissionName(self::PANEL_ADMIN, 'team', 'delete'),
            $routeName === 'admin.roles.index' => self::permissionName(self::PANEL_ADMIN, 'roles', 'view'),
            $routeName === 'admin.roles.store' => self::permissionName(self::PANEL_ADMIN, 'roles', 'create'),
            $routeName === 'admin.roles.update' => self::permissionName(self::PANEL_ADMIN, 'roles', 'edit'),
            $routeName === 'admin.roles.destroy' => self::permissionName(self::PANEL_ADMIN, 'roles', 'delete'),
            $routeName === 'admin.clients.index' => self::permissionName(self::PANEL_ADMIN, 'clients', 'view'),
            $routeName === 'admin.reservations.index' => self::permissionName(self::PANEL_ADMIN, 'reservations', 'view'),
            $routeName === 'admin.groups.index' => self::permissionName(self::PANEL_ADMIN, 'groups', 'view'),
            $routeName === 'admin.catalogs.index' => self::permissionName(self::PANEL_ADMIN, 'catalogs', 'view'),
            default => null,
        };
    }

    private static function ownerPermissionForRoute(string $routeName): ?string
    {
        return match (true) {
            $routeName === 'owner.dashboard',
            $routeName === 'owner.workspace.switch' => self::permissionName(self::PANEL_OWNER, 'dashboard', 'view'),
            $routeName === 'owner.serenatas.index',
            $routeName === 'owner.serenatas.show',
            $routeName === 'owner.serenatas.package-template',
            $routeName === 'owner.serenatas.location-options',
            $routeName === 'owner.serenatas.address-resolve',
            $routeName === 'owner.serenatas.address-suggestions' => self::permissionName(self::PANEL_OWNER, 'serenatas', 'view'),
            $routeName === 'owner.serenatas.planner',
            $routeName === 'owner.serenatas.planner.data' => self::permissionName(self::PANEL_OWNER, 'planner', 'view'),
            $routeName === 'owner.serenatas.planner.move',
            $routeName === 'owner.serenatas.planner.optimize' => self::permissionName(self::PANEL_OWNER, 'planner', 'edit'),
            $routeName === 'owner.serenatas.store',
            $routeName === 'owner.serenatas.ai-parse' => self::permissionName(self::PANEL_OWNER, 'serenatas', 'create'),
            str_starts_with($routeName, 'owner.serenatas.') => self::permissionName(self::PANEL_OWNER, 'serenatas', 'edit'),
            $routeName === 'owner.clients.index',
            $routeName === 'owner.clients.show' => self::permissionName(self::PANEL_OWNER, 'clients', 'view'),
            $routeName === 'owner.clients.store' => self::permissionName(self::PANEL_OWNER, 'clients', 'create'),
            $routeName === 'owner.clients.deactivate' => self::permissionName(self::PANEL_OWNER, 'clients', 'delete'),
            $routeName === 'owner.quotes.calculator' => self::permissionName(self::PANEL_OWNER, 'quotes', 'view'),
            $routeName === 'owner.quotes.calculator.calculate' => self::permissionName(self::PANEL_OWNER, 'quotes', 'edit'),
            $routeName === 'owner.reports.index' => self::permissionName(self::PANEL_OWNER, 'reports', 'view'),
            $routeName === 'owner.settings.index' => self::permissionName(self::PANEL_OWNER, 'settings_general', 'view'),
            $routeName === 'owner.settings.update',
            $routeName === 'owner.settings.api-tokens.store',
            $routeName === 'owner.settings.api-tokens.reset',
            $routeName === 'owner.settings.api-tokens.revoke' => self::permissionName(self::PANEL_OWNER, 'settings_general', 'edit'),
            $routeName === 'owner.settings.team' => self::permissionName(self::PANEL_OWNER, 'team', 'view'),
            $routeName === 'owner.settings.team.store' => self::permissionName(self::PANEL_OWNER, 'team', 'create'),
            $routeName === 'owner.settings.team.deactivate' => self::permissionName(self::PANEL_OWNER, 'team', 'delete'),
            $routeName === 'owner.settings.roles' => self::permissionName(self::PANEL_OWNER, 'roles', 'view'),
            $routeName === 'owner.settings.roles.store' => self::permissionName(self::PANEL_OWNER, 'roles', 'create'),
            $routeName === 'owner.settings.roles.update' => self::permissionName(self::PANEL_OWNER, 'roles', 'edit'),
            $routeName === 'owner.settings.roles.destroy' => self::permissionName(self::PANEL_OWNER, 'roles', 'delete'),
            $routeName === 'owner.settings.external-partners',
            $routeName === 'owner.settings.external-partners.show' => self::permissionName(self::PANEL_OWNER, 'external_partners', 'view'),
            $routeName === 'owner.settings.external-partners.store' => self::permissionName(self::PANEL_OWNER, 'external_partners', 'create'),
            $routeName === 'owner.settings.external-partners.update',
            $routeName === 'owner.settings.external-partners.deactivate',
            $routeName === 'owner.settings.external-partners.destroy' => self::permissionName(self::PANEL_OWNER, 'external_partners', 'edit'),
            $routeName === 'owner.settings.mariachi-groups',
            $routeName === 'owner.settings.mariachi-groups.show' => self::permissionName(self::PANEL_OWNER, 'mariachi_groups', 'view'),
            $routeName === 'owner.settings.mariachi-groups.store' => self::permissionName(self::PANEL_OWNER, 'mariachi_groups', 'create'),
            $routeName === 'owner.settings.mariachi-groups.update',
            $routeName === 'owner.settings.mariachi-groups.deactivate',
            $routeName === 'owner.settings.mariachi-groups.destroy' => self::permissionName(self::PANEL_OWNER, 'mariachi_groups', 'edit'),
            $routeName === 'owner.settings.packages' => self::permissionName(self::PANEL_OWNER, 'packages', 'view'),
            $routeName === 'owner.settings.packages.store' => self::permissionName(self::PANEL_OWNER, 'packages', 'create'),
            $routeName === 'owner.settings.packages.update' => self::permissionName(self::PANEL_OWNER, 'packages', 'edit'),
            $routeName === 'owner.settings.packages.destroy' => self::permissionName(self::PANEL_OWNER, 'packages', 'delete'),
            $routeName === 'owner.settings.gifts' => self::permissionName(self::PANEL_OWNER, 'gifts', 'view'),
            $routeName === 'owner.settings.gifts.store' => self::permissionName(self::PANEL_OWNER, 'gifts', 'create'),
            $routeName === 'owner.settings.gifts.update' => self::permissionName(self::PANEL_OWNER, 'gifts', 'edit'),
            $routeName === 'owner.settings.gifts.destroy' => self::permissionName(self::PANEL_OWNER, 'gifts', 'delete'),
            $routeName === 'owner.settings.artists' => self::permissionName(self::PANEL_OWNER, 'artists', 'view'),
            $routeName === 'owner.settings.artists.store' => self::permissionName(self::PANEL_OWNER, 'artists', 'create'),
            $routeName === 'owner.settings.artists.update' => self::permissionName(self::PANEL_OWNER, 'artists', 'edit'),
            $routeName === 'owner.settings.artists.destroy' => self::permissionName(self::PANEL_OWNER, 'artists', 'delete'),
            $routeName === 'owner.settings.other-costs' => self::permissionName(self::PANEL_OWNER, 'other_costs', 'view'),
            $routeName === 'owner.settings.other-costs.store' => self::permissionName(self::PANEL_OWNER, 'other_costs', 'create'),
            $routeName === 'owner.settings.other-costs.update' => self::permissionName(self::PANEL_OWNER, 'other_costs', 'edit'),
            $routeName === 'owner.settings.other-costs.destroy' => self::permissionName(self::PANEL_OWNER, 'other_costs', 'delete'),
            $routeName === 'owner.settings.payments' => self::permissionName(self::PANEL_OWNER, 'payments', 'view'),
            $routeName === 'owner.settings.payments.store' => self::permissionName(self::PANEL_OWNER, 'payments', 'create'),
            $routeName === 'owner.settings.payments.update' => self::permissionName(self::PANEL_OWNER, 'payments', 'edit'),
            $routeName === 'owner.settings.payments.destroy' => self::permissionName(self::PANEL_OWNER, 'payments', 'delete'),
            $routeName === 'owner.settings.quote-rules' => self::permissionName(self::PANEL_OWNER, 'quote_rules', 'view'),
            $routeName === 'owner.settings.quote-rules.store' => self::permissionName(self::PANEL_OWNER, 'quote_rules', 'create'),
            $routeName === 'owner.settings.quote-rules.update' => self::permissionName(self::PANEL_OWNER, 'quote_rules', 'edit'),
            $routeName === 'owner.settings.quote-rules.destroy' => self::permissionName(self::PANEL_OWNER, 'quote_rules', 'delete'),
            $routeName === 'owner.settings.price-rules.index' => self::permissionName(self::PANEL_OWNER, 'price_rules', 'view'),
            $routeName === 'owner.settings.price-rules.store' => self::permissionName(self::PANEL_OWNER, 'price_rules', 'create'),
            $routeName === 'owner.settings.price-rules.update' => self::permissionName(self::PANEL_OWNER, 'price_rules', 'edit'),
            $routeName === 'owner.settings.price-rules.destroy' => self::permissionName(self::PANEL_OWNER, 'price_rules', 'delete'),
            default => null,
        };
    }
}
