<?php
/**
 * NIS2 Agile - Assessment Controller
 *
 * Gap Analysis wizard: questionario NIS2, scoring, AI analysis.
 */

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

class AssessmentController extends BaseController
{
    /**
     * GET /api/assessments/list
     */
    public function list(): void
    {
        $this->requireOrgAccess();

        $assessments = Database::fetchAll(
            'SELECT a.*, u.full_name as completed_by_name
             FROM assessments a
             LEFT JOIN users u ON u.id = a.completed_by
             WHERE a.organization_id = ?
             ORDER BY a.created_at DESC',
            [$this->getCurrentOrgId()]
        );

        $this->jsonSuccess($assessments);
    }

    /**
     * POST /api/assessments/create
     */
    public function create(): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager']);

        $title = $this->getParam('title', 'Assessment NIS2 - ' . date('d/m/Y'));
        $type = $this->getParam('assessment_type', 'initial');

        $assessmentId = Database::insert('assessments', [
            'organization_id' => $this->getCurrentOrgId(),
            'title'           => $title,
            'assessment_type' => $type,
            'status'          => 'draft',
        ]);

        // Pre-popola le risposte con le domande dal questionario
        $questionnaire = $this->loadQuestionnaire();

        foreach ($questionnaire['categories'] as $category) {
            foreach ($category['questions'] as $question) {
                Database::insert('assessment_responses', [
                    'assessment_id'   => $assessmentId,
                    'question_code'   => $question['code'],
                    'nis2_article'    => $question['nis2_article'],
                    'iso27001_control' => $question['iso27001_control'],
                    'category'        => $category['id'],
                    'question_text'   => $question['text_it'],
                ]);
            }
        }

        $this->logAudit('assessment_created', 'assessment', $assessmentId);

        $this->jsonSuccess([
            'id'     => $assessmentId,
            'title'  => $title,
            'status' => 'draft',
        ], 'Assessment creato', 201);
    }

    /**
     * GET /api/assessments/{id}
     */
    public function get(int $id): void
    {
        $this->requireOrgAccess();

        $assessment = $this->getAssessment($id);

        // Conta risposte per stato
        $stats = Database::fetchAll(
            'SELECT response_value, COUNT(*) as count
             FROM assessment_responses
             WHERE assessment_id = ? AND response_value IS NOT NULL
             GROUP BY response_value',
            [$id]
        );

        $totalQuestions = Database::count('assessment_responses', 'assessment_id = ?', [$id]);
        $answeredQuestions = Database::count(
            'assessment_responses',
            'assessment_id = ? AND response_value IS NOT NULL',
            [$id]
        );

        $assessment['stats'] = $stats;
        $assessment['total_questions'] = $totalQuestions;
        $assessment['answered_questions'] = $answeredQuestions;
        $assessment['progress_percentage'] = $totalQuestions > 0
            ? round($answeredQuestions / $totalQuestions * 100)
            : 0;

        $this->jsonSuccess($assessment);
    }

    /**
     * GET /api/assessments/{id}/questions
     * Restituisce domande con risposte correnti, organizzate per categoria
     */
    public function getQuestions(int $id): void
    {
        $this->requireOrgAccess();
        $this->getAssessment($id);

        $responses = Database::fetchAll(
            'SELECT * FROM assessment_responses WHERE assessment_id = ? ORDER BY question_code',
            [$id]
        );

        // Carica questionario per i metadati
        $questionnaire = $this->loadQuestionnaire();
        $questionMeta = [];
        foreach ($questionnaire['categories'] as $cat) {
            foreach ($cat['questions'] as $q) {
                $questionMeta[$q['code']] = [
                    'text_en'           => $q['text_en'],
                    'guidance_it'       => $q['guidance_it'],
                    'evidence_examples' => $q['evidence_examples'],
                    'weight'            => $q['weight'],
                ];
            }
        }

        // Organizza per categoria
        $byCategory = [];
        foreach ($responses as $r) {
            $cat = $r['category'];
            if (!isset($byCategory[$cat])) {
                // Trova titolo categoria
                $catTitle = $cat;
                foreach ($questionnaire['categories'] as $c) {
                    if ($c['id'] === $cat) {
                        $catTitle = $c['title_it'];
                        break;
                    }
                }
                $byCategory[$cat] = [
                    'category_id'    => $cat,
                    'category_title' => $catTitle,
                    'questions'      => [],
                ];
            }

            $meta = $questionMeta[$r['question_code']] ?? [];
            $r['text_en'] = $meta['text_en'] ?? null;
            $r['guidance_it'] = $meta['guidance_it'] ?? null;
            $r['evidence_examples'] = $meta['evidence_examples'] ?? [];
            $r['weight'] = $meta['weight'] ?? 1;

            $byCategory[$cat]['questions'][] = $r;
        }

        $this->jsonSuccess(array_values($byCategory));
    }

    /**
     * POST /api/assessments/{id}/respond
     * Salva una o più risposte
     */
    public function saveResponse(int $id): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager', 'auditor']);

        $assessment = $this->getAssessment($id);

        if ($assessment['status'] === 'completed') {
            $this->jsonError('Assessment già completato', 400, 'ALREADY_COMPLETED');
        }

        // Accetta singola risposta o array di risposte
        $responses = $this->getParam('responses');
        if (!$responses) {
            // Singola risposta
            $this->validateRequired(['question_code', 'response_value']);
            $responses = [[
                'question_code'       => $this->getParam('question_code'),
                'response_value'      => $this->getParam('response_value'),
                'maturity_level'      => $this->getParam('maturity_level'),
                'evidence_description' => $this->getParam('evidence_description'),
                'notes'               => $this->getParam('notes'),
            ]];
        }

        $savedCount = 0;
        foreach ($responses as $resp) {
            $code = $resp['question_code'] ?? null;
            $value = $resp['response_value'] ?? null;

            if (!$code || !$value) continue;

            Database::update('assessment_responses', [
                'response_value'      => $value,
                'maturity_level'      => $resp['maturity_level'] ?? null,
                'evidence_description' => $resp['evidence_description'] ?? null,
                'notes'               => $resp['notes'] ?? null,
                'answered_by'         => $this->getCurrentUserId(),
                'answered_at'         => date('Y-m-d H:i:s'),
            ], 'assessment_id = ? AND question_code = ?', [$id, $code]);

            $savedCount++;
        }

        // Aggiorna status a in_progress se era draft
        if ($assessment['status'] === 'draft') {
            Database::update('assessments', ['status' => 'in_progress'], 'id = ?', [$id]);
        }

        $this->jsonSuccess(['saved' => $savedCount], "{$savedCount} risposte salvate");
    }

    /**
     * POST /api/assessments/{id}/complete
     */
    public function complete(int $id): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager']);

        $assessment = $this->getAssessment($id);

        if ($assessment['status'] === 'completed') {
            $this->jsonError('Assessment già completato', 400, 'ALREADY_COMPLETED');
        }

        // Calcola score
        $responses = Database::fetchAll(
            'SELECT * FROM assessment_responses WHERE assessment_id = ?',
            [$id]
        );

        $scores = $this->calculateScores($responses);

        Database::update('assessments', [
            'status'          => 'completed',
            'overall_score'   => $scores['overall'],
            'category_scores' => json_encode($scores['by_category']),
            'completed_by'    => $this->getCurrentUserId(),
            'completed_at'    => date('Y-m-d H:i:s'),
        ], 'id = ?', [$id]);

        $this->logAudit('assessment_completed', 'assessment', $id, [
            'overall_score' => $scores['overall']
        ]);

        $this->jsonSuccess([
            'overall_score'   => $scores['overall'],
            'category_scores' => $scores['by_category'],
        ], 'Assessment completato');
    }

    /**
     * GET /api/assessments/{id}/report
     */
    public function getReport(int $id): void
    {
        $this->requireOrgAccess();

        $assessment = $this->getAssessment($id);

        if ($assessment['status'] !== 'completed') {
            $this->jsonError('L\'assessment deve essere completato prima di generare il report', 400, 'NOT_COMPLETED');
        }

        $responses = Database::fetchAll(
            'SELECT ar.*, u.full_name as answered_by_name
             FROM assessment_responses ar
             LEFT JOIN users u ON u.id = ar.answered_by
             WHERE ar.assessment_id = ?
             ORDER BY ar.category, ar.question_code',
            [$id]
        );

        $categoryScores = json_decode($assessment['category_scores'], true) ?? [];

        $this->jsonSuccess([
            'assessment'      => $assessment,
            'category_scores' => $categoryScores,
            'responses'       => $responses,
            'ai_summary'      => $assessment['ai_summary'],
            'ai_recommendations' => json_decode($assessment['ai_recommendations'], true),
        ]);
    }

    /**
     * POST /api/assessments/{id}/ai-analyze
     * Richiede analisi AI dell'assessment
     */
    public function aiAnalyze(int $id): void
    {
        $this->requireOrgRole(['org_admin', 'compliance_manager']);

        $assessment = $this->getAssessment($id);

        if ($assessment['status'] !== 'completed') {
            $this->jsonError('Completare l\'assessment prima dell\'analisi AI', 400, 'NOT_COMPLETED');
        }

        // Carica organizzazione
        $org = Database::fetchOne('SELECT * FROM organizations WHERE id = ?', [$this->getCurrentOrgId()]);

        // Carica risposte
        $responses = Database::fetchAll(
            'SELECT * FROM assessment_responses WHERE assessment_id = ?',
            [$id]
        );

        try {
            $aiService = new AIService();
            $analysis = $aiService->analyzeGapAssessment($org, $responses, (float) $assessment['overall_score']);

            // Salva risultati AI
            Database::update('assessments', [
                'ai_summary'         => $analysis['executive_summary'] ?? json_encode($analysis),
                'ai_recommendations' => json_encode($analysis),
            ], 'id = ?', [$id]);

            // Log interazione AI
            $aiService->logInteraction(
                $this->getCurrentOrgId(),
                $this->getCurrentUserId(),
                'gap_analysis',
                "Gap analysis assessment #{$id}",
                substr(json_encode($analysis), 0, 500)
            );

            $this->logAudit('ai_analysis_requested', 'assessment', $id);

            $this->jsonSuccess($analysis, 'Analisi AI completata');

        } catch (Throwable $e) {
            error_log('[AI_ERROR] ' . $e->getMessage());
            $this->jsonError('Errore durante l\'analisi AI: ' . $e->getMessage(), 500, 'AI_ERROR');
        }
    }

    // ═══════════════════════════════════════════════════════════════════════
    // METODI PRIVATI
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Carica assessment verificando ownership
     */
    private function getAssessment(int $id): array
    {
        $assessment = Database::fetchOne(
            'SELECT * FROM assessments WHERE id = ? AND organization_id = ?',
            [$id, $this->getCurrentOrgId()]
        );

        if (!$assessment) {
            $this->jsonError('Assessment non trovato', 404, 'ASSESSMENT_NOT_FOUND');
        }

        return $assessment;
    }

    /**
     * Carica questionario da file JSON
     */
    private function loadQuestionnaire(): array
    {
        $file = DATA_PATH . '/nis2_questionnaire.json';

        if (!file_exists($file)) {
            $this->jsonError('Questionario NIS2 non disponibile', 500, 'QUESTIONNAIRE_MISSING');
        }

        $data = json_decode(file_get_contents($file), true);

        if (!$data) {
            $this->jsonError('Errore caricamento questionario', 500, 'QUESTIONNAIRE_ERROR');
        }

        return $data;
    }

    /**
     * Calcola score dell'assessment
     */
    private function calculateScores(array $responses): array
    {
        $byCategory = [];
        $totalWeightedScore = 0;
        $totalWeight = 0;

        // Carica pesi dalle domande
        $questionnaire = $this->loadQuestionnaire();
        $weights = [];
        foreach ($questionnaire['categories'] as $cat) {
            foreach ($cat['questions'] as $q) {
                $weights[$q['code']] = $q['weight'] ?? 1;
            }
        }

        foreach ($responses as $r) {
            $cat = $r['category'] ?? 'other';
            $value = $r['response_value'];
            $weight = $weights[$r['question_code']] ?? 1;

            if (!isset($byCategory[$cat])) {
                $byCategory[$cat] = ['score' => 0, 'max' => 0, 'count' => 0];
            }

            if ($value === 'not_applicable') continue;

            $score = match ($value) {
                'implemented' => 100,
                'partial'     => 50,
                default       => 0,
            };

            $byCategory[$cat]['score'] += $score * $weight;
            $byCategory[$cat]['max'] += 100 * $weight;
            $byCategory[$cat]['count']++;

            $totalWeightedScore += $score * $weight;
            $totalWeight += 100 * $weight;
        }

        // Calcola percentuali per categoria
        $categoryScores = [];
        foreach ($byCategory as $cat => $data) {
            $categoryScores[$cat] = [
                'score'   => $data['max'] > 0 ? round($data['score'] / $data['max'] * 100, 1) : 0,
                'count'   => $data['count'],
            ];
        }

        $overallScore = $totalWeight > 0 ? round($totalWeightedScore / $totalWeight * 100, 1) : 0;

        return [
            'overall'     => $overallScore,
            'by_category' => $categoryScores,
        ];
    }
}
