<?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();

/**
 * Creates/updates the local_kid functional roles and their capability
 * assignments. Shared by db/install.php (fresh install) and db/upgrade.php
 * (16-capability migration), so the role definitions live in exactly one
 * place.
 */
class role_setup {

    /** @var array Shortname => [name, description, capabilities[]]. CAP_ALLOW only, never CAP_PROHIBIT, so roles stay cumulable. */
    const FUNCTIONAL_ROLES = [
        'local_kid_gest_scolarite' => [
            'name' => 'Gestionnaire scolarité (KID)',
            'description' => 'Évaluations et CAPP : saisie/validation/publication, gestion du référentiel des évaluations, synchronisation des devoirs Moodle.',
            'capabilities' => [
                'local/kid:view', 'local/kid:evaluate_evaluation', 'local/kid:evaluate_capp',
                'local/kid:sync_moodle', 'local/kid:publish_evaluation', 'local/kid:publish_capp',
                'local/kid:manage_evaluation', 'local/kid:selectpromotion', 'local/kid:viewany',
                'local/kid:viewjournal', 'local/kid:viewannuaire', 'local/kid:managedashboardfavourites',
            ],
        ],
        'local_kid_gest_stages' => [
            'name' => 'Gestionnaire stages (KID)',
            'description' => 'Stages et CAPP : saisie/validation/publication, gestion du référentiel des stages.',
            'capabilities' => [
                'local/kid:view', 'local/kid:evaluate_stage', 'local/kid:evaluate_capp',
                'local/kid:publish_stage', 'local/kid:publish_capp',
                'local/kid:manage_stage', 'local/kid:selectpromotion', 'local/kid:viewany',
                'local/kid:viewjournal', 'local/kid:viewannuaire', 'local/kid:managedashboardfavourites',
            ],
        ],
        'local_kid_membre_capp' => [
            'name' => 'Membre CAPP (KID)',
            'description' => 'Consulte et saisit/valide/publie les trois domaines (évaluations, stages, CAPP), sans droits d\'administration du référentiel.',
            'capabilities' => [
                'local/kid:view', 'local/kid:evaluate_evaluation', 'local/kid:evaluate_stage', 'local/kid:evaluate_capp',
                'local/kid:publish_evaluation', 'local/kid:publish_stage', 'local/kid:publish_capp',
                'local/kid:selectpromotion', 'local/kid:viewany',
                'local/kid:viewjournal', 'local/kid:viewannuaire', 'local/kid:managedashboardfavourites',
            ],
        ],
        'local_kid_admin' => [
            'name' => 'Administrateur (KID)',
            'description' => 'Toutes les capacités du plugin, y compris l\'administration générale, l\'export ADESI et la vue élève (pour test).',
            'capabilities' => [
                'local/kid:view', 'local/kid:evaluate_evaluation', 'local/kid:evaluate_stage', 'local/kid:evaluate_capp',
                'local/kid:sync_moodle', 'local/kid:publish_evaluation', 'local/kid:publish_stage', 'local/kid:publish_capp',
                'local/kid:manage_evaluation', 'local/kid:manage_stage', 'local/kid:manage_capp', 'local/kid:manage',
                'local/kid:export_adesi', 'local/kid:selectpromotion', 'local/kid:viewany', 'local/kid:viewown',
                'local/kid:viewjournal', 'local/kid:viewannuaire', 'local/kid:managedashboardfavourites',
            ],
        ],
    ];

    /** @var string[] Custom roles from the previous 11-capability model, removed by the migration (test environment, no assignment to preserve). */
    const LEGACY_ROLES = ['kid_scolarite', 'kid_capp', 'kid_assistant'];

    /**
     * Creates the 4 functional roles (idempotent: creation is skipped if
     * the role already exists, but the capability assignment loop always
     * re-runs, itself idempotent) and re-applies the teacher-widening and
     * viewown grants.
     */
    public static function create_functional_roles(): void {
        global $DB;

        $systemcontext = \context_system::instance();

        foreach (self::FUNCTIONAL_ROLES as $shortname => $def) {
            $roleid = $DB->get_field('role', 'id', ['shortname' => $shortname]);
            if (!$roleid) {
                $roleid = create_role($def['name'], $shortname, $def['description'], '');
                set_role_contextlevels($roleid, [CONTEXT_SYSTEM]);
            }
            foreach ($def['capabilities'] as $capability) {
                assign_capability($capability, CAP_ALLOW, $roleid, $systemcontext->id, true);
            }
        }

        // Décision produit : « Personnel INSP (lecteur) » (shortname `teacher`)
        // reçoit un accès lecture seule au tableau de bord. Voir
        // access_helper::has_capability_or_teacher(), utilisé par tout le code
        // applicatif au lieu de has_capability() nu pour ces deux capacités.
        $teacherroleid = $DB->get_field('role', 'id', ['shortname' => 'teacher']);
        if ($teacherroleid) {
            foreach (\local_kid\local\access_helper::TEACHER_WIDENED_CAPABILITIES as $capability) {
                assign_capability($capability, CAP_ALLOW, $teacherroleid, $systemcontext->id, true);
            }
        }

        // Élève : `viewown` accordé à Authenticated user (id 7), restriction
        // réelle de propriété appliquée en code (pages/student.php).
        $authuserroleid = $DB->get_field('role', 'id', ['shortname' => 'user']);
        if ($authuserroleid) {
            assign_capability('local/kid:viewown', CAP_ALLOW, $authuserroleid, $systemcontext->id, true);
        }

        accesslib_clear_all_caches(false);
    }

    /**
     * Removes the 3 custom roles from the previous 11-capability model.
     * Safe to call even if a role no longer exists.
     */
    public static function remove_legacy_roles(): void {
        global $DB;

        foreach (self::LEGACY_ROLES as $shortname) {
            $roleid = $DB->get_field('role', 'id', ['shortname' => $shortname]);
            if ($roleid) {
                delete_role($roleid);
            }
        }

        accesslib_clear_all_caches(false);
    }
}
