<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

/**
 * Builds and serves the DOCX student fiche from a fiche_builder DTO, via
 * the vendored PHPWord library (not bundled by Moodle core, unlike
 * PhpSpreadsheet/TCPDF).
 *
 * @package    local_kid
 */

namespace local_kid\local;

use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\Style\Table as TableStyle;

defined('MOODLE_INTERNAL') || die();

require_once($GLOBALS['CFG']->dirroot . '/local/kid/vendor/autoload.php');

class docx_service {

    /**
     * Competency table column widths in twips, ~30/15/55%. Total (9000)
     * is kept within the section's printable width (A4 portrait, 11905
     * twips wide minus 1440-twip margins each side = ~9025 twips) now that
     * 'layout' => fixed below makes Word honour these widths literally
     * instead of auto-fitting the table to content.
     */
    private const COL_COMPETENCE = 2700;
    private const COL_NIVEAU = 1350;
    private const COL_COMMENTAIRE = 4950;

    /**
     * 'layout' => fixed (+ explicit 'width'/'unit') forces Word to honour
     * the column widths above instead of auto-resizing columns to fit
     * unwrapped content, which is what caused the original imbalance.
     */
    private const TABLE_STYLE = [
        'borderSize' => 6,
        'borderColor' => '999999',
        'cellMargin' => 80,
        'layout' => TableStyle::LAYOUT_FIXED,
        'unit' => TblWidth::TWIP,
        'width' => self::COL_COMPETENCE + self::COL_NIVEAU + self::COL_COMMENTAIRE,
    ];
    /** noWrap defaults to true in PHPWord; every cell needs it off so long text wraps instead of overflowing. */
    private const CELL_STYLE = ['noWrap' => false];
    private const HEADER_CELL = ['bgColor' => 'DDDDDD', 'noWrap' => false];

    /** Reduced font size for the competency-name column, so full names wrap rather than overflow. */
    private const COMPETENCE_FONT_SIZE = 8;

    /** Entry-level (not per-competency) comment fields, one per domain that has one; keyed by the fiche_builder item property, valued by its lang string. */
    private const GLOBAL_COMMENT_FIELDS = [
        'commentaireglobal' => 'stage_commentaire_global',
        'appreciationglobale' => 'capp_appreciation_globale',
    ];

    public static function build_fiche(\stdClass $dto): PhpWord {
        $phpword = new PhpWord();
        $phpword->setDefaultFontName('Arial');
        $phpword->setDefaultFontSize(10);

        $section = $phpword->addSection();
        $section->addTitle($dto->student->fullname, 1);
        $section->addText($dto->student->promotionname . ($dto->student->codeena ? ' — ' . $dto->student->codeena : ''));
        $section->addTextBreak(1);

        self::add_domain(
            $section,
            get_string('student_section_eval', 'local_kid'),
            get_string('student_section_eval_empty', 'local_kid'),
            $dto->evaluations
        );
        self::add_domain(
            $section,
            get_string('student_section_stage', 'local_kid'),
            get_string('student_section_stage_empty', 'local_kid'),
            $dto->stages
        );
        self::add_domain(
            $section,
            get_string('student_section_capp', 'local_kid'),
            get_string('student_section_capp_empty', 'local_kid'),
            $dto->capp
        );

        return $phpword;
    }

    private static function add_domain(\PhpOffice\PhpWord\Element\Section $section, string $title, string $emptylabel, array $items): void {
        $section->addTitle($title, 2);
        if (empty($items)) {
            $section->addText($emptylabel, ['italic' => true]);
            return;
        }
        foreach ($items as $item) {
            $itemtitle = $item->titre . ($item->date ?? '' ? ' — ' . $item->date : '') . ' (' . $item->statuslabel . ')';
            $section->addTitle($itemtitle, 3);

            $table = $section->addTable(self::TABLE_STYLE);
            $table->addRow();
            $table->addCell(self::COL_COMPETENCE, self::HEADER_CELL)->addText(get_string('grid_competence', 'local_kid'), ['bold' => true]);
            $table->addCell(self::COL_NIVEAU, self::HEADER_CELL)->addText(get_string('grid_niveau', 'local_kid'), ['bold' => true]);
            $table->addCell(self::COL_COMMENTAIRE, self::HEADER_CELL)->addText(get_string('grid_commentaire', 'local_kid'), ['bold' => true]);
            foreach ($item->competences as $cell) {
                $table->addRow();
                $table->addCell(self::COL_COMPETENCE, self::CELL_STYLE)->addText($cell->code . ' — ' . $cell->libelle, ['size' => self::COMPETENCE_FONT_SIZE]);
                $table->addCell(self::COL_NIVEAU, self::CELL_STYLE)->addText($cell->niveau ?? '');
                $table->addCell(self::COL_COMMENTAIRE, self::CELL_STYLE)->addText($cell->commentaire ?? '');

                if (!empty($cell->hasmoodlefeedback)) {
                    $table->addRow();
                    $table->addCell(self::COL_COMPETENCE, self::CELL_STYLE)->addText('');
                    $table->addCell(self::COL_NIVEAU, self::CELL_STYLE)->addText('');
                    $feedbackcell = $table->addCell(self::COL_COMMENTAIRE, self::CELL_STYLE);
                    $feedbackcell->addText(get_string('eval_feedback_heading', 'local_kid') . ' :', ['bold' => true, 'italic' => true, 'size' => 8]);
                    $feedbackcell->addText($cell->moodlefeedback, ['size' => 9]);
                }
            }

            foreach (self::GLOBAL_COMMENT_FIELDS as $field => $labelstring) {
                if (!empty($item->$field)) {
                    $section->addText(get_string($labelstring, 'local_kid') . ' : ', ['bold' => true]);
                    $section->addText($item->$field);
                }
            }
            $section->addTextBreak(1);
        }
    }

    public static function send(PhpWord $phpword, string $filename): void {
        header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $writer = IOFactory::createWriter($phpword, 'Word2007');
        $writer->save('php://output');
        exit;
    }

    /**
     * Saves to a real temp file (Word2007's zip writer needs one), for
     * bulk ZIP building where several fiches must exist on disk at once.
     */
    public static function save_to_temp_file(PhpWord $phpword): string {
        $dir = make_request_directory();
        $path = $dir . '/fiche.docx';
        $writer = IOFactory::createWriter($phpword, 'Word2007');
        $writer->save($path);
        return $path;
    }
}
