<?php
declare(strict_types=1);

if (session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}

require_once __DIR__ . '/../db.php';

if (!function_exists('permissions_pdo')) {
    function permissions_pdo(): PDO
    {
        $pdo = db();
        if (!$pdo instanceof PDO) {
            throw new RuntimeException('DB not ready');
        }

        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

        return $pdo;
    }
}

if (!function_exists('permissions_table_exists')) {
    function permissions_table_exists(?PDO $pdo = null): bool
    {
        try {
            $pdo ??= permissions_pdo();
            $st = $pdo->query("SHOW TABLES LIKE 'employee_permissions'");
            return (bool)$st->fetchColumn();
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('current_page_key')) {
    function current_page_key(): string
    {
        $script = str_replace('\\', '/', $_SERVER['SCRIPT_NAME'] ?? '');
        $dir = trim(dirname($script), '/\\.');
        $file = basename($script);

        if ($file === '' || $file === '.' || $file === '/') {
            return '';
        }

        if ($dir === '' || $dir === '.') {
            return $file;
        }

        $parts = explode('/', $dir);
        $lastDir = end($parts);

        if (!$lastDir || $lastDir === '.' || $lastDir === '..') {
            return $file;
        }

        return $lastDir . '/' . $file;
    }
}

if (!function_exists('permission_map')) {
    function permission_map(): array
    {
        return [
            // المالية - رواتب
            'finance/payroll.php'        => ['finance_access', 'payroll_page'],
            'finance/advances.php'       => ['finance_access', 'advances_page'],
            'finance/bonuses.php'        => ['finance_access', 'bonuses_page'],
            'finance/deductions.php'     => ['finance_access', 'deductions_page'],

            // الإدارة المالية
            'financial/dashboard.php'    => ['financial_access', 'financial_dashboard_page'],
            'financial/income.php'       => ['financial_access', 'financial_income_page'],
            'financial/expenses.php'     => ['financial_access', 'financial_expenses_page'],
            'financial/reports.php'      => ['financial_access', 'financial_reports_page'],
            'financial/half_yearly.php'  => ['financial_access', 'financial_half_yearly_page'],
            'financial/yearly.php'       => ['financial_access', 'financial_yearly_page'],

            // الموارد البشرية
            'employees.php'              => ['hr_access', 'employees_page'],
            'hr_attendance.php'          => ['HLG-Justice-Hub_access', 'hr_attendance.php_page'],
            'hr_leaves.php'              => ['hr_access', 'leaves_page'],
            'hr_employee_form.php'       => ['hr_access', 'employee_form_page'],

            // القضايا
            'cases.php'                  => ['cases_access', 'cases_page'],
            'case_details.php'           => ['cases_access', 'case_details_page'],
            'case_documents.php'         => ['cases_access', 'case_documents_page'],

            // العملاء
            'clients.php'                => ['clients_access', 'clients_page'],

            // الذكاء القانوني
            'ai/index.php'               => ['ai_access', 'ai_page'],
            'ai/chat.php'                => ['ai_access', 'ai_chat_page'],

            // المكتبة القانونية
            'library.php'                => ['library_access', 'library_page'],

            // الإعدادات
            'settings.php'               => ['settings_access', 'settings_page'],

            // إدارة الصلاحيات
            'permissions_manage.php'     => ['permissions_access', 'permissions_page'],
        ];
    }
}

if (!function_exists('permissions_current_user_id')) {
    function permissions_current_user_id(): int
    {
        return (int)($_SESSION['user_id'] ?? 0);
    }
}

if (!function_exists('permissions_current_role')) {
    function permissions_current_role(): string
    {
        return strtoupper((string)($_SESSION['role'] ?? 'STAFF'));
    }
}

if (!function_exists('permissions_is_owner')) {
    function permissions_is_owner(): bool
    {
        return permissions_current_role() === 'OWNER';
    }
}

if (!function_exists('permissions_is_admin')) {
    function permissions_is_admin(): bool
    {
        return permissions_current_role() === 'ADMIN';
    }
}

if (!function_exists('has_permission')) {
    function has_permission(string $code, ?int $userId = null, ?PDO $pdo = null): bool
    {
        try {
            $pdo ??= permissions_pdo();

            $userId ??= permissions_current_user_id();
            if ($userId <= 0 || $code === '') {
                return false;
            }

            if ($userId === permissions_current_user_id() && permissions_is_owner()) {
                return true;
            }

            if (!permissions_table_exists($pdo)) {
                return false;
            }

            $st = $pdo->prepare("
                SELECT 1
                FROM employee_permissions
                WHERE user_id = ?
                  AND permission_code = ?
                LIMIT 1
            ");
            $st->execute([$userId, $code]);

            return (bool)$st->fetchColumn();
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('has_any_permission')) {
    function has_any_permission(array $codes, ?int $userId = null, ?PDO $pdo = null): bool
    {
        foreach ($codes as $code) {
            if (has_permission((string)$code, $userId, $pdo)) {
                return true;
            }
        }
        return false;
    }
}

if (!function_exists('has_all_permissions')) {
    function has_all_permissions(array $codes, ?int $userId = null, ?PDO $pdo = null): bool
    {
        foreach ($codes as $code) {
            if (!has_permission((string)$code, $userId, $pdo)) {
                return false;
            }
        }
        return true;
    }
}

if (!function_exists('has_current_section_access')) {
    function has_current_section_access(?PDO $pdo = null): bool
    {
        $key = current_page_key();
        if ($key === '') {
            return false;
        }

        $map = permission_map();
        if (!isset($map[$key])) {
            return false;
        }

        $codes = $map[$key];
        if (!is_array($codes)) {
            $codes = [$codes];
        }

        return has_any_permission($codes, null, $pdo);
    }
}

if (!function_exists('get_current_page_permissions')) {
    function get_current_page_permissions(): array
    {
        $key = current_page_key();
        if ($key === '') {
            return [];
        }

        $map = permission_map();
        if (!isset($map[$key])) {
            return [];
        }

        $codes = $map[$key];
        return is_array($codes) ? array_values($codes) : [(string)$codes];
    }
}

if (!function_exists('get_user_permissions')) {
    function get_user_permissions(?int $userId = null, ?PDO $pdo = null): array
    {
        try {
            $pdo ??= permissions_pdo();

            $userId ??= permissions_current_user_id();
            if ($userId <= 0) {
                return [];
            }

            if ($userId === permissions_current_user_id() && permissions_is_owner()) {
                return ['*'];
            }

            if (!permissions_table_exists($pdo)) {
                return [];
            }

            $st = $pdo->prepare("
                SELECT permission_code
                FROM employee_permissions
                WHERE user_id = ?
                ORDER BY permission_code ASC
            ");
            $st->execute([$userId]);

            return array_map('strval', $st->fetchAll(PDO::FETCH_COLUMN));
        } catch (Throwable $e) {
            return [];
        }
    }
}

if (!function_exists('grant_permission')) {
    function grant_permission(int $userId, string $code, ?PDO $pdo = null): bool
    {
        try {
            $pdo ??= permissions_pdo();

            if ($userId <= 0 || $code === '') {
                return false;
            }

            if (!permissions_table_exists($pdo)) {
                return false;
            }

            $st = $pdo->prepare("
                INSERT IGNORE INTO employee_permissions (user_id, permission_code)
                VALUES (?, ?)
            ");

            return $st->execute([$userId, $code]);
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('revoke_permission')) {
    function revoke_permission(int $userId, string $code, ?PDO $pdo = null): bool
    {
        try {
            $pdo ??= permissions_pdo();

            if ($userId <= 0 || $code === '') {
                return false;
            }

            if (!permissions_table_exists($pdo)) {
                return false;
            }

            $st = $pdo->prepare("
                DELETE FROM employee_permissions
                WHERE user_id = ?
                  AND permission_code = ?
            ");

            return $st->execute([$userId, $code]);
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('replace_user_permissions')) {
    function replace_user_permissions(int $userId, array $codes, ?PDO $pdo = null): bool
    {
        try {
            $pdo ??= permissions_pdo();

            if ($userId <= 0) {
                return false;
            }

            if (!permissions_table_exists($pdo)) {
                return false;
            }

            $codes = array_values(array_unique(array_filter(array_map('strval', $codes))));

            $pdo->beginTransaction();

            $del = $pdo->prepare("DELETE FROM employee_permissions WHERE user_id = ?");
            $del->execute([$userId]);

            if (!empty($codes)) {
                $ins = $pdo->prepare("
                    INSERT INTO employee_permissions (user_id, permission_code)
                    VALUES (?, ?)
                ");
                foreach ($codes as $code) {
                    $ins->execute([$userId, $code]);
                }
            }

            $pdo->commit();
            return true;
        } catch (Throwable $e) {
            if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
                $pdo->rollBack();
            }
            return false;
        }
    }
}

if (!function_exists('require_permission')) {
    function require_permission(string $code, ?PDO $pdo = null, ?string $message = null): void
    {
        if (has_permission($code, null, $pdo)) {
            return;
        }

        http_response_code(403);
        exit($message ?: 'غير مصرح');
    }
}

if (!function_exists('require_any_permission')) {
    function require_any_permission(array $codes, ?PDO $pdo = null, ?string $message = null): void
    {
        if (has_any_permission($codes, null, $pdo)) {
            return;
        }

        http_response_code(403);
        exit($message ?: 'غير مصرح');
    }
}

if (!function_exists('require_current_page_permission')) {
    function require_current_page_permission(?PDO $pdo = null, ?string $message = null): void
    {
        $codes = get_current_page_permissions();
        if (!$codes) {
            http_response_code(403);
            exit($message ?: 'غير مصرح');
        }

        if (has_any_permission($codes, null, $pdo)) {
            return;
        }

        http_response_code(403);
        exit($message ?: 'غير مصرح');
    }
}