<?php

use App\Core\Database;

if (!function_exists('ec_current_role')) {
    function ec_current_role(): string
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        return (string)($_SESSION['conference_role'] ?? $_SESSION['role'] ?? $_SESSION['user_role'] ?? '');
    }
}


if (!function_exists('ec_can_menu')) {
    function ec_can_menu(string $url): bool
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        $role = ec_current_role();

        if ($role === 'super_admin') {
            return true;
        }

        if ($url === '/easychair/admin/rbac-matrix') {
            return false;
        }

        try {
            $db = Database::getInstance();

            /*
             * Important:
             * There may be duplicated/legacy rbac_menu_items for similar labels.
             * We decide permission by URL, role code, org, conference.
             * Most specific conference/org row wins.
             */
            $stmt = $db->prepare("
                SELECT
                    rp.is_allowed,
                    COALESCE(rp.can_view, rp.is_allowed, 0) AS can_view,
                    rp.conference_id,
                    rp.org_id
                FROM rbac_menu_items mi
                JOIN rbac_role_menu_permissions rp ON rp.menu_item_id = mi.id
                JOIN roles r ON r.id = rp.role_id
                WHERE mi.url = ?
                  AND r.code = ?
                  AND (
                        rp.conference_id = ?
                        OR rp.conference_id IS NULL
                      )
                  AND (
                        rp.org_id = ?
                        OR rp.org_id IS NULL
                      )
                ORDER BY
                    CASE WHEN rp.conference_id = ? THEN 0 ELSE 1 END,
                    CASE WHEN rp.org_id = ? THEN 0 ELSE 1 END,
                    rp.id DESC
                LIMIT 1
            ");

            $confId = (int)($_SESSION['conference_id'] ?? 0);
            $orgId  = (int)($_SESSION['org_id'] ?? 0);

            $stmt->execute([
                $url,
                $role,
                $confId,
                $orgId,
                $confId,
                $orgId,
            ]);

            $row = $stmt->fetch(PDO::FETCH_ASSOC);

            /*
             * If no DB permission row exists, fallback to static role list in the menu partial.
             * If a row exists, it is authoritative.
             */
            if (!$row) {
                return true;
            }

            return !empty($row['is_allowed']) && !empty($row['can_view']);
        } catch (Throwable $e) {
            return $url !== '/easychair/admin/rbac-matrix';
        }
    }
}



if (!function_exists('ec_can_action')) {
    function ec_can_action(string $url, string $action = 'view'): bool
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

        $role = ec_current_role();

        if ($role === 'super_admin') {
            return true;
        }

        if ($url === '/easychair/admin/rbac-matrix') {
            return false;
        }

        $allowedActions = ['view', 'create', 'update', 'delete'];
        if (!in_array($action, $allowedActions, true)) {
            $action = 'view';
        }

        $column = 'can_' . $action;

        try {
            $db = Database::getInstance();

            $stmt = $db->prepare("
                SELECT
                    rp.is_allowed,
                    COALESCE(rp.can_view, rp.is_allowed, 0) AS can_view,
                    COALESCE(rp.can_create,0) AS can_create,
                    COALESCE(rp.can_update,0) AS can_update,
                    COALESCE(rp.can_delete,0) AS can_delete
                FROM rbac_menu_items mi
                JOIN rbac_role_menu_permissions rp ON rp.menu_item_id = mi.id
                JOIN roles r ON r.id = rp.role_id
                WHERE mi.url = ?
                  AND r.code = ?
                  AND (
                        rp.conference_id = ?
                        OR rp.conference_id IS NULL
                      )
                  AND (
                        rp.org_id = ?
                        OR rp.org_id IS NULL
                      )
                ORDER BY
                    CASE WHEN rp.conference_id = ? THEN 0 ELSE 1 END,
                    CASE WHEN rp.org_id = ? THEN 0 ELSE 1 END,
                    rp.id DESC
                LIMIT 1
            ");

            $confId = (int)($_SESSION['conference_id'] ?? 0);
            $orgId  = (int)($_SESSION['org_id'] ?? 0);

            $stmt->execute([
                $url,
                $role,
                $confId,
                $orgId,
                $confId,
                $orgId,
            ]);

            $row = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$row) {
                return true;
            }

            return !empty($row['is_allowed']) && !empty($row[$column]);
        } catch (Throwable $e) {
            return $action === 'view';
        }
    }
}


if (!function_exists('ec_require_action')) {
    function ec_require_action(string $url, string $action = 'view'): void
    {
        if (!ec_can_action($url, $action)) {
            http_response_code(403);
            exit(function_exists('ec_t') ? ec_t('msg.access_denied', 'Access denied.') : 'Access denied.');
        }
    }
}



if (!function_exists('ec_permission_debug_row')) {
    function ec_permission_debug_row(string $url, string $role, int $conferenceId, int $orgId): ?array
    {
        try {
            $db = \App\Core\Database::getInstance();
            $stmt = $db->prepare("
                SELECT
                    rp.id,
                    rp.org_id,
                    rp.conference_id,
                    r.code AS role_code,
                    mi.url,
                    mi.label,
                    rp.is_allowed,
                    rp.can_view,
                    rp.can_create,
                    rp.can_update,
                    rp.can_delete
                FROM rbac_menu_items mi
                JOIN rbac_role_menu_permissions rp ON rp.menu_item_id = mi.id
                JOIN roles r ON r.id = rp.role_id
                WHERE mi.url = ?
                  AND r.code = ?
                  AND (rp.conference_id = ? OR rp.conference_id IS NULL)
                  AND (rp.org_id = ? OR rp.org_id IS NULL)
                ORDER BY
                    CASE WHEN rp.conference_id = ? THEN 0 ELSE 1 END,
                    CASE WHEN rp.org_id = ? THEN 0 ELSE 1 END,
                    rp.id DESC
                LIMIT 1
            ");
            $stmt->execute([$url, $role, $conferenceId, $orgId, $conferenceId, $orgId]);
            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $row ?: null;
        } catch (\Throwable $e) {
            return ['error' => $e->getMessage()];
        }
    }
}




if (!function_exists('ec_admin_url_from_request')) {
    function ec_admin_url_from_request(): string
    {
        $path = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '';
        if ($path === '') {
            return '';
        }

        // Normalize /easychair/admin/x/save or /delete to base menu URL.
        $path = preg_replace('#/(save|delete|send|copy|heal|test)$#', '', $path);
        $path = preg_replace('#/(save|delete|send|copy|heal|test)\?.*$#', '', $path);

        return $path;
    }
}

if (!function_exists('ec_admin_require_url_action')) {
    function ec_admin_require_url_action(string $url, string $action = 'view'): void
    {
        if (!function_exists('ec_can_action')) {
            return;
        }

        if (!ec_can_action($url, $action)) {
            http_response_code(403);
            exit(function_exists('ec_t') ? ec_t('msg.access_denied', 'Access denied.') : 'Access denied.');
        }
    }
}

if (!function_exists('ec_admin_can_url_action')) {
    function ec_admin_can_url_action(string $url, string $action = 'view'): bool
    {
        if (!function_exists('ec_can_action')) {
            return true;
        }

        return ec_can_action($url, $action);
    }
}

