<?php
declare(strict_types=1);

namespace App\Modules\AccessMatrix\Controllers;

use App\Core\App;
use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Modules\AccessMatrix\Services\MatrixService;
use App\Modules\AccessMatrix\Services\PermissionDiscoveryService;

final class AccessMatrixController extends Controller
{
    public function index(Request $request): Response
    {
        $matrixData = MatrixService::buildMatrix();

        return $this->view('AccessMatrix.Views.index', [
            'roles'  => $matrixData['roles'],
            'matrix' => $matrixData['matrix'],
        ]);
    }

    public function compare(Request $request): Response
    {
        $db = App::getInstance()->db();
        $roles = $db->select("SELECT id, role_code, name_ar FROM roles WHERE is_active = 1 ORDER BY name_ar");

        $roleA = (int) ($request->get('role_a') ?? 0);
        $roleB = (int) ($request->get('role_b') ?? 0);
        $comparison = null;
        $roleAData = null;
        $roleBData = null;

        if ($roleA && $roleB) {
            $comparison = MatrixService::compareRoles($roleA, $roleB);
            $roleAData = $db->selectOne("SELECT id, role_code, name_ar FROM roles WHERE id = ?", [$roleA]);
            $roleBData = $db->selectOne("SELECT id, role_code, name_ar FROM roles WHERE id = ?", [$roleB]);
        }

        return $this->view('AccessMatrix.Views.compare', [
            'roles'      => $roles,
            'roleA'      => $roleA,
            'roleB'      => $roleB,
            'roleAData'  => $roleAData,
            'roleBData'  => $roleBData,
            'comparison' => $comparison,
        ]);
    }

    public function toggle(Request $request): Response
    {
        $this->authorize('access_matrix.manage');

        $roleId = (int) ($request->post('role_id') ?? 0);
        $permissionKey = $request->post('permission_key') ?? '';

        if (!$roleId || !$permissionKey) {
            return $this->json(['error' => 'بيانات غير صالحة'], 400);
        }

        $db = App::getInstance()->db();

        $role = $db->selectOne("SELECT id, is_system FROM roles WHERE id = ?", [$roleId]);
        if (!$role) {
            return $this->json(['error' => 'الدور غير موجود'], 404);
        }

        $existing = $db->selectOne(
            "SELECT id FROM role_permissions WHERE role_id = ? AND permission_key = ?",
            [$roleId, $permissionKey]
        );

        if ($existing) {
            $db->delete('role_permissions', '`id` = ?', [(int) $existing['id']]);
            $granted = false;
        } else {
            $db->insert('role_permissions', [
                'role_id'        => $roleId,
                'permission_key' => $permissionKey,
                'granted_at'     => date('Y-m-d H:i:s'),
                'granted_by'     => (int) App::getInstance()->currentEmployee()->id,
            ]);
            $granted = true;
        }

        return $this->json(['granted' => $granted, 'role_id' => $roleId, 'permission' => $permissionKey]);
    }

    public function export(Request $request): Response
    {
        $matrixData = MatrixService::buildMatrix();
        $csv = MatrixService::exportCsv($matrixData);

        $filename = 'access_matrix_' . date('Y-m-d_His') . '.csv';

        return (new Response())
            ->header('Content-Type', 'text/csv; charset=utf-8')
            ->header('Content-Disposition', 'attachment; filename="' . $filename . '"')
            ->html($csv);
    }

    public function clone(Request $request): Response
    {
        $this->authorize('access_matrix.manage');

        $sourceId = (int) ($request->post('source_role_id') ?? 0);
        $newCode = trim($request->post('new_code') ?? '');
        $nameAr = trim($request->post('name_ar') ?? '');

        if (!$sourceId || !$newCode || !$nameAr) {
            return $this->redirect('/access-matrix')->withError('يرجى ملء جميع الحقول المطلوبة');
        }

        $db = App::getInstance()->db();
        $existingCode = $db->selectOne("SELECT 1 FROM roles WHERE role_code = ?", [$newCode]);
        if ($existingCode) {
            return $this->redirect('/access-matrix')->withError('كود الدور موجود مسبقاً');
        }

        try {
            MatrixService::cloneRole($sourceId, $newCode, $nameAr);
            return $this->redirect('/access-matrix')->withSuccess('تم نسخ الدور بنجاح');
        } catch (\Throwable $e) {
            return $this->redirect('/access-matrix')->withError('خطأ: ' . $e->getMessage());
        }
    }

    public function health(Request $request): Response
    {
        $orphans = PermissionDiscoveryService::findOrphanPermissions();
        $unprotected = PermissionDiscoveryService::findUnprotectedRoutes();
        $stats = PermissionDiscoveryService::getPermissionStats();

        $db = App::getInstance()->db();
        $roles = $db->select("SELECT id, role_code, name_ar FROM roles WHERE is_active = 1 ORDER BY name_ar");

        $violations = [];
        foreach ($roles as $role) {
            $v = PermissionDiscoveryService::validateRoleDependencies((int) $role['id']);
            if (!empty($v)) {
                $violations[$role['name_ar']] = $v;
            }
        }

        return $this->view('AccessMatrix.Views.health', [
            'orphans'     => $orphans,
            'unprotected' => $unprotected,
            'stats'       => $stats,
            'violations'  => $violations,
        ]);
    }
}
