<?php

declare(strict_types=1);

/**
 * Build a minimal valid Office Open XML (.docx) document for Microsoft Forms Quick Import (Quiz).
 *
 * Per question: number + stem (investigations in stem), lead-in, A.–E. options, blank line,
 * Answer: [letter] and Points: [n] (Forms Quick Import quiz format). Explanations omitted.
 * Required cannot be set from .docx — see export UI note for tutors.
 */

const DOCX_FORMS_DEFAULT_POINTS = 10;
function docx_escape(string $text): string
{
    return htmlspecialchars($text, ENT_XML1 | ENT_QUOTES, 'UTF-8');
}

function docx_paragraph(string $text, bool $bold = false): string
{
    if ($text === '') {
        return '<w:p/>';
    }

    $rPr = $bold ? '<w:rPr><w:b/></w:rPr>' : '';
    $escaped = docx_escape($text);

    return '<w:p><w:r>' . $rPr . '<w:t xml:space="preserve">' . $escaped . '</w:t></w:r></w:p>';
}

function docx_paragraphs_from_text(string $text, bool $bold = false): string
{
    $normalized = str_replace(["\r\n", "\r"], "\n", trim($text));
    if ($normalized === '') {
        return '';
    }

    $parts = preg_split('/\n\s*\n/', $normalized) ?: [];
    $xml = '';

    foreach ($parts as $part) {
        $part = trim($part);
        if ($part === '') {
            continue;
        }
        $lines = explode("\n", $part);
        foreach ($lines as $line) {
            $line = trim($line);
            if ($line !== '') {
                $xml .= docx_paragraph($line, $bold);
            }
        }
    }

    if ($xml === '') {
        $xml = docx_paragraph($normalized, $bold);
    }

    return $xml;
}

function docx_forms_points_for_question(array $question): int
{
    if (isset($question['points']) && is_numeric($question['points'])) {
        $points = (int) $question['points'];
        if ($points > 0) {
            return $points;
        }
    }

    return DOCX_FORMS_DEFAULT_POINTS;
}

function docx_forms_normalise_answer_letter(array $question): string
{
    $letter = strtoupper(trim((string) ($question['correct_answer_letter'] ?? '')));

    if (preg_match('/^[A-E]$/', $letter) === 1) {
        return $letter;
    }

    return '';
}

/**
 * @param list<array<string, mixed>> $questions
 */
function docx_build_microsoft_forms_document(
    array $questions,
    string $documentTitle
): string {
    $body = docx_paragraph($documentTitle, true);

    foreach ($questions as $index => $question) {
        $number = $index + 1;

        if ($index > 0) {
            $body .= docx_paragraph('', false);
        }

        $stem = trim((string) ($question['stem'] ?? ''));
        $leadIn = trim((string) ($question['lead_in'] ?? ''));

        if ($stem === '') {
            $questionHeading = $leadIn !== '' ? $leadIn : 'Question ' . $number;
            $body .= docx_paragraph($number . '. ' . $questionHeading, false);
        } else {
            $body .= docx_paragraph((string) $number . '.', false);
            $body .= docx_paragraphs_from_text($stem, false);
            if ($leadIn !== '') {
                $body .= docx_paragraphs_from_text($leadIn, false);
            }
        }

        $body .= docx_paragraph('', false);

        foreach (['A', 'B', 'C', 'D', 'E'] as $letter) {
            $key = 'option_' . strtolower($letter);
            $optionText = trim((string) ($question[$key] ?? ''));
            if ($optionText !== '') {
                $body .= docx_paragraph($letter . '. ' . $optionText, false);
            }
        }

        $answerLetter = docx_forms_normalise_answer_letter($question);
        if ($answerLetter !== '') {
            $body .= docx_paragraph('', false);
            $body .= docx_paragraph('Answer: ' . $answerLetter, false);
        }

        $body .= docx_paragraph('Points: ' . (string) docx_forms_points_for_question($question), false);
    }

    return docx_package($body, $documentTitle);
}

function docx_package(string $documentBody, string $documentTitle): string
{
    $documentXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">'
        . '<w:body>'
        . $documentBody
        . '<w:sectPr>'
        . '<w:pgSz w:w="11906" w:h="16838"/>'
        . '<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"/>'
        . '</w:sectPr>'
        . '</w:body>'
        . '</w:document>';

    $contentTypes = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
        . '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'
        . '<Default Extension="xml" ContentType="application/xml"/>'
        . '<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>'
        . '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>'
        . '<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>'
        . '</Types>';

    $rels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
        . '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>'
        . '<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>'
        . '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>'
        . '</Relationships>';

    $documentRels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"/>';

    $created = gmdate('Y-m-d\TH:i:s\Z');
    $coreTitle = docx_escape($documentTitle);
    $coreXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" '
        . 'xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" '
        . 'xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
        . '<dc:title>' . $coreTitle . '</dc:title>'
        . '<dc:creator>MLA Question Builder</dc:creator>'
        . '<cp:lastModifiedBy>MLA Question Builder</cp:lastModifiedBy>'
        . '<dcterms:created xsi:type="dcterms:W3CDTF">' . $created . '</dcterms:created>'
        . '<dcterms:modified xsi:type="dcterms:W3CDTF">' . $created . '</dcterms:modified>'
        . '</cp:coreProperties>';

    $appXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" '
        . 'xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">'
        . '<Application>MLA Question Builder</Application>'
        . '</Properties>';

    $tmp = tempnam(sys_get_temp_dir(), 'mla_docx_');
    if ($tmp === false) {
        throw new RuntimeException('Unable to create temporary file for DOCX export.');
    }

    $zip = new ZipArchive();
    if ($zip->open($tmp, ZipArchive::OVERWRITE | ZipArchive::CREATE) !== true) {
        @unlink($tmp);
        throw new RuntimeException('Unable to create DOCX archive.');
    }

    $zip->addFromString('[Content_Types].xml', $contentTypes);
    $zip->addFromString('_rels/.rels', $rels);
    $zip->addFromString('word/document.xml', $documentXml);
    $zip->addFromString('word/_rels/document.xml.rels', $documentRels);
    $zip->addFromString('docProps/core.xml', $coreXml);
    $zip->addFromString('docProps/app.xml', $appXml);
    $zip->close();

    $bytes = file_get_contents($tmp);
    @unlink($tmp);

    if ($bytes === false) {
        throw new RuntimeException('Unable to read generated DOCX file.');
    }

    return $bytes;
}

function docx_format_export_datetime(): string
{
    return (new DateTimeImmutable('now'))->format('d/m/Y H:i');
}
