<?php
declare(strict_types=1);

/**
 * Normalized exam document model.
 *
 * The generator has two independent sources of exam content:
 *
 *   1. `generated_exams`  — AI output stored as nested JSON sections.
 *   2. `exam_papers`      — curated papers stored as flat `exam_questions` rows.
 *
 * Both are adapted here into one uniform document structure so that a single
 * set of templates can render either source, in either the student paper or
 * the marking-scheme (answer key) variant.
 *
 * Document shape:
 *   [
 *     'school'   => ['name','address','phone','email','logo'],   // logo = data URI or ''
 *     'title', 'class_name', 'subject_name', 'term', 'academic_year',
 *     'duration_minutes', 'total_marks', 'instructions', 'is_key',
 *     'sections' => [
 *        ['letter','label','type','instruction','marks','passage','questions' => [
 *            ['number','text','marks','options','correct','model_answer',
 *             'marking_guide' (array), 'diagram_html', 'matching', 'subs']
 *        ]]
 *     ]
 *   ]
 */

require_once __DIR__ . '/exam_diagram_adapter.php'; // also pulls in diagram_renderer.php

/** GES-style section labels, keyed by internal question type. */
function examSectionLabel(string $type): string
{
    return [
        'mcq'           => 'Objective Test',
        'objective'     => 'Objective Test',
        'true_false'    => 'True or False',
        'matching'      => 'Matching Items',
        'fill_blank'    => 'Fill in the Blanks',
        'comprehension' => 'Comprehension',
        'theory'        => 'Theory / Essay',
        'subjective'    => 'Theory / Essay',
    ][$type] ?? ucfirst(str_replace('_', ' ', $type));
}

/**
 * School identity for the exam letterhead. Logo is base64-embedded so mPDF
 * never needs remote/file access at render time.
 */
function examSchoolInfo(mysqli $conn): array
{
    $settings = [];
    $res = $conn->query("SELECT setting_key, setting_value FROM settings");
    if ($res) {
        while ($row = $res->fetch_assoc()) {
            $settings[$row['setting_key']] = $row['setting_value'];
        }
    }

    $logo    = '';
    $relPath = ltrim((string) ($settings['school_logo'] ?? 'uploads/logos/logo.png'), '/');
    $abs     = dirname(__DIR__, 2) . '/' . $relPath; // lib -> exams_generator -> edutrack
    if ($relPath !== '' && file_exists($abs)) {
        $ext  = strtolower(pathinfo($abs, PATHINFO_EXTENSION));
        $mime = in_array($ext, ['jpg', 'jpeg']) ? 'image/jpeg' : 'image/png';
        $logo = 'data:' . $mime . ';base64,' . base64_encode((string) file_get_contents($abs));
    }

    return [
        'name'     => (string) ($settings['school_name']    ?? 'SCHOOL NAME'),
        'address'  => (string) ($settings['school_address'] ?? ''),
        'phone'    => (string) ($settings['school_phone']   ?? ''),
        'email'    => (string) ($settings['school_email']   ?? ''),
        'logo'     => $logo,
        'template' => (string) ($settings['exam_template']  ?? 'ges_standard'),
    ];
}

/**
 * Decode a matching question into left items, a deterministically-shuffled
 * right column (lettered), and the correct left→letter answer map. Seeded by
 * the question id so the paper and the marking scheme always agree.
 */
if (!function_exists('matchingLayout')) {
    function matchingLayout(array $q): array
    {
        $extra = is_array($q['extra_data'] ?? null) ? $q['extra_data'] : json_decode((string) ($q['extra_data'] ?? ''), true);
        $pairs = (is_array($extra) && is_array($extra['pairs'] ?? null)) ? array_values($extra['pairs']) : [];

        $left = [];
        $rightItems = [];
        foreach ($pairs as $p) {
            $left[]       = (string) ($p['left'] ?? '');
            $rightItems[] = (string) ($p['right'] ?? '');
        }

        $count = count($rightItems);
        $order = range(0, max(0, $count - 1));
        if ($count > 1) {
            $seed = (int) ($q['id'] ?? 0);
            mt_srand($seed > 0 ? $seed : 12345);
            for ($i = $count - 1; $i > 0; $i--) {
                $j = mt_rand(0, $i);
                [$order[$i], $order[$j]] = [$order[$j], $order[$i]];
            }
            mt_srand();
        }

        $letters = range('A', 'Z');
        $right = [];
        foreach ($order as $pos => $origIdx) {
            $right[] = ['letter' => $letters[$pos] ?? '?', 'text' => $rightItems[$origIdx] ?? ''];
        }
        $answer = [];
        foreach ($left as $i => $_) {
            $pos = array_search($i, $order, true);
            $answer[$i + 1] = $pos !== false ? ($letters[$pos] ?? '?') : '?';
        }

        return ['left' => $left, 'right' => $right, 'answer' => $answer];
    }
}

/**
 * Adapter A — build a document from a curated `exam_papers` record
 * (flat exam_questions rows grouped by type into lettered sections).
 */
function examDocFromPaper(array $questions, array $config, bool $isKey, array $school): array
{
    $sectionConfig = is_array($config['section_config'] ?? null) ? $config['section_config'] : [];

    $groups = ['mcq', 'true_false', 'matching', 'fill_blank', 'comprehension', 'theory'];

    $sections = [];
    $n = 1;
    $letterIdx = 0;
    $grandTotal = 0;

    foreach ($groups as $type) {
        $items = array_values(array_filter($questions, static fn($q) => ($q['question_type'] ?? '') === $type));
        if ($items === []) {
            continue;
        }
        $count = count($items);
        $sectionMarks = (int) array_sum(array_map(static fn($q) => (int) ($q['marks'] ?? 0), $items));

        $cfg    = is_array($sectionConfig[$type] ?? null) ? $sectionConfig[$type] : [];
        $choose = (int) ($cfg['choose'] ?? 0);

        if ($choose > 0 && $choose < $count) {
            $instruction = "Answer any {$choose} of the {$count} questions in this section.";
            $perMark     = $count > 0 ? $sectionMarks / $count : 0;
            $creditMarks = (int) round($choose * $perMark);
        } else {
            $instruction = (string) ($cfg['instruction'] ?? 'Answer ALL questions in this section.');
            $creditMarks = $sectionMarks;
        }
        $grandTotal += $creditMarks;

        $qs = [];
        foreach ($items as $q) {
            $qs[] = normalizePaperQuestion($q, $n++, $type);
        }

        $sections[] = [
            'letter'      => chr(65 + $letterIdx++),
            'label'       => examSectionLabel($type),
            'type'        => $type,
            'instruction' => $instruction,
            'marks'       => $creditMarks,
            'passage'     => '',
            'questions'   => $qs,
        ];
    }

    return [
        'school'           => $school,
        'title'            => (string) $config['title'],
        'class_name'       => (string) ($config['class_name'] ?? ''),
        'subject_name'     => (string) ($config['subject_name'] ?? ''),
        'term'             => (string) ($config['term'] ?? ''),
        'academic_year'    => (string) ($config['academic_year'] ?? ''),
        'duration_minutes' => (int) ($config['duration_minutes'] ?? 0),
        'total_marks'      => $grandTotal > 0 ? $grandTotal : (int) ($config['total_marks'] ?? 0),
        'instructions'     => (string) ($config['instructions'] ?? ''),
        'is_key'           => $isKey,
        'sections'         => $sections,
    ];
}

function normalizePaperQuestion(array $q, int $number, string $type): array
{
    $options = [];
    if ($type === 'mcq') {
        foreach (['A', 'B', 'C', 'D'] as $opt) {
            $val = (string) ($q['option_' . strtolower($opt)] ?? '');
            if ($val !== '') {
                $options[$opt] = $val;
            }
        }
    }

    $diagramHtml = '';
    if (!empty($q['diagram_required']) && !empty($q['diagram_spec'])) {
        $spec = is_array($q['diagram_spec']) ? $q['diagram_spec'] : json_decode((string) $q['diagram_spec'], true);
        if (is_array($spec)) {
            if (empty($spec['question'])) { $spec['question'] = (string) ($q['question'] ?? ''); }
            $diagramHtml = renderDiagram($spec);
        }
    }

    $extra = is_array($q['extra_data'] ?? null) ? $q['extra_data'] : json_decode((string) ($q['extra_data'] ?? ''), true);

    $subs = [];
    $passage = '';
    if ($type === 'comprehension' && is_array($extra)) {
        $passage = (string) ($extra['passage'] ?? '');
        foreach ((is_array($extra['questions'] ?? null) ? $extra['questions'] : []) as $sq) {
            $subs[] = [
                'text'         => (string) ($sq['text'] ?? ''),
                'marks'        => max(1, (int) ($sq['marks'] ?? 1)),
                'model_answer' => (string) ($sq['model_answer'] ?? ''),
            ];
        }
    }

    $markingGuide = [];
    $mg = trim((string) ($q['marking_guide'] ?? ''));
    if ($mg !== '') {
        $markingGuide = array_values(array_filter(array_map('trim', explode("\n", $mg))));
    }

    return [
        'number'        => $number,
        'text'          => (string) ($q['question'] ?? ''),
        'marks'         => (int) ($q['marks'] ?? 1),
        'options'       => $options,
        'correct'       => (string) ($q['correct_answer'] ?? ''),
        'model_answer'  => (string) ($q['model_answer'] ?? ''),
        'marking_guide' => $markingGuide,
        'diagram_html'  => $diagramHtml,
        'matching'      => $type === 'matching' ? matchingLayout($q) : null,
        'passage'       => $passage,
        'subs'          => $subs,
    ];
}

/**
 * Adapter B — build a document from a `generated_exams` record whose
 * `exam_data` holds nested AI-generated sections.
 */
function examDocFromGeneratedExam(array $exam, bool $isKey, array $school): array
{
    $examData = is_array($exam['exam_data'] ?? null) ? $exam['exam_data'] : (json_decode((string) ($exam['exam_data'] ?? ''), true) ?: []);

    $sections = [];
    $letterIdx = 0;
    $grandTotal = 0;

    foreach (($examData['sections'] ?? []) as $section) {
        $type  = (string) ($section['type'] ?? 'objective');
        $items = is_array($section['questions'] ?? null) ? $section['questions'] : [];
        if ($items === []) {
            continue;
        }

        $sectionMarks = (int) array_sum(array_map(static fn($q) => (int) ($q['marks'] ?? 0), $items));
        $grandTotal  += $sectionMarks;

        $qs = [];
        foreach ($items as $i => $q) {
            $options = [];
            foreach ((is_array($q['options'] ?? null) ? $q['options'] : []) as $k => $v) {
                $options[(string) $k] = (string) $v;
            }

            $diagramHtml = '';
            if (!empty($q['diagram']) && is_array($q['diagram'])) {
                $title = trim((string) ($q['diagram']['title'] ?? ''));
                if ($title !== '') {
                    $diagramHtml .= '<div style="text-align:center;font-weight:bold;font-size:9pt;margin-top:4px;">' . htmlspecialchars($title) . '</div>';
                }
                $diagramHtml .= renderExamDiagram($q['diagram']);
            }

            $rubric = [];
            foreach ((is_array($q['rubric'] ?? null) ? $q['rubric'] : []) as $point) {
                $rubric[] = (string) $point;
            }

            $qs[] = [
                'number'        => (int) ($q['number'] ?? ($i + 1)),
                'text'          => (string) ($q['text'] ?? ''),
                'marks'         => (int) ($q['marks'] ?? 0),
                'options'       => $options,
                'correct'       => (string) ($q['correct_option'] ?? ''),
                'model_answer'  => (string) ($q['model_answer'] ?? ''),
                'marking_guide' => $rubric,
                'diagram_html'  => $diagramHtml,
                'matching'      => null,
                'passage'       => '',
                'subs'          => [],
            ];
        }

        $sections[] = [
            'letter'      => chr(65 + $letterIdx++),
            'label'       => (string) ($section['title'] ?? examSectionLabel($type)),
            'type'        => $type === 'objective' ? 'mcq' : ($type === 'subjective' ? 'theory' : $type),
            'instruction' => (string) ($section['instructions'] ?? 'Answer ALL questions in this section.'),
            'marks'       => $sectionMarks,
            'passage'     => (string) ($section['passage'] ?? ''),
            'questions'   => $qs,
        ];
    }

    return [
        'school'           => $school,
        'title'            => (string) ($exam['title'] ?? 'Examination'),
        'class_name'       => (string) ($exam['class_name'] ?? ''),
        'subject_name'     => (string) ($exam['subject_name'] ?? ''),
        'term'             => (string) ($exam['term'] ?? ''),
        'academic_year'    => (string) ($exam['academic_year'] ?? getAcademicYear()),
        'duration_minutes' => (int) ($exam['duration_minutes'] ?? 0),
        'total_marks'      => (int) ($exam['total_marks'] ?? 0) ?: $grandTotal,
        'instructions'     => (string) ($exam['instructions'] ?? ''),
        'is_key'           => $isKey,
        'sections'         => $sections,
    ];
}
