<?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.

/**
 * CAPP per-student rating grid: per competency, read-only consultative
 * "Enseignements"/"Stages" columns (never authoritative) plus the CAPP's
 * own niveau/commentaire, and a single "Appréciation d'ensemble" field
 * shown once after every competency, not repeated per row.
 *
 * @package    local_kid
 */

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

require_once($CFG->libdir . '/formslib.php');

class local_kid_capp_grid_form extends moodleform {

    protected function definition() {
        $mform = $this->_form;

        $competencies = $this->_customdata['competencies']; // id => libelle
        $niveaux = $this->_customdata['niveaux'];
        $results = $this->_customdata['results']; // competencyid => {niveauid, commentaire}
        $consultative = $this->_customdata['consultative']; // competencyid => ['eval' => [...], 'stage' => [...]]
        $commenthistory = $this->_customdata['commenthistory'] ?? [];
        $historycontext = $this->_customdata['historycontext'] ?? '';

        $mform->addElement('hidden', 'entryid');
        $mform->setType('entryid', PARAM_INT);

        // See entry_grid_form.php for the same fields — kept identical
        // across both grid forms so entry_conflict_service and the
        // navigation-guard JS work the same way on all three domains.
        $mform->addElement('hidden', 'expectedtimemodified');
        $mform->setType('expectedtimemodified', PARAM_INT);
        $mform->addElement('hidden', 'returnurl');
        $mform->setType('returnurl', PARAM_LOCALURL);

        $niveauoptions = [0 => get_string('niveau_none', 'local_kid')];
        foreach ($niveaux as $niveau) {
            $niveauoptions[$niveau->id] = $niveau->libelle;
        }

        foreach ($competencies as $competencyid => $libelle) {
            $mform->addElement('header', 'comp_' . $competencyid, format_string($libelle));
            $mform->setExpanded('comp_' . $competencyid, true);

            $consult = $consultative[$competencyid] ?? ['eval' => ['count' => 0, 'items' => []], 'stage' => ['count' => 0, 'items' => []], 'priors' => []];
            $evalhtml = $this->render_consultative($consult['eval'], get_string('capp_col_enseignements', 'local_kid'));
            $stagehtml = $this->render_consultative($consult['stage'], get_string('capp_col_stages', 'local_kid'));
            $priorshtml = $this->render_priors($consult['priors'] ?? []);
            $mform->addElement('static', 'consult_' . $competencyid, '', $evalhtml . $stagehtml . $priorshtml);

            $mform->addElement('select', "results[{$competencyid}][niveauid]", get_string('niveau_libelle', 'local_kid'), $niveauoptions);
            $mform->addElement('textarea', "results[{$competencyid}][commentaire]", get_string('capp_commentaire', 'local_kid'), ['rows' => 2, 'cols' => 60]);
            $mform->addElement('hidden', "results[{$competencyid}][origcommentaire]");
            $mform->setType("results[{$competencyid}][origcommentaire]", PARAM_RAW);

            $versions = $commenthistory[$competencyid] ?? [];
            if ($versions) {
                $linkhtml = \local_kid\local\comment_history_service::render_link($versions,
                    $historycontext . ' · ' . format_string($libelle));
                $mform->addElement('static', "historylink_{$competencyid}", '', $linkhtml);
            }

            $existing = $results[$competencyid] ?? null;
            if ($existing) {
                $mform->setDefault("results[{$competencyid}][niveauid]", $existing->niveauid ?: 0);
                $mform->setDefault("results[{$competencyid}][commentaire]", $existing->commentaire ?? '');
                $mform->setDefault("results[{$competencyid}][origcommentaire]", $existing->commentaire ?? '');
            } else {
                $mform->setDefault("results[{$competencyid}][origcommentaire]", '');
            }
        }

        $mform->addElement('header', 'appreciationheader', get_string('capp_appreciation_globale', 'local_kid'));
        $mform->setExpanded('appreciationheader', true);
        $mform->addElement('textarea', 'appreciationglobale', get_string('capp_appreciation_globale', 'local_kid'), ['rows' => 5, 'cols' => 60]);
        $mform->setType('appreciationglobale', PARAM_TEXT);
        $mform->addElement('hidden', 'origappreciationglobale');
        $mform->setType('origappreciationglobale', PARAM_RAW);

        if (!empty($this->_customdata['readonly'])) {
            $mform->hardFreezeAllVisibleExcept([]);
        } else {
            $this->add_action_buttons(true, get_string('action_save', 'local_kid'));
        }
    }

    private function render_consultative(array $consult, string $label): string {
        if (empty($consult['count'])) {
            return \html_writer::tag('p', $label . ' : ' . get_string('capp_no_source', 'local_kid'), ['class' => 'kid-muted']);
        }
        $lines = '';
        foreach ($consult['items'] as $item) {
            $line = $item['label'];
            if (!empty($item['commentaire'])) {
                $line .= ' — ' . shorten_text(strip_tags($item['commentaire']), 120);
            }
            $lines .= \html_writer::tag('li', $line);
        }
        return \html_writer::tag('strong', $label . ' (' . $consult['count'] . ')') . \html_writer::tag('ul', $lines);
    }

    /**
     * Read-only "Niveau CAPP N : …" lines, one per CAPP session strictly
     * before this one in the promotion's ordered sequence (see
     * pages/capp.php, built on capp_repository::get_niveau_history() /
     * get_active_sessions_for_promotion() — the same ordering the
     * "Récupérer les niveaux" link already relies on via
     * get_previous_session()), in ascending order. Replaces the former
     * single, always-highlighted "CAPP précédent" line: plain text label
     * like the Enseignements/Stages lines above (no highlight), one line
     * per prior session instead of only the immediately preceding one.
     * Empty array on the promotion's first CAPP session → no lines at all.
     * The niveau badge itself uses the same markup/CSS as the "current
     * niveau" reminder in entry_grid_form.php (niveau_repository::
     * badge_class()) — single source of truth for the badge palette. A
     * null niveau means no saisie exists at all for that (session,
     * competency, student) — distinct from an explicit "Non observé"
     * result, which is a real niveau record and gets its badge like any
     * other level (see capp_repository::get_niveau_history()).
     *
     * @param array<array{shortname: string, niveau: ?\stdClass}> $priors
     */
    private function render_priors(array $priors): string {
        $lines = '';
        foreach ($priors as $prior) {
            $label = get_string('capp_niveau_of', 'local_kid', $prior['shortname']);
            $niveau = $prior['niveau'];
            if (!$niveau) {
                $lines .= \html_writer::tag('p', $label . ' : —', ['class' => 'kid-muted']);
                continue;
            }
            $badge = \html_writer::tag('span', s($niveau->libelle), [
                'class' => 'fr-badge kid-level-badge ' . \local_kid\local\niveau_repository::badge_class($niveau->code),
            ]);
            $lines .= \html_writer::tag('p', $label . ' : ' . $badge);
        }
        return $lines;
    }
}
