<?php
/**
 * Academic-calendar helpers, shared by Settings, attendance day-counts and reports.
 *
 * The multi_calendar add-on adds a `programme_level` dimension to school_terms so
 * SHS / JHS / Primary can run a term on different dates. When the add-on is not
 * licensed everything collapses to the single 'All' (school-wide) calendar, which
 * is also the fallback whenever a level has no dedicated row.
 */

if (!function_exists('calendar_ensure_schema')) {

    /** Programme levels a term can target (must mirror the class-level list + 'All'). */
    function calendar_levels(): array
    {
        return ['All', 'KG', 'Lower Primary', 'Upper Primary', 'JHS', 'SHS', 'Other'];
    }

    /** Is the multi-level calendar add-on active? */
    function calendar_multilevel_enabled(): bool
    {
        return function_exists('hasModule') && hasModule('multi_calendar');
    }

    /**
     * Ensure school_terms carries the programme_level column + composite unique key.
     * Safe to call on every request; runs its ALTERs at most once per request and
     * silently no-ops when already migrated.
     */
    function calendar_ensure_schema(mysqli $conn): void
    {
        static $done = false;
        if ($done) return;
        $done = true;

        // Base table (in case this runs before school_calendar_ajax.php).
        $conn->query("CREATE TABLE IF NOT EXISTS school_terms (
            id INT AUTO_INCREMENT PRIMARY KEY,
            academic_year VARCHAR(20) NOT NULL,
            term VARCHAR(20) NOT NULL,
            start_date DATE NOT NULL,
            end_date DATE NOT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci");

        // Add column if missing.
        $res = $conn->query("SHOW COLUMNS FROM school_terms LIKE 'programme_level'");
        if ($res && $res->num_rows === 0) {
            @$conn->query("ALTER TABLE school_terms ADD COLUMN programme_level VARCHAR(30) NOT NULL DEFAULT 'All' AFTER term");
        }

        // Swap unique index (year,term) -> (year,term,programme_level).
        $hasOld = false; $hasNew = false;
        $idx = $conn->query("SHOW INDEX FROM school_terms");
        while ($idx && $row = $idx->fetch_assoc()) {
            if ($row['Key_name'] === 'unique_term')       $hasOld = true;
            if ($row['Key_name'] === 'unique_term_level') $hasNew = true;
        }
        if ($hasOld) @$conn->query("ALTER TABLE school_terms DROP INDEX unique_term");
        if (!$hasNew) @$conn->query("ALTER TABLE school_terms ADD UNIQUE KEY unique_term_level (academic_year, term, programme_level)");
    }

    /** Map a class level (from classes.class_level) to a calendar programme level. */
    function calendar_class_to_level(?string $classLevel): string
    {
        $classLevel = trim((string) $classLevel);
        $valid = calendar_levels();
        return in_array($classLevel, $valid, true) && $classLevel !== '' ? $classLevel : 'All';
    }

    /**
     * Resolve term start/end dates for a given programme level, falling back to the
     * school-wide 'All' calendar when the level has no dedicated row.
     * Returns ['start_date'=>..,'end_date'=>..,'programme_level'=>..] or null.
     */
    function getTermDatesForLevel(mysqli $conn, string $level, string $academicYear, string $term): ?array
    {
        calendar_ensure_schema($conn);
        $level = $level === '' ? 'All' : $level;

        // Level-specific first, then 'All'.
        foreach ([$level, 'All'] as $lvl) {
            $stmt = $conn->prepare("SELECT start_date, end_date, programme_level
                                    FROM school_terms
                                    WHERE academic_year=? AND term=? AND programme_level=? LIMIT 1");
            $stmt->bind_param('sss', $academicYear, $term, $lvl);
            $stmt->execute();
            $row = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            if ($row) return $row;
            if ($level === 'All') break; // no point re-querying the same thing
        }
        return null;
    }
}
