<?php
namespace App\Core;

use App\Core\Database;
use App\Core\I18n;

class RbacService
{
    private \PDO $db;

    public function __construct()
    {
        $this->db = Database::getInstance();
    }

    public function roleCode(): string
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }

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

    public function roleId(?string $roleCode = null): int
    {
        $roleCode = $roleCode ?: $this->roleCode();

        if ($roleCode === '') {
            return 0;
        }

        $stmt = $this->db->prepare("SELECT id FROM roles WHERE code=? LIMIT 1");
        $stmt->execute([$roleCode]);
        return (int)$stmt->fetchColumn();
    }

    public function isSuperAdmin(): bool
    {
        return $this->roleCode() === 'superadmin';
    }

    public function canMenu(string $url, ?int $conferenceId = null, ?string $roleCode = null): bool
    {
        
        if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); }
        $role = (string)($_SESSION['conference_role'] ?? $_SESSION['role'] ?? $_SESSION['user_role'] ?? '');
        if ($url === '/easychair/admin/rbac-matrix' && $role !== 'superadmin') { return false; }
if ($this->isSuperAdmin()) {
            return true;
        }

        $roleId = $this->roleId($roleCode);
        if ($roleId <= 0) {
            return false;
        }

        if ($conferenceId === null) {
            $conferenceId = (int)($_SESSION['conference_id'] ?? 0);
        }

        if ($conferenceId <= 0) {
            return true;
        }

        $stmt = $this->db->prepare("
            SELECT COALESCE(p.is_allowed,1) AS is_allowed
            FROM rbac_menu_items mi
            LEFT JOIN rbac_role_menu_permissions p
                   ON p.menu_item_id=mi.id
                  AND p.role_id=?
                  AND p.conference_id=?
            WHERE mi.url=?
              AND mi.is_active=1
            LIMIT 1
        ");
        $stmt->execute([$roleId, $conferenceId, $url]);
        $val = $stmt->fetchColumn();

        if ($val === false) {
            return true; // unknown legacy links remain visible until registered
        }

        return (int)$val === 1;
    }

    public function canAction(string $moduleKey, string $actionKey, ?int $conferenceId = null, ?string $roleCode = null): bool
    {
        if ($this->isSuperAdmin()) {
            return true;
        }

        $roleId = $this->roleId($roleCode);
        if ($roleId <= 0) {
            return false;
        }

        if ($conferenceId === null) {
            $conferenceId = (int)($_SESSION['conference_id'] ?? 0);
        }

        if ($conferenceId <= 0) {
            return true;
        }

        $stmt = $this->db->prepare("
            SELECT COALESCE(is_allowed,1)
            FROM rbac_role_action_permissions
            WHERE role_id=?
              AND conference_id=?
              AND module_key=?
              AND action_key=?
            LIMIT 1
        ");
        $stmt->execute([$roleId, $conferenceId, $moduleKey, $actionKey]);
        $val = $stmt->fetchColumn();

        if ($val === false) {
            return true;
        }

        return (int)$val === 1;
    }

    public function requireAction(string $moduleKey, string $actionKey): void
    {
        if ($this->canAction($moduleKey, $actionKey)) {
            return;
        }

        http_response_code(403);
        exit("Access denied by RBAC: {$moduleKey}.{$actionKey}");
    }

    public function filterSidebarItems(array $items, ?int $conferenceId = null): array
    {
        $out = [];

        foreach ($items as $item) {
            $url = (string)($item['url'] ?? '');

            if ($url === '' || $this->canMenu($url, $conferenceId)) {
                if (!empty($item['i18n_key'])) {
                    $item['label'] = I18n::t((string)$item['i18n_key'], (string)($item['label'] ?? ''));
                }
                $out[] = $item;
            }
        }

        return $out;
    }
}
