<?php
/**
 * NIS2 Agile - Audit Controller
 *
 * Controlli compliance, evidenze, audit logs, mapping ISO 27001.
 */

require_once __DIR__ . '/BaseController.php';
require_once APP_PATH . '/services/ReportService.php';

class AuditController extends BaseController
{
    public function listControls(): void
    {
        $this->requireOrgAccess();

        $controls = Database::fetchAll(
            'SELECT cc.*, u.full_name as responsible_name
             FROM compliance_controls cc
             LEFT JOIN users u ON u.id = cc.responsible_user_id
             WHERE cc.organization_id = ?
             ORDER BY cc.control_code',
            [$this->getCurrentOrgId()]
        );

        $this->jsonSuccess($controls);
    }

    public function updateControl(int $id): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'auditor']);

        $updates = [];
        foreach (['status', 'implementation_percentage', 'evidence_description', 'responsible_user_id', 'next_review_date'] as $field) {
            if ($this->hasParam($field)) {
                $updates[$field] = $this->getParam($field);
            }
        }

        if (isset($updates['status']) && $updates['status'] === 'verified') {
            $updates['last_verified_at'] = date('Y-m-d H:i:s');
        }

        if (!empty($updates)) {
            Database::update('compliance_controls', $updates, 'id = ? AND organization_id = ?', [$id, $this->getCurrentOrgId()]);
            $this->logAudit('control_updated', 'compliance_control', $id, $updates);
        }

        $this->jsonSuccess($updates, 'Controllo aggiornato');
    }

    public function uploadEvidence(): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'auditor']);

        if (!isset($_FILES['file'])) {
            $this->jsonError('File non fornito', 400, 'NO_FILE');
        }

        $file = $_FILES['file'];
        $maxSize = 10 * 1024 * 1024; // 10MB

        if ($file['size'] > $maxSize) {
            $this->jsonError('File troppo grande (max 10MB)', 400, 'FILE_TOO_LARGE');
        }

        $orgId = $this->getCurrentOrgId();
        $uploadDir = UPLOAD_PATH . "/evidence/{$orgId}";

        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $filename = uniqid('ev_') . '.' . $ext;
        $filePath = $uploadDir . '/' . $filename;

        if (!move_uploaded_file($file['tmp_name'], $filePath)) {
            $this->jsonError('Errore caricamento file', 500, 'UPLOAD_ERROR');
        }

        $evidenceId = Database::insert('evidence_files', [
            'organization_id' => $orgId,
            'control_id'      => $this->getParam('control_id'),
            'entity_type'     => $this->getParam('entity_type'),
            'entity_id'       => $this->getParam('entity_id'),
            'file_name'       => $file['name'],
            'file_path'       => "evidence/{$orgId}/{$filename}",
            'file_size'       => $file['size'],
            'mime_type'       => $file['type'],
            'uploaded_by'     => $this->getCurrentUserId(),
        ]);

        $this->logAudit('evidence_uploaded', 'evidence', $evidenceId);
        $this->jsonSuccess(['id' => $evidenceId], 'Evidenza caricata', 201);
    }

    public function listEvidence(): void
    {
        $this->requireOrgAccess();

        $where = 'organization_id = ?';
        $params = [$this->getCurrentOrgId()];

        if ($this->hasParam('control_id')) {
            $where .= ' AND control_id = ?';
            $params[] = $this->getParam('control_id');
        }
        if ($this->hasParam('entity_type') && $this->hasParam('entity_id')) {
            $where .= ' AND entity_type = ? AND entity_id = ?';
            $params[] = $this->getParam('entity_type');
            $params[] = $this->getParam('entity_id');
        }

        $evidence = Database::fetchAll(
            "SELECT ef.*, u.full_name as uploaded_by_name
             FROM evidence_files ef
             LEFT JOIN users u ON u.id = ef.uploaded_by
             WHERE ef.{$where}
             ORDER BY ef.created_at DESC",
            $params
        );

        $this->jsonSuccess($evidence);
    }

    public function generateReport(): void
    {
        $this->requireOrgAccess();
        $orgId = $this->getCurrentOrgId();

        $org = Database::fetchOne('SELECT * FROM organizations WHERE id = ?', [$orgId]);
        $controls = Database::fetchAll('SELECT * FROM compliance_controls WHERE organization_id = ? ORDER BY control_code', [$orgId]);
        $lastAssessment = Database::fetchOne('SELECT * FROM assessments WHERE organization_id = ? AND status = "completed" ORDER BY completed_at DESC LIMIT 1', [$orgId]);
        $riskCount = Database::count('risks', 'organization_id = ? AND status != "closed"', [$orgId]);
        $incidentCount = Database::count('incidents', 'organization_id = ?', [$orgId]);
        $policyCount = Database::count('policies', 'organization_id = ? AND status IN ("approved","published")', [$orgId]);

        $totalControls = count($controls);
        $implemented = count(array_filter($controls, fn($c) => in_array($c['status'], ['implemented', 'verified'])));

        $this->jsonSuccess([
            'organization'       => $org,
            'report_date'        => date('Y-m-d H:i:s'),
            'compliance_summary' => [
                'total_controls'       => $totalControls,
                'implemented_controls' => $implemented,
                'compliance_percentage' => $totalControls > 0 ? round($implemented / $totalControls * 100) : 0,
            ],
            'controls'           => $controls,
            'last_assessment'    => $lastAssessment,
            'risk_count'         => $riskCount,
            'incident_count'     => $incidentCount,
            'policy_count'       => $policyCount,
        ]);
    }

    public function getAuditLogs(): void
    {
        $this->requireOrgRole(['org_admin', 'auditor']);
        $pagination = $this->getPagination(50);

        $total = Database::count('audit_logs', 'organization_id = ?', [$this->getCurrentOrgId()]);

        $logs = Database::fetchAll(
            "SELECT al.*, u.full_name
             FROM audit_logs al
             LEFT JOIN users u ON u.id = al.user_id
             WHERE al.organization_id = ?
             ORDER BY al.created_at DESC
             LIMIT {$pagination['per_page']} OFFSET {$pagination['offset']}",
            [$this->getCurrentOrgId()]
        );

        $this->jsonPaginated($logs, $total, $pagination['page'], $pagination['per_page']);
    }

    public function getIsoMapping(): void
    {
        $this->requireOrgAccess();

        $mapping = [
            ['nis2' => '21.2.a', 'iso27001' => 'A.5.1, A.5.2, A.8.1, A.8.2', 'title' => 'Risk analysis and security policies'],
            ['nis2' => '21.2.b', 'iso27001' => 'A.5.24, A.5.25, A.5.26, A.6.8', 'title' => 'Incident handling'],
            ['nis2' => '21.2.c', 'iso27001' => 'A.5.29, A.5.30', 'title' => 'Business continuity'],
            ['nis2' => '21.2.d', 'iso27001' => 'A.5.19, A.5.20, A.5.21, A.5.22', 'title' => 'Supply chain security'],
            ['nis2' => '21.2.e', 'iso27001' => 'A.8.25, A.8.26, A.8.27, A.8.28', 'title' => 'System acquisition and development'],
            ['nis2' => '21.2.f', 'iso27001' => 'A.5.35, A.5.36', 'title' => 'Effectiveness assessment'],
            ['nis2' => '21.2.g', 'iso27001' => 'A.6.3, A.6.6', 'title' => 'Cyber hygiene and training'],
            ['nis2' => '21.2.h', 'iso27001' => 'A.8.24', 'title' => 'Cryptography and encryption'],
            ['nis2' => '21.2.i', 'iso27001' => 'A.5.15, A.5.16, A.5.17, A.5.18, A.6.1, A.6.2', 'title' => 'HR security, access control, asset management'],
            ['nis2' => '21.2.j', 'iso27001' => 'A.8.5', 'title' => 'Multi-factor authentication'],
        ];

        $this->jsonSuccess($mapping);
    }

    /**
     * GET /api/audit/nistCsfMapping
     * Layer di mapping NIST CSF 2.0 (43 controlli) -> NIS2 Art.21 / D.Lgs.138/2024 -> modulo piattaforma.
     * Reference-only (nessuna persistenza): arricchisce l'assessment Art.21 con i codici controllo
     * NIST CSF 2.0 usati come standard de-facto. Fonte mapping: NIST CSF 2.0 + Direttiva (UE) 2022/2555.
     */
    public function getNistCsfMapping(): void
    {
        $this->requireOrgAccess();

        // [code, function, nis2, module]
        $rows = [
            // GOVERN
            ['GV.OC-04', 'Govern', '21.1', 'Asset - Sistemi rilevanti (GV.OC-04)'],
            ['GV.RM-03', 'Govern', '21.2.a', 'Risk Management'],
            ['GV.RR-02', 'Govern', '20',     'Organizzazione - Ruoli e responsabilita'],
            ['GV.RR-04', 'Govern', '20',     'Organizzazione - Risorse cybersecurity'],
            ['GV.PO-01', 'Govern', '21.2.a', 'Policy - Politica di sicurezza'],
            ['GV.PO-02', 'Govern', '21.2.a', 'Policy - Revisione politiche'],
            ['GV.SC-01', 'Govern', '21.2.d', 'Supply Chain - Strategia'],
            ['GV.SC-02', 'Govern', '21.2.d', 'Supply Chain - Ruoli fornitori'],
            ['GV.SC-04', 'Govern', '21.2.d', 'Supply Chain - Valutazione fornitori'],
            ['GV.SC-05', 'Govern', '21.2.d', 'Supply Chain - Requisiti contrattuali'],
            ['GV.SC-07', 'Govern', '21.2.d', 'Supply Chain - Monitoraggio rischio fornitori'],
            // IDENTIFY
            ['ID.AM-01', 'Identify', '21.2.i', 'Asset - Inventario hardware'],
            ['ID.AM-02', 'Identify', '21.2.i', 'Asset - Inventario software'],
            ['ID.AM-03', 'Identify', '21.2.i', 'Asset - Diagrammi flussi/rete (essenziali)'],
            ['ID.AM-04', 'Identify', '21.2.i', 'Asset - Catalogo servizi'],
            ['ID.RA-01', 'Identify', '21.2.a', 'Risk Management - Vulnerabilita'],
            ['ID.RA-05', 'Identify', '21.2.a', 'Risk Management - Valutazione rischio'],
            ['ID.RA-06', 'Identify', '21.2.a', 'Risk Management - Trattamento rischio'],
            ['ID.RA-08', 'Identify', '21.2.e', 'Risk Management - Gestione vulnerabilita/disclosure'],
            ['ID.IM-01', 'Identify', '21.2.f', 'Audit - Miglioramento da valutazioni'],
            ['ID.IM-04', 'Identify', '21.2.c', 'Incidenti - Piani BC/DR e test'],
            // PROTECT
            ['PR.AA-01', 'Protect', '21.2.i', 'Asset/Access - Gestione identita'],
            ['PR.AA-03', 'Protect', '21.2.i', 'Access - Autenticazione'],
            ['PR.AA-05', 'Protect', '21.2.i', 'Access - Privilegi e accessi'],
            ['PR.AA-06', 'Protect', '21.2.i', 'Access - Accesso fisico'],
            ['PR.AT-01', 'Protect', '21.2.g', 'Training - Awareness'],
            ['PR.AT-02', 'Protect', '21.2.g', 'Training - Ruoli privilegiati'],
            ['PR.DS-01', 'Protect', '21.2.h', 'Policy - Protezione dati a riposo'],
            ['PR.DS-02', 'Protect', '21.2.h', 'Policy - Protezione dati in transito'],
            ['PR.DS-11', 'Protect', '21.2.c', 'Incidenti - Backup'],
            ['PR.PS-01', 'Protect', '21.2.e', 'Policy - Configurazione sicura'],
            ['PR.PS-02', 'Protect', '21.2.e', 'Asset - Gestione software'],
            ['PR.PS-03', 'Protect', '21.2.e', 'Asset - Gestione hardware'],
            ['PR.PS-04', 'Protect', '21.2.b', 'Audit - Log generation'],
            ['PR.PS-06', 'Protect', '21.2.e', 'Policy - Secure development lifecycle'],
            ['PR.IR-01', 'Protect', '21.2.i', 'Asset - Protezione reti'],
            ['PR.IR-03', 'Protect', '21.2.c', 'Incidenti - Resilienza/ridondanza'],
            // DETECT
            ['DE.CM-01', 'Detect', '21.2.b', 'Incidenti - Monitoraggio reti'],
            ['DE.CM-09', 'Detect', '21.2.b', 'Incidenti - Monitoraggio asset/sistemi'],
            // RESPOND / RECOVER
            ['RS.MA-01', 'Respond', '21.2.b / 23', 'Incidenti - Gestione incidenti'],
            ['RS.CO-02', 'Respond', '23',          'Incidenti - Notifica CSIRT'],
            ['RC.RP-01', 'Recover', '21.2.c',      'Incidenti - Piano di ripristino'],
            ['RC.CO-03', 'Recover', '21.2.c',      'Incidenti - Post-Incident Review'],
        ];

        $mapping = array_map(fn($r) => [
            'csf_code'  => $r[0],
            'function'  => $r[1],
            'nis2_art'  => $r[2],
            'module'    => $r[3],
        ], $rows);

        $this->jsonSuccess([
            'mapping'    => $mapping,
            'count'      => count($mapping),
            'functions'  => ['Govern', 'Identify', 'Protect', 'Detect', 'Respond', 'Recover'],
            'source'     => 'NIST Cybersecurity Framework 2.0 + Direttiva (UE) 2022/2555 (NIS2) Art.20-21-23 / D.Lgs. 138/2024',
        ]);
    }

    /**
     * GET /api/audit/executive-report
     * Genera report esecutivo HTML (stampabile come PDF)
     */
    public function executiveReport(): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'board_member']);

        $reportService = new ReportService();
        $html = $reportService->generateExecutiveReport($this->getCurrentOrgId());

        header('Content-Type: text/html; charset=utf-8');
        echo $html;
        exit;
    }

    /**
     * GET /api/audit/relevantSystemsRegister
     * Registro formale "Sistemi Rilevanti NIS2" (GV.OC-04), HTML stampabile.
     */
    public function relevantSystemsRegister(): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'board_member', 'auditor']);

        $reportService = new ReportService();
        $html = $reportService->generateRelevantSystemsRegister($this->getCurrentOrgId());

        header('Content-Type: text/html; charset=utf-8');
        echo $html;
        exit;
    }

    /**
     * GET /api/audit/export/{type}
     * Esporta dati in CSV
     */
    public function export(int $type = 0): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'auditor']);

        $exportType = $_GET['type'] ?? 'controls';
        $orgId = $this->getCurrentOrgId();
        $reportService = new ReportService();

        $csv = match ($exportType) {
            'risks'     => $reportService->exportRisksCSV($orgId),
            'incidents' => $reportService->exportIncidentsCSV($orgId),
            'controls'  => $reportService->exportControlsCSV($orgId),
            'assets'    => $reportService->exportAssetsCSV($orgId),
            default     => $reportService->exportControlsCSV($orgId),
        };

        $filename = "nis2_{$exportType}_" . date('Y-m-d') . '.csv';

        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        echo $csv;
        exit;
    }

    /**
     * GET /api/audit/chain-verify
     * Verifica l'integrità dell'hash chain per l'organizzazione corrente.
     * Risponde con: valid, total, hashed, coverage_pct, broken_at, last_hash
     */
    public function chainVerify(): void
    {
        $this->requireOrgRole(['org_admin', 'auditor']);
        $orgId = $this->getCurrentOrgId();

        $db     = Database::getInstance();
        $result = AuditService::verifyChain($db, $orgId);

        // Se la catena è rotta, registra la violazione
        if (!$result['valid'] && $result['broken_at'] !== null) {
            $performer = $this->currentUser['email'] ?? 'system';
            try {
                $ins = $db->prepare(
                    "INSERT INTO audit_violations
                     (organization_id, detected_by, broken_at_id, chain_length, notes)
                     VALUES (:org, :by, :bid, :len, :notes)"
                );
                $ins->execute([
                    'org'   => $orgId,
                    'by'    => $performer,
                    'bid'   => $result['broken_at'],
                    'len'   => $result['total'],
                    'notes' => 'Violazione rilevata tramite API chain-verify',
                ]);
            } catch (Throwable $e) {
                error_log('[AuditController] chain violation log error: ' . $e->getMessage());
            }

            $this->logAudit('audit.chain_broken', 'audit_logs', $result['broken_at'], [
                'total'        => $result['total'],
                'coverage_pct' => $result['coverage_pct'],
            ]);
        }

        $this->jsonSuccess($result);
    }

    /**
     * GET /api/audit/export-certified
     * Genera un export JSON certificato con hash SHA-256 dell'intero contenuto.
     * Adatto per ispezioni ACN, audit NIS2 Art.32, certificazione ISO 27001.
     */
    public function exportCertified(): void
    {
        $this->requireOrgRole(['org_admin', 'auditor']);
        $orgId  = $this->getCurrentOrgId();
        $userId = $this->getCurrentUserId();
        $email  = $this->currentUser['email'] ?? 'system';

        $db     = Database::getInstance();
        $result = AuditService::exportCertified(
            $db,
            $orgId,
            $userId,
            $email,
            $_GET['purpose'] ?? 'export_certificato',
            $_GET['from']    ?? null,
            $_GET['to']      ?? null
        );

        $this->logAudit('audit.export_certified', 'audit_logs', null, [
            'records_count' => $result['records_count'],
            'chain_valid'   => $result['chain_valid'],
            'export_hash'   => $result['export_hash'],
        ]);

        header('Content-Disposition: attachment; filename="nis2_audit_certified_' . date('Y-m-d') . '.json"');
        $this->jsonSuccess($result);
    }

    /**
     * GET /api/audit/controlsMonitoring
     * Continuous Control Monitoring (P1): stato/freschezza dei controlli
     * alimentato dalle evidenze automatiche. Versione JWT per la UI.
     */
    public function controlsMonitoring(): void
    {
        $this->requireOrgAccess();
        $orgId = $this->getCurrentOrgId();

        try {
            Database::query(
                "UPDATE compliance_controls cc
                 LEFT JOIN (
                    SELECT t.control_code, t.valid_until
                    FROM control_evidence_auto t
                    JOIN (SELECT control_code, MAX(collected_at) mx FROM control_evidence_auto
                          WHERE organization_id = ? GROUP BY control_code) m
                      ON m.control_code = t.control_code AND m.mx = t.collected_at
                    WHERE t.organization_id = ?
                 ) last ON last.control_code = cc.control_code
                 SET cc.monitoring_status = 'stale'
                 WHERE cc.organization_id = ?
                   AND cc.monitoring_status NOT IN ('not_monitored')
                   AND last.valid_until IS NOT NULL AND last.valid_until < NOW()",
                [$orgId, $orgId, $orgId]
            );
        } catch (Throwable $e) {
            error_log('[CCM] ' . $e->getMessage());
        }

        $rows = Database::fetchAll(
            'SELECT control_code, title, status, monitoring_status, last_checked_at, freshness_days, implementation_percentage
             FROM compliance_controls WHERE organization_id = ? ORDER BY control_code',
            [$orgId]
        );

        $summary = ['healthy' => 0, 'warning' => 0, 'stale' => 0, 'failing' => 0, 'not_monitored' => 0];
        foreach ($rows as $r) {
            $ms = $r['monitoring_status'] ?? 'not_monitored';
            if (isset($summary[$ms])) $summary[$ms]++;
        }
        $monitored = count($rows) - $summary['not_monitored'];

        $recent = [];
        try {
            $recent = Database::fetchAll(
                'SELECT control_code, source, source_system, status, summary, collected_at, valid_until
                 FROM control_evidence_auto WHERE organization_id = ?
                 ORDER BY collected_at DESC LIMIT 20',
                [$orgId]
            );
        } catch (Throwable $e) { /* ignore */ }

        $this->jsonSuccess([
            'total_controls'   => count($rows),
            'monitored'        => $monitored,
            'coverage_percent' => count($rows) ? (int) round($monitored * 100 / count($rows)) : 0,
            'summary'          => $summary,
            'controls'         => $rows,
            'recent_evidence'  => $recent,
        ]);
    }

    // ══════════════════════════════════════════════════════════════════════
    // REQUISITI ACN (specifiche di base, Determina 164179/2025)
    // Gap Analysis a livello requisiti: 87 (importanti) / 116 (essenziali).
    // ══════════════════════════════════════════════════════════════════════

    /** Mappa entity_type org (essential/important/...) -> entity catalogo ACN. */
    private function acnEntityFor(int $orgId): string
    {
        $org = Database::fetchOne('SELECT entity_type FROM organizations WHERE id = ?', [$orgId]);
        // I soggetti essenziali hanno il set esteso (116). Tutti gli altri (importanti o
        // non classificati) usano il set base importanti (87).
        return ($org && ($org['entity_type'] ?? '') === 'essential') ? 'essenziale' : 'importante';
    }

    /**
     * GET /api/audit/acnRequirements
     * Requisiti ACN applicabili all'org (per entity_type) con stato + sommario per funzione.
     */
    public function acnRequirements(): void
    {
        $this->requireOrgAccess();
        $orgId  = $this->getCurrentOrgId();
        $entity = $this->acnEntityFor($orgId);

        $rows = Database::fetchAll(
            "SELECT r.id, r.function_name, r.subcategory, r.subcategory_text, r.req_index, r.requirement,
                    COALESCE(s.status,'not_started') AS status, s.evidence_note, s.updated_at
             FROM acn_requirements r
             LEFT JOIN org_acn_requirement_status s
                    ON s.requirement_id = r.id AND s.organization_id = ?
             WHERE r.entity = ?
             ORDER BY r.subcategory, r.req_index",
            [$orgId, $entity]
        );

        $summary = ['not_started'=>0,'in_progress'=>0,'implemented'=>0,'not_applicable'=>0];
        $byFunc = [];
        foreach ($rows as $r) {
            $st = $r['status'];
            if (isset($summary[$st])) $summary[$st]++;
            $f = $r['function_name'];
            if (!isset($byFunc[$f])) $byFunc[$f] = ['total'=>0,'implemented'=>0];
            $byFunc[$f]['total']++;
            if ($st === 'implemented') $byFunc[$f]['implemented']++;
        }
        $total = count($rows);
        $applicable = $total - $summary['not_applicable'];
        $compliance = $applicable > 0 ? (int) round($summary['implemented'] * 100 / $applicable) : 0;

        $this->jsonSuccess([
            'entity'            => $entity,
            'total'             => $total,
            'summary'           => $summary,
            'by_function'       => $byFunc,
            'compliance_percent'=> $compliance,
            'requirements'      => $rows,
            'source'            => 'Determina ACN 164179/2025, Allegati 1-2 (Framework Nazionale 2025)',
        ]);
    }

    /**
     * PUT /api/audit/acnRequirements/{id}
     * Aggiorna lo stato di un requisito ACN per l'org. Body: { status, evidence_note? }
     */
    public function updateAcnRequirement(int $id): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'auditor']);
        $orgId  = $this->getCurrentOrgId();
        $entity = $this->acnEntityFor($orgId);

        // Il requisito deve appartenere al set applicabile all'org
        $req = Database::fetchOne('SELECT id FROM acn_requirements WHERE id = ? AND entity = ?', [$id, $entity]);
        if (!$req) {
            $this->jsonError('Requisito non trovato o non applicabile a questa organizzazione', 404, 'NOT_FOUND');
        }

        $status = $this->getParam('status');
        $valid = ['not_started','in_progress','implemented','not_applicable'];
        if (!in_array($status, $valid, true)) {
            $this->jsonError('Stato non valido', 422, 'INVALID_STATUS');
        }
        $note = $this->getParam('evidence_note');

        Database::query(
            'INSERT INTO org_acn_requirement_status (organization_id, requirement_id, status, evidence_note, updated_by)
             VALUES (?,?,?,?,?)
             ON DUPLICATE KEY UPDATE status=VALUES(status), evidence_note=VALUES(evidence_note),
                                     updated_by=VALUES(updated_by), updated_at=NOW()',
            [$orgId, $id, $status, $note, $this->getCurrentUserId()]
        );
        $this->logAudit('acn_requirement_updated', 'acn_requirement', $id, ['status' => $status]);
        $this->jsonSuccess(['id' => $id, 'status' => $status], 'Requisito aggiornato');
    }
}
