<?php

declare(strict_types=1);

namespace App\Core;

use App\Shared\Security\PermissionCatalog;
use PDO;

final class Authorization
{
    /** @var array<string,bool> */
    private static array $permissionDecisionCache = [];

    private static function expandedCandidates(string $permissionCode): array
    {
        return PermissionCatalog::expand($permissionCode);
    }

    public static function can(string $permissionCode): bool
    {
        $uid = Auth::id() ?? 0;
        if ($uid <= 0) {
            return false;
        }

        $permissionCode = trim($permissionCode);
        $cacheKey = $uid . '|' . $permissionCode;
        if (array_key_exists($cacheKey, self::$permissionDecisionCache)) {
            return self::$permissionDecisionCache[$cacheKey];
        }

        $pdo = db();
        if (!rbac_enabled($pdo)) {
            return self::$permissionDecisionCache[$cacheKey] = true;
        }

        // Keep permission catalog and the default admin role in sync with deployed modules.
        // Seed only once per permission-catalog version instead of on every can() call.
        ensure_permissions_seed($pdo);

        $roles = current_user_roles($pdo);
        foreach ($roles as $role) {
            $roleId = (int) ($role['id'] ?? 0);
            $roleName = mb_strtolower(trim((string) ($role['name'] ?? '')));
            if ($roleId === 1 || in_array($roleName, ['administrator', 'admin', 'مدير النظام'], true)) {
                return self::$permissionDecisionCache[$cacheKey] = true;
            }
        }

        $perms = current_user_permissions($pdo);
        foreach (self::expandedCandidates($permissionCode) as $candidate) {
            if (!empty($perms[$candidate])) {
                return self::$permissionDecisionCache[$cacheKey] = true;
            }
        }
        return self::$permissionDecisionCache[$cacheKey] = false;
    }

    public static function requirePermission(string $permissionCode, ?string $message = null): void
    {
        if (self::can($permissionCode)) {
            return;
        }

        http_response_code(403);
        view('pages/dashboard', [
            'error' => $message ?: 'ليس لديك صلاحية لتنفيذ هذا الإجراء.'
        ]);
        exit;
    }

    public static function canManageParties(): bool
    {
        return self::can('parties.edit') || self::can('customers.edit') || self::can('suppliers.edit') || self::can('parties.create');
    }

    public static function canViewParties(): bool
    {
        return self::can('parties.view') || self::can('customers.view') || self::can('suppliers.view');
    }

    public static function requireViewParties(): void
    {
        self::requirePermission('parties.view', 'ليس لديك صلاحية لعرض الأطراف.');
    }
}
