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

namespace local_kid\local;

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

/**
 * The 5-level scale is fixed at install and can only be renamed/restyled —
 * deliberately no delete() method anywhere in this class (not just a hidden
 * button): removing a level would break every existing rating that
 * references it.
 */
class niveau_repository {

    /**
     * Fixed code → CSS badge class map, single point of truth for the
     * niveau badge palette (matches the InterfaceEvaluation React
     * prototype). Keyed on `code` (COMPETENCE0..4, seeded in install.php)
     * deliberately, not `libelle` or `sortorder` — both of those are
     * admin-editable via local_kid_niveau_form, `code` is the only field
     * that's guaranteed stable across the fixed 5-level scale.
     */
    private const BADGE_CLASSES = [
        'COMPETENCE0' => 'kid-level-nonobserve',
        'COMPETENCE1' => 'kid-level-nonacquis',
        'COMPETENCE2' => 'kid-level-encours',
        'COMPETENCE3' => 'kid-level-acquis',
        'COMPETENCE4' => 'kid-level-depasse',
    ];

    /** @param ?string $code a niveau's `code` field; null/unknown returns ''. */
    public static function badge_class(?string $code): string {
        return self::BADGE_CLASSES[$code] ?? '';
    }

    /**
     * Fixed code -> {bg, fg} hex pair, single point of truth for the badge
     * palette's actual colours — kept here rather than only in CSS because
     * pdf_service.php can't read a stylesheet (TCPDF's HTML renderer needs
     * inline styles). Values must stay byte-identical to styles/local_kid.css's
     * .kid-level-* rules (see the comment there); nothing enforces that
     * automatically, so update both together.
     */
    private const BADGE_COLORS = [
        'COMPETENCE0' => ['bg' => '#EEEEEE', 'fg' => '#666666'],
        'COMPETENCE1' => ['bg' => '#FFE9E9', 'fg' => '#CE0500'],
        'COMPETENCE2' => ['bg' => '#FFE9E6', 'fg' => '#B34000'],
        'COMPETENCE3' => ['bg' => '#B8FEC9', 'fg' => '#18753C'],
        'COMPETENCE4' => ['bg' => '#E8EDFF', 'fg' => '#0063CB'],
    ];

    /** @param ?string $code a niveau's `code` field; null/unknown falls back to the "non observé" pair. */
    public static function badge_colors(?string $code): array {
        return self::BADGE_COLORS[$code] ?? self::BADGE_COLORS['COMPETENCE0'];
    }

    /**
     * Same palette, keyed on the folded display_bucket() values instead of
     * `code` — for the CAPP Bilan général summary table, whose 4 columns
     * (Acquis DLA folding COMPETENCE3+4) don't map 1:1 to a single code.
     * 'acquisdla' deliberately reuses COMPETENCE3's colour, not a blend.
     */
    private const BUCKET_COLORS = [
        'nonobserve' => ['bg' => '#EEEEEE', 'fg' => '#666666'],
        'nonacquis' => ['bg' => '#FFE9E9', 'fg' => '#CE0500'],
        'encours' => ['bg' => '#FFE9E6', 'fg' => '#B34000'],
        'acquisdla' => ['bg' => '#B8FEC9', 'fg' => '#18753C'],
    ];

    /** @param string $bucket one of display_bucket()'s return values; unknown falls back to "non observé". */
    public static function bucket_colors(string $bucket): array {
        return self::BUCKET_COLORS[$bucket] ?? self::BUCKET_COLORS['nonobserve'];
    }

    /**
     * Fixed code → display-bucket map for the CAPP Bilan général count
     * table (see capp_rapport_builder::build_bilan()): Acquis (COMPETENCE3)
     * and Dépasse les attentes (COMPETENCE4) are counted together as
     * "Acquis DLA" — storage (local_kid_capp_result.niveauid) always keeps
     * them distinct, this only folds them for display/counting. Single
     * point of truth so a future second caller of the same fold can't
     * drift from this one.
     */
    private const DISPLAY_BUCKETS = [
        'COMPETENCE0' => 'nonobserve',
        'COMPETENCE1' => 'nonacquis',
        'COMPETENCE2' => 'encours',
        'COMPETENCE3' => 'acquisdla',
        'COMPETENCE4' => 'acquisdla',
    ];

    /**
     * @param ?string $code a niveau's `code` field; null/unknown counts as
     *        "non observé" — same convention used elsewhere in this plugin
     *        for "compétence couverte mais aucun résultat saisi" (see
     *        adesi_export_service, comparateur_repository).
     */
    public static function display_bucket(?string $code): string {
        return self::DISPLAY_BUCKETS[$code] ?? 'nonobserve';
    }

    public static function get_all(): array {
        global $DB;
        return $DB->get_records('local_kid_niveau', null, 'sortorder ASC');
    }

    public static function get(int $id): ?\stdClass {
        global $DB;
        return $DB->get_record('local_kid_niveau', ['id' => $id], '*', IGNORE_MISSING) ?: null;
    }

    public static function update(int $id, string $libelle, string $couleur, int $sortorder, string $codeadesi, int $userid): void {
        global $DB;
        $DB->update_record('local_kid_niveau', (object) [
            'id' => $id,
            'libelle' => $libelle,
            'couleur' => $couleur,
            'sortorder' => $sortorder,
            'codeadesi' => $codeadesi,
            'timemodified' => time(),
            'usermodified' => $userid,
        ]);
    }
}
