<?php
namespace App\Controllers;

use App\Core\Database;

class AdminRbacMatrixController
{
    protected function db()
    {
        return Database::getInstance();
    }

    private function startSession(): void
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
    }

    private function role(): string
    {
        return (string)($_SESSION['conference_role'] ?? $_SESSION['role'] ?? $_SESSION['user_role'] ?? '');
    }

    private function requireSuperAdmin(): void
    {
        $this->startSession();

        if (empty($_SESSION['user_id'])) {
            header("Location: /easychair/login");
            exit;
        }

        if ($this->role() !== 'super_admin') {
            http_response_code(403);
            exit("Only super admin can manage RBAC matrix.");
        }

        if (empty($_SESSION['conference_id'])) {
            header("Location: /easychair/select-conference");
            exit;
        }
    }

    private function conference(): array
    {
        $stmt = $this->db()->prepare("
            SELECT c.*, o.name AS org_name
            FROM conferences c
            LEFT JOIN organizations o ON o.id=c.org_id
            WHERE c.id=?
            LIMIT 1
        ");
        $stmt->execute([(int)$_SESSION['conference_id']]);
        $c = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$c) {
            exit("Conference not found.");
        }

        return $c;
    }

    private function ensureDefaults(array $conference): void
    {
        $this->db()->prepare("
            INSERT IGNORE INTO rbac_role_menu_permissions
            (org_id, conference_id, role_id, menu_item_id, is_allowed)
            SELECT ?, ?, r.id, mi.id, 1
            FROM roles r
            JOIN rbac_menu_items mi ON mi.is_active=1
            WHERE r.code IN ('super_admin','org_admin','admin','organizer','conference_chair','track_chair')
        ")->execute([(int)$conference['org_id'], (int)$conference['id']]);

        $this->db()->prepare("
            INSERT IGNORE INTO rbac_role_action_permissions
            (org_id, conference_id, role_id, module_key, action_key, is_allowed)
            SELECT ?, ?, r.id, m.module_key, a.action_key, 1
            FROM roles r
            JOIN rbac_modules m ON m.is_active=1
            JOIN (
                SELECT 'view' action_key
                UNION ALL SELECT 'create'
                UNION ALL SELECT 'update'
                UNION ALL SELECT 'delete'
                UNION ALL SELECT 'approve'
                UNION ALL SELECT 'assign'
                UNION ALL SELECT 'export'
                UNION ALL SELECT 'send_email'
            ) a
            WHERE r.code IN ('super_admin','org_admin','admin','organizer','conference_chair','track_chair')
        ")->execute([(int)$conference['org_id'], (int)$conference['id']]);

        $this->db()->prepare("
            UPDATE rbac_role_menu_permissions p
            JOIN roles r ON r.id=p.role_id
            SET p.is_allowed=1
            WHERE p.conference_id=? AND r.code='super_admin'
        ")->execute([(int)$conference['id']]);

        $this->db()->prepare("
            UPDATE rbac_role_action_permissions p
            JOIN roles r ON r.id=p.role_id
            SET p.is_allowed=1
            WHERE p.conference_id=? AND r.code='super_admin'
        ")->execute([(int)$conference['id']]);
    }

    public function index()
    {
        $this->requireSuperAdmin();
        $conference = $this->conference();
        $this->ensureDefaults($conference);

        $stmt = $this->db()->query("
            SELECT *
            FROM roles
            WHERE code IN ('super_admin','org_admin','admin','organizer','conference_chair','track_chair')
            ORDER BY FIELD(code,'super_admin','org_admin','admin','conference_chair','track_chair','organizer'), id
        ");
        $roles = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $stmt = $this->db()->query("
            SELECT *
            FROM rbac_menu_items
            WHERE is_active=1
            ORDER BY sort_order, label
        ");
        $menuItems = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $stmt = $this->db()->query("
            SELECT *
            FROM rbac_modules
            WHERE is_active=1
            ORDER BY sort_order, module_label
        ");
        $modules = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $actions = ['view','create','update','delete','approve','assign','export','send_email'];

        $stmt = $this->db()->prepare("
            SELECT p.*, r.code AS role_code
            FROM rbac_role_menu_permissions p
            JOIN roles r ON r.id=p.role_id
            WHERE p.conference_id=?
        ");
        $stmt->execute([(int)$conference['id']]);
        $menuPermRows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $menuPerms = [];
        foreach ($menuPermRows as $p) {
            $menuPerms[(int)$p['role_id']][(int)$p['menu_item_id']] = (int)$p['is_allowed'];
        }

        $stmt = $this->db()->prepare("
            SELECT p.*, r.code AS role_code
            FROM rbac_role_action_permissions p
            JOIN roles r ON r.id=p.role_id
            WHERE p.conference_id=?
        ");
        $stmt->execute([(int)$conference['id']]);
        $actionPermRows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $actionPerms = [];
        foreach ($actionPermRows as $p) {
            $actionPerms[(int)$p['role_id']][$p['module_key']][$p['action_key']] = (int)$p['is_allowed'];
        }

        ob_start();
        require BASE_PATH . '/app/views/admin/rbac_matrix/index.php';
        $content = ob_get_clean();

        require BASE_PATH . '/app/views/layouts/admin_layout.php';
    }

    public function saveMenu()
    {
        $this->requireSuperAdmin();
        $conference = $this->conference();
        $this->ensureDefaults($conference);

        $posted = $_POST['menu'] ?? [];

        $stmt = $this->db()->prepare("
            SELECT p.id, p.role_id, p.menu_item_id, r.code AS role_code
            FROM rbac_role_menu_permissions p
            JOIN roles r ON r.id=p.role_id
            WHERE p.conference_id=?
        ");
        $stmt->execute([(int)$conference['id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $update = $this->db()->prepare("
            UPDATE rbac_role_menu_permissions
            SET is_allowed=?,
                updated_by=?,
                updated_at=NOW()
            WHERE id=?
        ");

        foreach ($rows as $row) {
            if ($row['role_code'] === 'super_admin') {
                $allowed = 1;
            } else {
                $allowed = !empty($posted[$row['role_id']][$row['menu_item_id']]) ? 1 : 0;
            }

            $update->execute([$allowed, (int)$_SESSION['user_id'], (int)$row['id']]);
        }

        $_SESSION['flash_success'] = 'Sidebar permissions saved.';
        header("Location: /easychair/admin/rbac-matrix#menu");
        exit;
    }

    public function saveActions()
    {
        $this->requireSuperAdmin();
        $conference = $this->conference();
        $this->ensureDefaults($conference);

        $posted = $_POST['actions'] ?? [];

        $stmt = $this->db()->prepare("
            SELECT p.id, p.role_id, p.module_key, p.action_key, r.code AS role_code
            FROM rbac_role_action_permissions p
            JOIN roles r ON r.id=p.role_id
            WHERE p.conference_id=?
        ");
        $stmt->execute([(int)$conference['id']]);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $update = $this->db()->prepare("
            UPDATE rbac_role_action_permissions
            SET is_allowed=?,
                updated_by=?,
                updated_at=NOW()
            WHERE id=?
        ");

        foreach ($rows as $row) {
            if ($row['role_code'] === 'super_admin') {
                $allowed = 1;
            } else {
                $allowed = !empty($posted[$row['role_id']][$row['module_key']][$row['action_key']]) ? 1 : 0;
            }

            $update->execute([$allowed, (int)$_SESSION['user_id'], (int)$row['id']]);
        }

        $_SESSION['flash_success'] = 'CRUD/action permissions saved.';
        header("Location: /easychair/admin/rbac-matrix#actions");
        exit;
    }
}
