<?php
class RolesController {
    public function index(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('roles.manage');

        $tid = Auth::tenantId();
        $roles = Role::findByTenant($tid);

        // Get user count for each role
        foreach ($roles as &$role) {
            $stmt = db()->prepare("SELECT COUNT(*) FROM users WHERE role_id=?");
            $stmt->execute([$role['id']]);
            $role['user_count'] = $stmt->fetchColumn();
        }
        unset($role); // Prevent reference leaks to the view

        $pageTitle = 'Roles & Permissions';
        ob_start();
        include APP_ROOT . '/views/tenant/roles/index.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function create(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('roles.manage');

        $permissions = Permission::getGroupedByCategory();
        $pageTitle = 'Create New Role';
        ob_start();
        include APP_ROOT . '/views/tenant/roles/create.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function store(): void {
        Auth::requireLogin();
        Security::checkCsrf();
        Auth::requirePermission('roles.manage');

        $data = [
            'tenant_id' => Auth::tenantId(),
            'name' => Security::sanitize($_POST['name']),
            'description' => Security::sanitize($_POST['description'] ?? ''),
            'is_system' => 0
        ];

        // Validate role name
        if (empty($data['name'])) {
            flash('error', 'Role name is required.');
            redirectBack();
        }

        // Check if role name already exists for this tenant
        $stmt = db()->prepare("SELECT id FROM roles WHERE tenant_id=? AND name=?");
        $stmt->execute([$data['tenant_id'], $data['name']]);
        if ($stmt->fetch()) {
            flash('error', 'A role with this name already exists.');
            redirectBack();
        }

        // Create role
        $cols = implode(',', array_map(fn($k) => "`$k`", array_keys($data)));
        $vals = implode(',', array_fill(0, count($data), '?'));
        db()->prepare("INSERT INTO roles ($cols) VALUES ($vals)")->execute(array_values($data));
        $roleId = (int)db()->lastInsertId();

        // Assign permissions if selected
        if (!empty($_POST['permissions'])) {
            Role::syncPermissions($roleId, $_POST['permissions']);
        }

        flash('success', 'Role created successfully.');
        redirect('roles');
    }

    public function edit(string $id): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('roles.manage');

        $tid = Auth::tenantId();
        $role = Role::findById((int)$id, $tid);

        if (!$role) {
            flash('error', 'Role not found.');
            redirect('roles');
        }

        $permissions = Permission::getGroupedByCategory();
        $rolePermissions = Role::getPermissions($role['id']);
        $rolePermissionIds = array_column($rolePermissions, 'id');

        $pageTitle = 'Edit Role: ' . e($role['name']);
        ob_start();
        include APP_ROOT . '/views/tenant/roles/edit.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function update(string $id): void {
        Auth::requireLogin();
        Security::checkCsrf();
        Auth::requirePermission('roles.manage');

        $tid = Auth::tenantId();
        $role = Role::findById((int)$id, $tid);

        if (!$role) {
            flash('error', 'Role not found.');
            redirect('roles');
        }

        $data = [
            'name' => Security::sanitize($_POST['name']),
            'description' => Security::sanitize($_POST['description'] ?? '')
        ];

        // Validate role name
        if (empty($data['name'])) {
            flash('error', 'Role name is required.');
            redirectBack();
        }

        // Check if role name already exists for this tenant (excluding current role)
        $stmt = db()->prepare("SELECT id FROM roles WHERE tenant_id=? AND name=? AND id!=?");
        $stmt->execute([$tid, $data['name'], (int)$id]);
        if ($stmt->fetch()) {
            flash('error', 'A role with this name already exists.');
            redirectBack();
        }

        // Update role
        $updates = implode(',', array_map(fn($k) => "`$k`=?", array_keys($data)));
        $stmt = db()->prepare("UPDATE roles SET $updates WHERE id=? AND tenant_id=?");
        $stmt->execute([...array_values($data), (int)$id, $tid]);

        // Sync permissions
        $permissionIds = $_POST['permissions'] ?? [];
        Role::syncPermissions((int)$id, $permissionIds);

        flash('success', 'Role updated successfully.');
        redirect('roles');
    }

    public function delete(string $id): void {
        Auth::requireLogin();
        Security::checkCsrf();
        Auth::requireRole(['admin','owner']);

        $tid = Auth::tenantId();
        $role = Role::findById((int)$id, $tid);

        if (!$role) {
            flash('error', 'Role not found.');
            redirect('roles');
        }

        // Check if role has users
        $stmt = db()->prepare("SELECT COUNT(*) FROM users WHERE role_id=?");
        $stmt->execute([(int)$id]);
        if ($stmt->fetchColumn() > 0) {
            flash('error', 'Cannot delete role that has assigned users. Please reassign users first.');
            redirect('roles');
        }

        // Delete role (cascade will handle role_permissions)
        $stmt = db()->prepare("DELETE FROM roles WHERE id=? AND tenant_id=?");
        $stmt->execute([(int)$id, $tid]);

        flash('success', 'Role deleted successfully.');
        redirect('roles');
    }
}
