<?= $this->extend('layouts/main') ?>
<?= $this->section('content') ?>

<?php
$schedId = (int)$schedule['id'];
$isPublished = $schedule['status'] === 'published';
$CSRF = csrf_hash();
$activeDaysArray = array_map('intval', explode(',', $schedule['active_days']));
$dayNames = ['', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];

// Preprocess timeslots
$timeslotsByDay = [];
foreach ($timeslots as $ts) {
    $timeslotsByDay[(int)$ts['day']][] = $ts;
}

// Preprocess classrooms by grade
$classroomsByGrade = [];
foreach ($classrooms as $cls) {
    $classroomsByGrade[$cls['grade_id']][] = $cls;
}

// Master grid pre-processing for Step 7
$classroomsMap = []; $teachersMap = []; $teacherMeta = [];
foreach ($gridData as $e) {
    $cid = (int)$e['classroom_id']; $tid = (int)$e['teacher_id'];
    if (!isset($classroomsMap[$cid])) $classroomsMap[$cid] = $e['classroom_name'];
    if (!isset($teachersMap[$tid])) {
        $teachersMap[$tid] = $e['teacher_name'];
        $teacherMeta[$tid] = [
            'name'    => $e['teacher_name'],
            'nip'     => $e['teacher_nip']     ?? '','nip_label' => guess_id_label($e['teacher_nip'] ?? null),
            'user_id' => $e['teacher_user_id'] ?? '',
            'color'   => $e['teacher_color']   ?? '',
        ];
    }
}
asort($classroomsMap); asort($teachersMap);

$teacherLockStatus = [];
foreach ($teachersMap as $tid => $tname) {
    $totalEntries = 0; $lockedEntries = 0;
    foreach ($gridData as $e) {
        if ((int)$e['teacher_id'] !== $tid) continue;
        $totalEntries++;
        if ((int)($e['is_locked'] ?? 0)) $lockedEntries++;
    }
    if ($totalEntries === 0)         $teacherLockStatus[$tid] = 'none';
    elseif ($lockedEntries === 0)    $teacherLockStatus[$tid] = 'none';
    elseif ($lockedEntries === $totalEntries) $teacherLockStatus[$tid] = 'all';
    else                             $teacherLockStatus[$tid] = 'partial';
}

$teacherPalettes = []; // Kept for compatibility

function hslToHex($h, $s, $l) {
    $h /= 360;
    $s /= 100;
    $l /= 100;

    $r = $l;
    $g = $l;
    $b = $l;

    $v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
    if ($v > 0) {
        $m = $l + $l - $v;
        $sv = ($v - $m) / $v;
        $h *= 6.0;
        $sextant = floor($h);
        $fract = $h - $sextant;
        $vsf = $v * $sv * $fract;
        $mid1 = $m + $vsf;
        $mid2 = $v - $vsf;

        switch ($sextant) {
            case 0: $r = $v; $g = $mid1; $b = $m; break;
            case 1: $r = $mid2; $g = $v; $b = $m; break;
            case 2: $r = $m; $g = $v; $b = $mid1; break;
            case 3: $r = $m; $g = $mid2; $b = $v; break;
            case 4: $r = $mid1; $g = $m; $b = $v; break;
            case 5: $r = $v; $g = $m; $b = $mid2; break;
        }
    }

    $r = (int)round($r * 255);
    $g = (int)round($g * 255);
    $b = (int)round($b * 255);

    return sprintf("#%02x%02x%02x", $r, $g, $b);
}

function getContrastColor($hex) {
    $hex = ltrim($hex, '#');
    if (strlen($hex) !== 6) return '#000000';
    $r = hexdec(substr($hex, 0, 2));
    $g = hexdec(substr($hex, 2, 2));
    $b = hexdec(substr($hex, 4, 2));
    $luminance = (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255;
    return $luminance > 0.5 ? '#000000' : '#ffffff';
}

function getTeacherColor(int $tid, ?string $dbColor, array $p): array {
    if (!empty($dbColor) && strtolower($dbColor) !== '#cccccc') {
        return [
            'bg' => $dbColor,
            'text' => getContrastColor($dbColor),
            'border' => $dbColor
        ];
    }
    $hue = ($tid * 137.5) % 360;
    $sat = 70 + ($tid % 3) * 15;
    $lit = 40 + (($tid * 3) % 4) * 15;
    $bg = hslToHex($hue, $sat, $lit);
    $border = hslToHex($hue, $sat, max(25, $lit - 10));
    return [
        'bg' => $bg,
        'text' => getContrastColor($bg),
        'border' => $border
    ];
}

$subjColorsJs = [];
foreach ($gridData as $e) {
    $sid = (int)$e['school_subject_id'];
    if (!isset($subjColorsJs[$sid])) {
        $p = [
            ['bg'=>'#EBF5FF','border'=>'#93C5FD','text'=>'#1E40AF'],
            ['bg'=>'#F0FDF4','border'=>'#86EFAC','text'=>'#166534'],
            ['bg'=>'#FDF4FF','border'=>'#E879F9','text'=>'#86198F'],
            ['bg'=>'#FFF7ED','border'=>'#FDB261','text'=>'#9A3412'],
            ['bg'=>'#F0F9FF','border'=>'#7DD3FC','text'=>'#0C4A6E'],
        ];
        $subjColorsJs[$sid] = $p[$sid % count($p)];
    }
}
?>

<link rel="stylesheet" href="/css/wizard_style.css">
<style>
.avail-grid {
    grid-template-columns: 100px repeat(6, 1fr) !important;
}
.avail-grid-cell {
    aspect-ratio: auto !important;
    height: 58px !important;
    padding: 4px !important;
}

/* ─── ASC MATCHING CLASSES ─── */
.mt-cell { padding: 0 !important; height: 44px; }
.mt-chip { border-radius: 0; min-height: 44px; padding: 4px 2px; transition: opacity .25s, filter .25s; }
.mt-chip.dimmed, .ec.dimmed { opacity: .15 !important; filter: grayscale(100%) !important; pointer-events: none; }
.mt-chip.highlighted, .ec.highlighted { outline: 2px solid #fff; outline-offset: -2px; z-index: 1; position: relative; }

.schedule-matrix {
    table-layout: fixed;
    border-collapse: collapse;
    width: 100%;
}
.header-period-col {
    background: #1e3a5f;
    color: #fff;
    font-size: .75rem;
    padding: 6px 4px;
    min-width: 80px;
}
.header-day {
    background: #1e3a5f;
    color: #fff;
    padding: 5px 4px;
    min-width: 85px;
    font-size: .8rem;
}
.day-full {
    font-size: .65rem;
    opacity: .8;
    font-weight: normal;
}
.period-label {
    background: #f0f4f8;
    padding: 6px 4px;
}
.period-num {
    font-size: .9rem;
    font-weight: 700;
    line-height: 1.2;
}
.period-time {
    font-size: .65rem;
    color: #666;
    line-height: 1.2;
}
.schedule-cell {
    height: 65px;
    padding: 0 !important;
    transition: filter .15s;
}
.schedule-cell.has-slot:hover {
    filter: brightness(.88);
}
.empty-slot {
    background: #fafafa !important;
}
.slot-subject {
    font-size: .82rem;
    font-weight: 700;
    line-height: 1.2;
}
.slot-teacher {
    font-size: .7rem;
    line-height: 1.2;
    margin-top: 2px;
    opacity: .85;
}
.slot-class {
    font-size: .82rem;
    font-weight: 700;
    line-height: 1.2;
}
</style>

<!-- BREADCRUMB / MINI HEADER -->
<div class="d-flex align-items-center justify-content-between mb-4">
    <div class="d-flex align-items-center gap-2">
        <a href="/schedule-generator" class="btn btn-sm btn-outline-secondary">
            <i class="bi bi-arrow-left"></i> Kembali ke Daftar
        </a>
        <div>
            <h5 class="mb-0 fw-bold text-dark" id="headerScheduleName"><?= esc($schedule['name']) ?></h5>
            <small class="text-muted">
                Tahun Ajaran: <span class="fw-semibold text-dark"><?= esc($schedule['year_name'] ?? '-') ?></span> &bull; 
                Semester: <span class="fw-semibold text-dark"><?= esc($schedule['period_name'] ?? '-') ?></span>
            </small>
        </div>
    </div>
    <div>
        <span class="badge <?= $isPublished ? 'bg-success' : 'bg-warning text-dark' ?> px-3 py-2 fs-6 rounded-pill" id="headerScheduleStatus">
            <?= $isPublished ? '<i class="bi bi-check-circle-fill me-1"></i> Published' : '<i class="bi bi-file-earmark-diff me-1"></i> Draft' ?>
        </span>
    </div>
</div>

<div class="wizard-card">
    <!-- Header strip -->
    <div class="wizard-header-strip">
        <h4 id="wizardPanelTitle">Langkah 1: Informasi Umum & Hari Aktif</h4>
        <p id="wizardPanelSubtitle">Tentukan nama jadwal, catatan operasional, dan hari-hari di mana KBM berlangsung.</p>
    </div>

    <!-- Steps Tracker -->
    <div class="wizard-steps-track">
        <div class="wizard-steps-progress-line" id="wizardProgressLine"></div>
        
        <button class="wizard-step-node active" onclick="jumpToStep(1)">
            <div class="wizard-step-circle">1</div>
            <div class="wizard-step-label">Info &amp; Hari</div>
        </button>
        <button class="wizard-step-node" onclick="jumpToStep(2)">
            <div class="wizard-step-circle">2</div>
            <div class="wizard-step-label">Slot Waktu</div>
        </button>
        <button class="wizard-step-node" onclick="jumpToStep(3)">
            <div class="wizard-step-circle">3</div>
            <div class="wizard-step-label">Target JTM</div>
        </button>
        <button class="wizard-step-node" onclick="jumpToStep(4)">
            <div class="wizard-step-circle">4</div>
            <div class="wizard-step-label">Beban Kerja</div>
        </button>
        <button class="wizard-step-node" onclick="jumpToStep(5)">
            <div class="wizard-step-circle">5</div>
            <div class="wizard-step-label">Ketersediaan</div>
        </button>
        <button class="wizard-step-node" onclick="jumpToStep(6)">
            <div class="wizard-step-circle">6</div>
            <div class="wizard-step-label">Validator</div>
        </button>
        <button class="wizard-step-node" onclick="jumpToStep(7)">
            <div class="wizard-step-circle">7</div>
            <div class="wizard-step-label">Tinjau &amp; Publish</div>
        </button>
    </div>

    <!-- WIZARD PANELS CONTENT -->
    
    <!-- ── Step 1: Info Umum & Hari Aktif ── -->
    <div class="wizard-panel active" id="stepPanel1">
        <form id="formStep1">
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group-wizard">
                        <label for="inputName">Nama / Judul Jadwal</label>
                        <input type="text" class="input-wizard" id="inputName" name="name" value="<?= esc($schedule['name']) ?>" required>
                    </div>
                    <div class="form-group-wizard">
                        <label for="inputNotes">Catatan / Deskripsi</label>
                        <textarea class="input-wizard" id="inputNotes" name="notes" rows="4"><?= esc($schedule['notes']) ?></textarea>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group-wizard">
                        <label>Hari Aktif Pembelajaran</label>
                        <p class="text-muted small">Centang hari-hari aktif pembelajaran. Generator hanya akan menyusun jadwal pada hari yang dipilih.</p>
                        <div class="d-flex flex-column gap-2 mt-2">
                            <?php for ($d = 1; $d <= 6; $d++): ?>
                            <label class="d-flex align-items-center gap-2 fw-normal text-dark text-capitalize" style="font-size:0.9rem; cursor:pointer">
                                <input type="checkbox" name="active_days[]" value="<?= $d ?>" <?= in_array($d, $activeDaysArray) ? 'checked' : '' ?> style="width:18px; height:18px">
                                <?= $dayNames[$d] ?>
                            </label>
                            <?php endfor; ?>
                        </div>
                    </div>
                </div>
            </div>
        </form>
    </div>

    <!-- ── Step 2: Slot Waktu (Timeslots) ── -->
    <div class="wizard-panel" id="stepPanel2">
        <div class="row">
            <div class="col-lg-4">
                <div class="card shadow-sm border border-slate mb-3">
                    <div class="card-header bg-light py-2 fw-bold text-dark" style="font-size:0.85rem">TAMBAH SLOT WAKTU</div>
                    <div class="card-body">
                        <form id="formAddTimeslot">
                            <div class="form-group-wizard mb-2">
                                <label for="slotDay">Hari</label>
                                <select class="input-wizard" id="slotDay" name="day">
                                    <?php foreach ($activeDaysArray as $d): ?>
                                    <option value="<?= $d ?>"><?= $dayNames[$d] ?></option>
                                    <?php endforeach; ?>
                                </select>
                            </div>
                            <div class="row g-2 mb-2">
                                <div class="col-6">
                                    <div class="form-group-wizard mb-0">
                                        <label for="slotNumber">Slot Ke-</label>
                                        <input type="number" class="input-wizard text-center" id="slotNumber" name="slot_number" min="1" value="1" required>
                                    </div>
                                </div>
                                <div class="col-6">
                                    <div class="form-group-wizard mb-0">
                                        <label for="slotType">Tipe</label>
                                        <select class="input-wizard" id="slotType" name="slot_type">
                                            <option value="kbm">KBM</option>
                                            <option value="istirahat">Istirahat</option>
                                            <option value="upacara">Upacara</option>
                                            <option value="keagamaan">Keagamaan</option>
                                            <option value="lainnya">Lainnya</option>
                                        </select>
                                    </div>
                                </div>
                            </div>
                            <div class="form-group-wizard mb-2">
                                <label for="slotLabel">Label (misal: JP 1, Istirahat)</label>
                                <input type="text" class="input-wizard" id="slotLabel" name="label" placeholder="JP 1" required>
                            </div>
                            <div class="row g-2 mb-3">
                                <div class="col-6">
                                    <div class="form-group-wizard mb-0">
                                        <label for="slotStart">Mulai</label>
                                        <input type="time" class="input-wizard text-center" id="slotStart" name="start_time" required>
                                    </div>
                                </div>
                                <div class="col-6">
                                    <div class="form-group-wizard mb-0">
                                        <label for="slotEnd">Selesai</label>
                                        <input type="time" class="input-wizard text-center" id="slotEnd" name="end_time" required>
                                    </div>
                                </div>
                            </div>
                            <button type="submit" class="btn btn-primary w-100 btn-sm fw-bold">
                                <i class="bi bi-plus-circle me-1"></i> Tambah Slot
                            </button>
                        </form>
                    </div>
                </div>

                <div class="card shadow-sm border border-slate">
                    <div class="card-header bg-light py-2 fw-bold text-dark" style="font-size:0.85rem">SALIN HARI</div>
                    <div class="card-body">
                        <form id="formCopyTimeslots">
                            <div class="form-group-wizard mb-2">
                                <label for="copyFromDay">Dari Hari</label>
                                <select class="input-wizard" id="copyFromDay" name="from_day">
                                    <?php foreach ($activeDaysArray as $d): ?>
                                    <option value="<?= $d ?>"><?= $dayNames[$d] ?></option>
                                    <?php endforeach; ?>
                                </select>
                            </div>
                            <div class="form-group-wizard mb-3">
                                <label>Ke Hari (Bisa Pilih Banyak)</label>
                                <div class="d-flex flex-wrap gap-2 mt-1">
                                    <?php foreach ($activeDaysArray as $d): ?>
                                    <label class="d-flex align-items-center gap-1 fw-normal text-dark text-capitalize" style="font-size:0.85rem; cursor:pointer">
                                        <input type="checkbox" name="to_days[]" value="<?= $d ?>"> <?= $dayNames[$d] ?>
                                    </label>
                                    <?php endforeach; ?>
                                </div>
                            </div>
                            <button type="submit" class="btn btn-outline-primary w-100 btn-sm fw-bold">
                                <i class="bi bi-arrow-left-right me-1"></i> Salin Struktur
                            </button>
                        </form>
                    </div>
                </div>
            </div>
            <div class="col-lg-8">
                <!-- Tabs hari -->
                <div class="d-flex gap-2 mb-3 border-bottom pb-2 overflow-x-auto">
                    <?php foreach ($activeDaysArray as $i => $d): ?>
                    <button class="timeslot-day-tab <?= $i === 0 ? 'active' : '' ?>" data-day="<?= $d ?>" onclick="selectTimeslotDay(<?= $d ?>, this)">
                        <?= $dayNames[$d] ?>
                    </button>
                    <?php endforeach; ?>
                </div>

                <!-- Tabel list slot -->
                <div class="table-responsive">
                    <table class="table table-bordered table-sm align-middle" id="tableTimeslots" style="font-size:0.85rem">
                        <thead class="table-light">
                            <tr>
                                <th class="text-center" style="width:50px">Slot</th>
                                <th>Label</th>
                                <th class="text-center" style="width:120px">Tipe</th>
                                <th class="text-center" style="width:120px">Mulai</th>
                                <th class="text-center" style="width:120px">Selesai</th>
                                <th class="text-center" style="width:80px">Aktif</th>
                                <th class="text-center" style="width:100px">Aksi</th>
                            </tr>
                        </thead>
                        <tbody id="timeslotsListBody">
                            <!-- JS loaded contents -->
                        </tbody>
                    </table>
                </div>
                <div class="d-flex justify-content-end mt-2">
                    <button type="button" class="btn btn-outline-danger btn-sm fw-bold" onclick="clearActiveDayTimeslots()">
                        <i class="bi bi-trash me-1"></i> Kosongkan Hari Ini
                    </button>
                </div>
            </div>
        </div>
    </div>

    <!-- ── Step 3: Target JTM Kurikulum ── -->
    <div class="wizard-panel" id="stepPanel3">
        <div class="alert alert-info py-2 mb-3" style="font-size:0.85rem">
            <i class="bi bi-info-circle-fill me-1"></i>
            Silakan tentukan **Target Jam Tatap Muka (JTM)** per kelas dalam seminggu untuk tiap Mata Pelajaran berdasarkan Kurikulum Sekolah.
        </div>
        <div class="table-responsive" style="max-height:480px; overflow-y:auto">
            <table class="jtm-table">
                <thead>
                    <tr>
                        <th>Mata Pelajaran</th>
                        <th class="text-center" style="width:140px">Kelas VII</th>
                        <th class="text-center" style="width:140px">Kelas VIII</th>
                        <th class="text-center" style="width:140px">Kelas IX</th>
                        <th class="text-center" style="width:120px">Aksi</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($subjects as $s): 
                        $vii = $subjectTargets[$s['id']][1] ?? 0;
                        $viii = $subjectTargets[$s['id']][2] ?? 0;
                        $ix = $subjectTargets[$s['id']][3] ?? 0;
                    ?>
                    <tr data-subject-id="<?= $s['id'] ?>">
                        <td>
                            <div class="fw-bold text-dark"><?= esc($s['name']) ?></div>
                            <div class="text-muted small"><?= esc($s['code']) ?></div>
                        </td>
                        <td class="text-center">
                            <input type="number" class="jtm-input-field" data-grade="1" value="<?= $vii ?>" min="0" max="24">
                        </td>
                        <td class="text-center">
                            <input type="number" class="jtm-input-field" data-grade="2" value="<?= $viii ?>" min="0" max="24">
                        </td>
                        <td class="text-center">
                            <input type="number" class="jtm-input-field" data-grade="3" value="<?= $ix ?>" min="0" max="24">
                        </td>
                        <td class="text-center">
                            <button class="btn btn-sm btn-save-inline btn-wizard-action py-1 px-3" onclick="saveJtmTarget(<?= $s['id'] ?>, this)">
                                Simpan
                            </button>
                        </td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </div>

    <!-- ── Step 4: Alokasi Beban Mengajar & Auto-Split ── -->
    <div class="wizard-panel" id="stepPanel4">
        <div class="row">
            <div class="col-lg-5">
                <div class="card shadow-sm border border-slate">
                    <div class="card-header bg-light py-2 fw-bold text-dark" style="font-size:0.85rem">TAMBAH BEBAN MENGAJAR GURU</div>
                    <div class="card-body">
                        <form id="formAddLoad">
                            <div class="form-group-wizard mb-2">
                                <label for="loadTeacher">Guru Pengajar</label>
                                <select class="input-wizard" id="loadTeacher" name="teacher_id" required>
                                    <option value="">-- Pilih Guru --</option>
                                    <?php foreach ($teachers as $t): ?>
                                    <option value="<?= $t['id'] ?>"><?= esc($t['name']) ?></option>
                                    <?php endforeach; ?>
                                </select>
                            </div>
                            <div class="form-group-wizard mb-2">
                                <label for="loadSubject">Mata Pelajaran</label>
                                <select class="input-wizard" id="loadSubject" name="school_subject_id" required>
                                    <option value="">-- Pilih Mapel --</option>
                                    <?php foreach ($subjects as $sub): ?>
                                    <option value="<?= $sub['id'] ?>"><?= esc($sub['name']) ?> (<?= esc($sub['code']) ?>)</option>
                                    <?php endforeach; ?>
                                </select>
                            </div>
                            <div class="form-group-wizard mb-2">
                                <label>Rombel / Kelas</label>
                                <div class="border rounded p-2" style="max-height: 120px; overflow-y: auto; background:#ffffff">
                                    <?php foreach ($classrooms as $cls): ?>
                                    <label class="d-flex align-items-center gap-2 fw-normal text-dark text-capitalize" style="font-size:0.85rem; cursor:pointer">
                                        <input type="checkbox" name="classroom_ids[]" value="<?= $cls['id'] ?>" class="classroom-cb">
                                        <?= esc($cls['name']) ?>
                                    </label>
                                    <?php endforeach; ?>
                                </div>
                            </div>
                            <div class="row g-2 mb-3">
                                <div class="col-6">
                                    <div class="form-group-wizard mb-0">
                                        <label for="loadHours">Beban JTM (Jam/Minggu)</label>
                                        <input type="number" class="input-wizard text-center" id="loadHours" name="hours_per_week" min="1" max="18" required>
                                    </div>
                                </div>
                                <div class="col-6">
                                    <div class="form-group-wizard mb-0">
                                        <label for="loadSplit">Split Config (Pecah Jam)</label>
                                        <input type="text" class="input-wizard text-center" id="loadSplit" name="split_config" placeholder="contoh: 2,2">
                                    </div>
                                </div>
                            </div>
                            <div class="mb-2" id="suggestSplitContainer" style="display:none">
                                <span class="text-muted small d-block mb-1">Rekomendasi Split:</span>
                                <div id="suggestSplitPills" class="d-flex flex-wrap gap-1"></div>
                            </div>
                            <button type="submit" class="btn btn-primary w-100 btn-sm fw-bold">
                                <i class="bi bi-plus-circle me-1"></i> Alokasikan Beban
                            </button>
                        </form>
                    </div>
                </div>
            </div>
            <div class="col-lg-7">
                <div class="card shadow-sm border border-slate">
                    <div class="card-header bg-white py-2 d-flex justify-content-between align-items-center">
                        <span class="fw-bold text-dark" style="font-size:0.85rem">DAFTAR BEBAN MENGAJAR TERDAFTAR</span>
                        <div class="d-flex align-items-center gap-2">
                            <span class="badge bg-secondary" id="totalLoadsBadge">0 Beban</span>
                        </div>
                    </div>
                    <div class="card-body p-0">
                        <div class="p-2 border-bottom d-flex flex-wrap gap-2 justify-content-between align-items-center bg-light" id="bulkActionsBar" style="font-size:0.8rem">
                            <div class="d-flex gap-2">
                                <button type="button" class="btn btn-danger btn-xs py-1 px-2 fw-bold" id="btnBulkDelete" style="display:none" onclick="deleteBulkLoads()">
                                    <i class="bi bi-trash3 me-1"></i>Hapus Terpilih (<span id="bulkCount">0</span>)
                                </button>
                                <button type="button" class="btn btn-outline-danger btn-xs py-1 px-2 fw-bold" id="btnClearTeacher" style="display:none" onclick="clearTeacherLoads()">
                                    <i class="bi bi-x-circle me-1"></i>Kosongkan Beban Guru
                                </button>
                            </div>
                            <div class="form-check form-switch mb-0">
                                <input class="form-check-input" type="checkbox" id="switchShowAllLoads" checked onclick="toggleShowAllLoads(this)">
                                <label class="form-check-label fw-semibold" for="switchShowAllLoads" style="cursor:pointer">Tampilkan Semua Guru</label>
                            </div>
                        </div>
                        <div class="table-responsive" style="max-height: 400px; overflow-y: auto">
                            <table class="table table-sm align-middle mb-0" id="tableLoads" style="font-size:0.85rem">
                                <thead class="table-light">
                                    <tr>
                                        <th style="width:30px" class="text-center">
                                            <input type="checkbox" id="selectAllLoads" onclick="toggleSelectAllLoads(this)">
                                        </th>
                                        <th>Guru</th>
                                        <th>Mapel</th>
                                        <th>Kelas</th>
                                        <th class="text-center" style="width:70px">JTM</th>
                                        <th class="text-center" style="width:100px">Split</th>
                                        <th class="text-center" style="width:70px">Aksi</th>
                                    </tr>
                                </thead>
                                <tbody id="loadsListBody">
                                    <?php foreach ($scheduleLoads as $l): ?>
                                    <tr data-load-id="<?= $l['id'] ?>" data-teacher-id="<?= $l['teacher_id'] ?>">
                                        <td class="text-center">
                                            <input type="checkbox" class="load-item-cb" value="<?= $l['id'] ?>" onclick="updateBulkDeleteUI()">
                                        </td>
                                        <td><strong><?= esc($l['teacher_name']) ?></strong></td>
                                        <td><?= esc($l['subject_name']) ?></td>
                                        <td><?= esc($l['classroom_name']) ?></td>
                                        <td class="text-center fw-bold"><?= $l['hours_per_week'] ?> jam</td>
                                        <td class="text-center">
                                            <?php 
                                            $blocks = explode(',', $l['split_config']);
                                            foreach ($blocks as $b):
                                            ?>
                                            <span class="load-split-badge"><?= $b ?> JP</span>
                                            <?php endforeach; ?>
                                        </td>
                                        <td class="text-center">
                                            <button class="btn btn-outline-danger btn-xs py-0 px-2" onclick="deleteLoad(<?= $l['id'] ?>, this)">
                                                <i class="bi bi-trash3"></i>
                                            </button>
                                        </td>
                                    </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- ── Step 5: Batasan & Ketersediaan Guru ── -->
    <div class="wizard-panel" id="stepPanel5">
        <div class="row">
            <div class="col-lg-3">
                <div class="card shadow-sm border border-slate mb-3">
                    <div class="card-header bg-light py-2 fw-bold text-dark" style="font-size:0.85rem">PENGATURAN GLOBAL</div>
                    <div class="card-body">
                        <div class="form-group-wizard mb-3">
                            <label for="globalMaxHoursInput">Max Jam per Hari</label>
                            <input type="number" class="input-wizard text-center" id="globalMaxHoursInput" value="<?= $globalMaxHours ?>" min="1" max="12">
                            <small class="text-muted d-block mt-1">Batas maksimum default jam mengajar guru dalam sehari.</small>
                        </div>
                        <button class="btn btn-primary w-100 btn-sm fw-bold" onclick="saveGlobalMaxHours()">
                            Simpan Aturan Global
                        </button>
                    </div>
                </div>
                <div class="card shadow-sm border border-slate">
                    <div class="card-header bg-light py-2 fw-bold text-dark" style="font-size:0.85rem">PILIH GURU</div>
                    <div class="card-body p-0">
                        <div style="max-height: 250px; overflow-y: auto" id="availTeacherList">
                            <?php foreach ($teachers as $i => $t): ?>
                            <div class="avail-teacher-list-item <?= $i === 0 ? 'active' : '' ?>" data-teacher-id="<?= $t['id'] ?>" onclick="selectAvailTeacher(<?= $t['id'] ?>, this)">
                                <div><?= esc($t['name']) ?></div>
                                <small class="text-muted"><?= esc(teacher_id_display($t)) ?></small>
                            </div>
                            <?php endforeach; ?>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-lg-9">
                <div class="card shadow-sm border border-slate">
                    <div class="card-header bg-white py-2 d-flex justify-content-between align-items-center">
                        <span class="fw-bold text-dark" id="availTeacherNameTitle">Memuat Ketersediaan Guru...</span>
                        <div class="d-flex gap-2">
                            <button class="btn btn-outline-secondary btn-xs py-1 px-2" onclick="resetAvailTeacher()">Reset Semua Blokir</button>
                            <button class="btn btn-success btn-xs py-1 px-2" onclick="saveAvailTeacherGrid()">Simpan Grid</button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="row align-items-center mb-3">
                            <div class="col-md-5">
                                <label for="teacherMaxHoursInput" class="fw-bold" style="font-size:0.8rem">Batas Khusus Jam Guru / Hari</label>
                                <div class="d-flex gap-2 align-items-center mt-1">
                                    <input type="number" class="input-wizard text-center" id="teacherMaxHoursInput" placeholder="Sama dg Global" min="1" max="12" style="width:100px">
                                    <button class="btn btn-primary btn-sm py-1 px-3" onclick="saveTeacherSettings()">Simpan Batas</button>
                                </div>
                            </div>
                            <div class="col-md-7 text-end">
                                <span class="badge bg-success me-1">&nbsp;</span> Hijau = Guru Bersedia
                                <span class="badge bg-danger ms-2 me-1">&nbsp;</span> Merah = Guru Libur / Blokir (KBM Dilarang)
                            </div>
                        </div>

                        <!-- Grid ketersediaan -->
                        <div id="teacherAvailGridContainer">
                            <!-- JS loaded grid -->
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- ── Step 6: Pre-Validasi & Pemicu Generator ── -->
    <div class="wizard-panel" id="stepPanel6">
        <div class="row">
            <div class="col-lg-8">
                <div class="card shadow-sm border border-slate mb-3">
                    <div class="card-header bg-white py-2 d-flex align-items-center justify-content-between">
                        <span class="fw-bold text-dark"><i class="bi bi-shield-check me-2 text-primary"></i>STATUS PRE-VALIDASI DATA</span>
                        <button class="btn btn-sm btn-outline-primary" onclick="loadValidationStep()">
                            <i class="bi bi-arrow-repeat me-1"></i> Jalankan Validasi
                        </button>
                    </div>
                    <div class="card-body" id="validationWizardContent">
                        <!-- JS Loaded Validation content -->
                    </div>
                </div>
            </div>
            <div class="col-lg-4">
                <div class="card shadow-sm border border-slate mb-3">
                    <div class="card-header bg-light py-2 fw-bold text-dark" style="font-size:0.85rem">PENGATURAN GENERATOR</div>
                    <div class="card-body">
                        <div class="form-check mb-3">
                            <input class="form-check-input" type="checkbox" id="keepManualCb">
                            <label class="form-check-label text-dark fw-normal" for="keepManualCb" style="font-size:12px">
                                Pertahankan entry manual / terkunci
                            </label>
                        </div>
                        <button class="btn-generate mb-3" id="btnRunWizardGenerator" disabled>
                            <i class="bi bi-lightning-charge-fill"></i> Mulai Generate Jadwal
                        </button>

                        <div class="gen-progress-wrap" id="genProgressWrap" style="display:none">
                            <div class="gen-progress-bar">
                                <div class="gen-progress-fill" id="genProgressFill"></div>
                            </div>
                            <div class="gen-progress-label text-dark" id="genProgressLabel">Memproses...</div>
                        </div>
                    </div>
                </div>

                <div class="card shadow-sm border border-slate">
                    <div class="card-header bg-dark text-white py-1 fw-bold" style="font-size:0.85rem">CONSOLE RUN LOG</div>
                    <div class="card-body p-0">
                        <div class="log-wrap" id="generateLog" style="height: 180px; display: block">
                            <div class="log-line log-info">⚡ Terminal Siap. Klik generate...</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- ── Step 7: Tinjau Jadwal & Publikasikan ── -->
    <div class="wizard-panel" id="stepPanel7">
        <!-- Visual Mode Selector -->
        <div class="d-flex justify-content-between align-items-center mb-3">
            <div class="vmode-bar no-print m-0">
                <button class="vmode-btn active" onclick="switchTimetableMode('master',this)"><i class="bi bi-table me-1"></i>Master Timetable</button>
                <button class="vmode-btn" onclick="switchTimetableMode('classroom',this)"><i class="bi bi-door-open me-1"></i>Per Kelas</button>
                <button class="vmode-btn" onclick="switchTimetableMode('teacher',this)"><i class="bi bi-person-badge me-1"></i>Per Guru</button>
            </div>
            
            <div class="d-flex gap-2">
                <a href="/schedule-generator/reset/<?= $schedId ?>" class="btn btn-outline-danger btn-sm" onclick="return confirmReset(event, this)">
                    <i class="bi bi-arrow-counterclockwise me-1"></i> Reset
                </a>
                <?php if (!$isPublished): ?>
                <a href="/schedule-generator/publish/<?= $schedId ?>" class="btn btn-success btn-sm" onclick="return confirmPublish(event, this)">
                    <i class="bi bi-send-check me-1"></i> Publish Ke Guru
                </a>
                <?php else: ?>
                <button class="btn btn-secondary btn-sm" disabled><i class="bi bi-check-circle-fill me-1"></i> Published</button>
                <?php endif; ?>
            </div>
        </div>

        <!-- Timetable Panels -->
        <div id="timetableModeMaster" class="timetable-mode-panel active">
            <!-- Legend guru -->
            <div class="legend-panel no-print mb-2">
                <div class="legend-panel-title"><i class="bi bi-palette me-1"></i>Kode Guru — Klik highlight &amp; lock</div>
                <div class="legend-grid" id="teacherLegend">
                    <?php foreach ($teachersMap as $tid => $tname):
                        $meta = $teacherMeta[$tid] ?? ['name'=>$tname, 'nip'=>'', 'user_id'=>'', 'color'=>''];
                        $tc = getTeacherColor((int)$tid, $meta['color'] ?? '', $teacherPalettes);
                        $status = $teacherLockStatus[$tid] ?? 'none';
                        $uid = $meta['user_id'] ?: '-';
                    ?>
                    <div class="legend-item <?= $status==='all'?'is-locked-teacher':'' ?>"
                         style="background:<?= $tc['bg'] ?>;color:<?= $tc['text'] ?>;border-color:<?= $tc['border'] ?>"
                         data-teacher-id="<?= $tid ?>"
                         data-lock-status="<?= $status ?>"
                         onclick="highlightTeacherInTimetable(<?= $tid ?>, this)"
                         title="<?= esc($tname) ?> | ID: <?= esc($uid) ?>">
                        <span class="legend-sw" style="background:<?= $tc['text'] ?>22;outline:1px solid <?= $tc['border'] ?>"></span>
                        <span><?= esc(mb_substr($tname,0,16,'UTF-8')) ?></span>
                        <span class="legend-lock">🔒</span>
                    </div>
                    <?php endforeach; ?>
                </div>
            </div>

            <!-- Lock Action Bar -->
            <div class="lock-action-bar no-print mb-2" id="timetableLockBar">
                <div class="teacher-info">
                    <div><strong id="timetableLockName">—</strong> <span class="ms-2 badge rounded-pill" id="timetableLockBadge" style="font-size:10px"></span></div>
                    <small id="timetableLockSub" class="text-muted"></small>
                </div>
                <button class="btn btn-sm btn-warning" onclick="lockHighlightedTeacher('lock')"><i class="bi bi-lock-fill me-1"></i>Kunci Jadwal Guru</button>
                <button class="btn btn-sm btn-outline-secondary" onclick="lockHighlightedTeacher('unlock')"><i class="bi bi-unlock me-1"></i>Buka Kunci</button>
                <button class="btn btn-sm btn-outline-light border" onclick="clearTimetableHighlight()"><i class="bi bi-x"></i></button>
            </div>

            <!-- Master Timetable Grid -->
            <div class="card border-0 shadow-sm">
                <div class="card-body p-0">
                    <div class="mt-wrap" style="max-height: 500px; overflow-y: auto">
                        <table class="mt-table" id="masterTimetableTable">
                            <thead>
                                <tr>
                                    <th class="mt-col-day">Hari</th>
                                    <th class="mt-col-jam">Jam</th>
                                    <?php foreach ($classroomsMap as $cid => $cname): ?>
                                    <th class="mt-cls-th"><?= esc($cname) ?></th>
                                    <?php endforeach; ?>
                                </tr>
                            </thead>
                            <tbody>
                            <?php
                            $allSlotNumbers = [];
                            foreach ($timeslotsByDay as $day => $slots) {
                                foreach ($slots as $ts) {
                                    $allSlotNumbers[$ts['slot_number']] = true;
                                }
                            }
                            ksort($allSlotNumbers);
                            $allSlotNumbers = array_keys($allSlotNumbers);

                            $dayRowCount = [];
                            foreach ($activeDaysArray as $dayNum) {
                                $cnt = 0;
                                foreach ($allSlotNumbers as $slotNum) {
                                    if (isset($timeslotsByDay[$dayNum])) {
                                        $daySlots = array_column($timeslotsByDay[$dayNum], 'slot_number');
                                        if (in_array($slotNum, $daySlots)) $cnt++;
                                    }
                                }
                                $dayRowCount[$dayNum] = $cnt;
                            }

                            $prevDay = null;
                            foreach ($activeDaysArray as $dayNum):
                                $daySlots = $timeslotsByDay[$dayNum] ?? [];
                                foreach ($allSlotNumbers as $slotNum):
                                    $slotRow = null;
                                    foreach ($daySlots as $ds) {
                                        if ((int)$ds['slot_number'] === $slotNum) {
                                            $slotRow = $ds; break;
                                        }
                                    }
                                    if (!$slotRow) continue;

                                    $isKbm = ($slotRow['slot_type'] === 'kbm');
                                    $isNewDay = ($prevDay !== $dayNum);
                                    $prevDay = $dayNum;
                                    $rowspan = $dayRowCount[$dayNum];
                            ?>
                            <?php if ($isKbm): ?>
                            <tr class="<?= $isNewDay ? 'mt-day-sep' : '' ?>">
                                <?php if ($isNewDay): ?>
                                <td class="mt-col-day" rowspan="<?= $rowspan ?>">
                                    <div class="day-vert"><?= $dayNames[$dayNum] ?></div>
                                </td>
                                <?php endif; ?>
                                <td class="mt-col-jam">
                                    <div style="font-weight:700;font-size:11px;color:#1f2937;line-height:1.2"><?= esc($slotRow['label']) ?></div>
                                    <div style="font-size:9px;color:#9ca3af"><?= substr($slotRow['start_time'],0,5) ?>–<?= substr($slotRow['end_time'],0,5) ?></div>
                                </td>
                                <?php foreach ($classroomsMap as $cid => $cname):
                                    // Cari entry di gridData
                                    $cellEntries = [];
                                    foreach ($gridData as $gd) {
                                        if ((int)$gd['day'] === $dayNum && (int)$gd['slot_number'] === $slotNum && (int)$gd['classroom_id'] === $cid) {
                                            $cellEntries[] = $gd;
                                        }
                                    }
                                    $isClash = count($cellEntries) > 1;
                                ?>
                                <td class="mt-cell <?= $isClash ? 'table-danger' : '' ?>">
                                    <?php foreach ($cellEntries as $entry): 
                                         $tc = getTeacherColor((int)$entry['teacher_id'], $entry['teacher_color'], $teacherPalettes);
                                         $locked = (int)($entry['is_locked'] ?? 0);
                                         $teacherCodeDisplay = esc($entry['teacher_short_code'] ?: ($entry['teacher_user_id'] ?: substr($entry['teacher_name'], 0, 10)));
                                         $code = esc($entry['subject_code'] ?: substr($entry['subject_name'], 0, 6));
                                     ?>
                                     <div class="mt-chip <?= $locked ? 'is-locked' : '' ?>"
                                          style="background:<?= $tc['bg'] ?>;color:<?= $tc['text'] ?>;border-color:<?= $isClash ? '#ef4444' : $tc['border'] ?>; <?= $isClash ? 'border-width:2px; font-weight:bold;' : '' ?>"
                                          data-teacher-id="<?= $entry['teacher_id'] ?>"
                                          data-locked="<?= $locked ?>"
                                          title="<?= esc($entry['teacher_name']) ?> — <?= esc($entry['subject_name']) ?>">
                                         <div class="fw-bold lh-1" style="font-size:.78rem"><?= $code ?></div>
                                         <div class="lh-1 mt-1" style="font-size:.68rem;opacity:.85">[<?= $teacherCodeDisplay ?>]</div>
                                     </div>
                                     <?php endforeach; ?>
                                </td>
                                <?php endforeach; ?>
                            </tr>
                            <?php else: // Istirahat / Upacara / dll ?>
                            <tr class="mt-nonkbm-row <?= $isNewDay ? 'mt-day-sep' : '' ?>">
                                <?php if ($isNewDay): ?>
                                <td class="mt-col-day" rowspan="<?= $rowspan ?>">
                                    <div class="day-vert"><?= $dayNames[$dayNum] ?></div>
                                </td>
                                <?php endif; ?>
                                <td class="mt-col-jam-nonkbm">
                                    <div style="font-size:9px;color:#92400e;line-height:1.2;font-weight:700"><?= esc($slotRow['label']) ?></div>
                                </td>
                                <td class="mt-nonkbm-label-cell" colspan="<?= count($classroomsMap) ?>">
                                    <?= esc($slotRow['label']) ?> (<?= substr($slotRow['start_time'],0,5) ?> – <?= substr($slotRow['end_time'],0,5) ?>)
                                </td>
                            </tr>
                            <?php endif; ?>
                            <?php endforeach; ?>
                            <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>

        <div id="timetableModeClassroom" class="timetable-mode-panel d-none">
            <div class="entity-selector no-print">
                <label for="selClassroom">Pilih Kelas:</label>
                <select class="entity-select" id="selClassroom" onchange="renderClassroomGrid(this.value)">
                    <?php foreach ($classrooms as $cls): ?>
                    <option value="<?= $cls['id'] ?>"><?= esc($cls['name']) ?></option>
                    <?php endforeach; ?>
                </select>
                <h5 class="mb-0 fw-bold ms-3" id="clsTitle">—</h5>
            </div>
            <div class="card border-0 shadow-sm">
                <div class="card-body p-0" id="gridClassroomContainer">
                    <!-- Loaded via JS -->
                </div>
            </div>
        </div>

        <div id="timetableModeTeacher" class="timetable-mode-panel d-none">
            <div class="entity-selector no-print">
                <label for="selTeacher">Pilih Guru:</label>
                <select class="entity-select" id="selTeacher" onchange="renderTeacherGrid(this.value)">
                    <?php foreach ($teachers as $t): ?>
                    <option value="<?= $t['id'] ?>"><?= esc($t['name']) ?></option>
                    <?php endforeach; ?>
                </select>
                <h5 class="mb-0 fw-bold ms-3" id="tchTitle">—</h5>
                <button class="btn btn-sm btn-outline-warning py-1 px-3 ms-2" onclick="lockCurrentTeacherGrid('lock')"><i class="bi bi-lock-fill"></i> Kunci</button>
                <button class="btn btn-sm btn-outline-secondary py-1 px-3 ms-1" onclick="lockCurrentTeacherGrid('unlock')"><i class="bi bi-unlock"></i> Buka</button>
            </div>
            <div class="card border-0 shadow-sm">
                <div class="card-body p-0" id="gridTeacherContainer">
                    <!-- Loaded via JS -->
                </div>
            </div>
        </div>

        <!-- Export button row -->
        <div class="row g-3 mt-4">
            <div class="col-md-6">
                <div class="card border border-slate shadow-sm">
                    <div class="card-header bg-white py-2"><i class="bi bi-file-earmark-excel me-2 text-success"></i>Download Excel</div>
                    <div class="card-body">
                        <div class="d-grid gap-2">
                            <div class="d-flex gap-2">
                                <a href="/schedule-generator/export-excel/<?= $schedId ?>/master" class="btn btn-outline-success w-100 btn-sm" title="Master Timetable dengan Mata Pelajaran + Kode Guru"><i class="bi bi-grid-3x3-gap"></i> Master (Mapel + Guru)</a>
                                <a href="/schedule-generator/export-excel/<?= $schedId ?>/master-teacher" class="btn btn-outline-success w-100 btn-sm" title="Master Timetable dengan Hanya Kode Guru saja"><i class="bi bi-person-badge"></i> Master (Hanya Guru)</a>
                            </div>
                            <div class="d-flex gap-2">
                                <a href="/schedule-generator/export-excel/<?= $schedId ?>/per-class" class="btn btn-outline-success w-100 btn-sm"><i class="bi bi-door-open"></i> Per Kelas</a>
                                <a href="/schedule-generator/export-excel/<?= $schedId ?>/per-teacher" class="btn btn-outline-success w-100 btn-sm"><i class="bi bi-person"></i> Per Guru</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-md-6">
                <div class="card border border-slate shadow-sm">
                    <div class="card-header bg-white py-2"><i class="bi bi-file-earmark-pdf me-2 text-danger"></i>Download PDF</div>
                    <div class="card-body">
                        <div class="d-grid gap-2">
                            <div class="d-flex gap-2">
                                <a href="/schedule-generator/export-pdf/<?= $schedId ?>/master" class="btn btn-outline-danger w-100 btn-sm" title="Master PDF dengan Mata Pelajaran + Kode Guru"><i class="bi bi-grid-3x3-gap"></i> Master (Mapel + Guru)</a>
                                <a href="/schedule-generator/export-pdf/<?= $schedId ?>/master-teacher" class="btn btn-outline-danger w-100 btn-sm" title="Master PDF dengan Hanya Kode Guru saja"><i class="bi bi-person-badge"></i> Master (Hanya Guru)</a>
                            </div>
                            <div class="d-flex gap-2">
                                <a href="/schedule-generator/export-pdf/<?= $schedId ?>/per-class" class="btn btn-outline-danger w-100 btn-sm"><i class="bi bi-door-open"></i> Per Kelas</a>
                                <a href="/schedule-generator/export-pdf/<?= $schedId ?>/per-teacher" class="btn btn-outline-danger w-100 btn-sm"><i class="bi bi-person"></i> Per Guru</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Print-only Legend Mapping Teacher Short Codes to Names -->
        <div class="d-none d-print-block mt-4 pt-3 border-top page-break-inside-avoid">
            <h6 class="fw-bold mb-2">Daftar Singkatan Nama Guru (Legenda):</h6>
            <div class="d-flex flex-wrap gap-x-4 gap-y-1" style="font-size: 10px; line-height: 1.4;">
                <?php 
                $printLegendItems = [];
                foreach ($teachers as $t) {
                    $code = $t['short_code'] ?: (($t['user_id'] ?? '') ?: substr($t['name'], 0, 10));
                    $printLegendItems[] = '<span class="fw-bold">' . esc($code) . '</span>: ' . esc($t['name']);
                }
                echo implode(' &bull; ', $printLegendItems);
                ?>
            </div>
        </div>
    </div>

    <!-- Actions Navigation bar -->
    <div class="wizard-actions-bar">
        <button class="btn-wizard-action btn-back" id="btnWizardBack" disabled onclick="navigateStep(-1)">
            <i class="bi bi-arrow-left"></i> Kembali
        </button>
        <button class="btn-wizard-action btn-next" id="btnWizardNext" onclick="navigateStep(1)">
            Lanjutkan <i class="bi bi-arrow-right"></i>
        </button>
    </div>
</div>

<!-- Toast for simple notifications -->
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index:9999">
    <div id="mainToast" class="toast align-items-center border-0 text-white" role="alert" aria-live="assertive">
        <div class="d-flex">
            <div class="toast-body fw-semibold" id="toastMsg">—</div>
            <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
        </div>
    </div>
</div>

<?= $this->endSection() ?>

<?= $this->section('scripts') ?>
<script>
'use strict';

const SCHED_ID = <?= $schedId ?>;
const CSRF = '<?= $CSRF ?>';

function getContrastColor(hex) {
    if (!hex) return '#000000';
    hex = hex.replace('#', '');
    if (hex.length !== 6) return '#000000';
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);
    const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
    return luminance > 0.5 ? '#000000' : '#ffffff';
}

function hslToHex(h, s, l) {
    l /= 100;
    const a = s * Math.min(l, 1 - l) / 100;
    const f = n => {
        const k = (n + h / 30) % 12;
        const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
        return Math.round(255 * color).toString(16).padStart(2, '0');
    };
    return `#${f(0)}${f(8)}${f(4)}`;
}

function getTeacherColor(teacherId, dbColor) {
    if (dbColor && dbColor.toLowerCase() !== '#cccccc') {
        return {
            bg: dbColor,
            text: getContrastColor(dbColor),
            border: dbColor
        };
    }
    const hue = (teacherId * 137.5) % 360;
    const sat = 70 + (teacherId % 3) * 15;
    const lit = 40 + ((teacherId * 3) % 4) * 15;
    const bg = hslToHex(hue, sat, lit);
    const border = hslToHex(hue, sat, Math.max(25, lit - 10));
    return {
        bg: bg,
        text: getContrastColor(bg),
        border: border
    };
}

// Master data maps passed from PHP
const ACTIVE_DAYS = <?= json_encode($activeDaysArray) ?>;
const DAY_NAMES = <?= json_encode($dayNames) ?>;
const SUBJ_COLORS = <?= json_encode($subjColorsJs) ?>;
const TEACHER_PALETTES = <?= json_encode($teacherPalettes) ?>;
const CLASSROOMS = <?= json_encode($classrooms) ?>;
const TEACHERS = <?= json_encode($teachers) ?>;

// Grid data for Step 7 (JSON equivalent of PHP structures)
const GRID_CLS = <?= json_encode($gridByClassroom) ?>;
const GRID_TCH = <?= json_encode($gridByTeacher) ?>;
const TEACHER_META = <?= json_encode($teacherMeta) ?>;
const TEACHER_LOCK_STATUS = <?= json_encode($teacherLockStatus) ?>;

// Global state
let currentStep = <?= $selectedStep ?>;
let currentTeacherAvailId = null;
let currentAvailGridData = [];
const ALL_TIMESLOTS = <?= json_encode($timeslots) ?>;
let currentAvailTimeslots = ALL_TIMESLOTS;
let selectedTimeslotDay = <?= $activeDaysArray[0] ?? 1 ?>;

// ═══════════════════════════════════════════════════════════════
// BOOTSTRAP WIZARD LOGIC
// ═══════════════════════════════════════════════════════════════
const stepPanels = [
    { title: "Langkah 1: Informasi Umum & Hari Aktif", desc: "Tentukan nama draf, catatan, dan hari-hari aktif pembelajaran." },
    { title: "Langkah 2: Konfigurasi Slot Waktu (Timeslots)", desc: "Buat atau sesuaikan slot KBM (KBM ke-1, KBM ke-2) dan Non-KBM (Istirahat, Upacara) harian." },
    { title: "Langkah 3: Target JTM Kurikulum", desc: "Tentukan batas JTM mingguan per kelas untuk setiap mata pelajaran." },
    { title: "Langkah 4: Alokasi Beban Mengajar & Auto-Split", desc: "Masukkan beban kerja guru per rombel dengan saran pecah JP otomatis." },
    { title: "Langkah 5: Batasan & Ketersediaan Guru", desc: "Batasi jam harian guru dan tentukan hari/slot libur di mana guru dilarang mengajar." },
    { title: "Langkah 6: Pre-Validasi & Pemicu Generator", desc: "Validasikan kelayakan alokasi data lalu jalankan engine generator otomatis." },
    { title: "Langkah 7: Tinjau Jadwal & Publikasikan", desc: "Tinjau Master Timetable, lakukan edit manual drag-and-drop, kunci guru, lalu publikasikan." }
];

document.addEventListener('DOMContentLoaded', () => {
    // Initialise Step 2 timeslots list
    loadTimeslotsList();

    // Sync timeslot day tab when dropdown selection changes
    const slotDaySelect = document.getElementById('slotDay');
    if (slotDaySelect) {
        slotDaySelect.addEventListener('change', function() {
            const dayVal = parseInt(this.value);
            const tabBtn = document.querySelector(`#stepPanel2 .timeslot-day-tab[data-day="${dayVal}"]`);
            if (tabBtn) {
                selectTimeslotDay(dayVal, tabBtn);
            } else {
                selectedTimeslotDay = dayVal;
                loadTimeslotsList();
            }
        });
    }

    // Initialise Step 4 teacher subjects logic
    setupLoadTeacherDropdown();

    // Initialise Step 5 teacher selector
    if (TEACHERS.length > 0) {
        selectAvailTeacher(TEACHERS[0].id, document.querySelector('#availTeacherList .avail-teacher-list-item'));
    }

    // If current step is 6, load validation data
    if (currentStep === 6) {
        loadValidationStep();
    }

    // Update progress tracker
    updateWizardUI();

    // Setup visual grids in Step 7
    if (CLASSROOMS.length > 0) renderClassroomGrid(CLASSROOMS[0].id);
    if (TEACHERS.length > 0) renderTeacherGrid(TEACHERS[0].id);
});

function updateWizardUI() {
    // Set titles
    document.getElementById('wizardPanelTitle').textContent = stepPanels[currentStep - 1].title;
    document.getElementById('wizardPanelSubtitle').textContent = stepPanels[currentStep - 1].desc;

    // Show active panel, hide others
    for (let i = 1; i <= 7; i++) {
        const p = document.getElementById('stepPanel' + i);
        if (i === currentStep) p.classList.add('active');
        else p.classList.remove('active');

        // Step tracker nodes styling
        const node = document.querySelectorAll('.wizard-step-node')[i - 1];
        node.classList.remove('active', 'completed');
        if (i < currentStep) node.classList.add('completed');
        else if (i === currentStep) node.classList.add('active');
    }

    // Progress bar line width calculation
    const progressLine = document.getElementById('wizardProgressLine');
    const widthPct = ((currentStep - 1) / 6) * 92;
    progressLine.style.width = widthPct + '%';

    // Buttons visibility / status
    const btnBack = document.getElementById('btnWizardBack');
    const btnNext = document.getElementById('btnWizardNext');

    btnBack.disabled = (currentStep === 1);

    if (currentStep === 7) {
        btnNext.innerHTML = 'Publikasikan Jadwal <i class="bi bi-send-check"></i>';
        btnNext.className = 'btn-wizard-action btn-next btn-save-inline';
    } else {
        btnNext.innerHTML = 'Lanjutkan <i class="bi bi-arrow-right"></i>';
        btnNext.className = 'btn-wizard-action btn-next';
    }
}

async function navigateStep(dir) {
    if (dir === 1) {
        // Save current step data before going next
        let success = true;
        if (currentStep === 1) success = await saveStep1();
        else if (currentStep === 3) success = await saveStep3All();
        else if (currentStep === 5) success = await saveAvailTeacherGrid();
        else if (currentStep === 6) {
            // Check if step 6 allows moving next
            success = true;
        }

        if (!success) return; // Stop if saving failed
    }

    currentStep += dir;
    if (currentStep < 1) currentStep = 1;
    if (currentStep > 7) {
        // Handle publish click
        currentStep = 7;
        const pubBtn = document.querySelector('#stepPanel7 a[href*="/publish/"]');
        if (pubBtn) pubBtn.click();
        return;
    }
    
    // Load dynamic data on entering step
    if (currentStep === 6) {
        loadValidationStep();
    }

    updateWizardUI();
}

function jumpToStep(step) {
    // Only allow jumping back, or jumping forward if validated (simulated by standard linear next)
    if (step < currentStep) {
        currentStep = step;
        updateWizardUI();
    } else if (step > currentStep) {
        // Run next steps in sequence
        navigateStep(1);
    }
}

// Toast helper
function showToast(msg, type = 'success') {
    const toastEl = document.getElementById('mainToast');
    const toastMsg = document.getElementById('toastMsg');
    if (!toastEl || !toastMsg) return;
    toastMsg.textContent = msg;
    toastEl.className = 'toast align-items-center border-0 text-white bg-' +
        (type === 'success' ? 'success' : type === 'error' ? 'danger' : type === 'warning' ? 'warning' : 'primary');
    const bsToast = bootstrap.Toast.getOrCreateInstance(toastEl, { delay: 3000 });
    bsToast.show();
}

// ═══════════════════════════════════════════════════════════════
// STEP 1 FUNCTIONS: INFO & HARI AKTIF
// ═══════════════════════════════════════════════════════════════
async function saveStep1() {
    const form = document.getElementById('formStep1');
    const fd = new FormData(form);
    
    try {
        const res = await fetch('/schedule-generator/update/' + SCHED_ID, {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF },
            body: fd
        });
        const data = await res.json();
        if (data.success) {
            document.getElementById('headerScheduleName').textContent = data.name;
            showToast(data.message, 'success');
            
            // Reload timeslot days dynamically in case active days changed
            const activeDaysArray = data.active_days.split(',').map(Number);
            updateTimeslotsDayTabs(activeDaysArray);
            return true;
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menyimpan', text: data.message });
            return false;
        }
    } catch (e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
        return false;
    }
}

function updateTimeslotsDayTabs(days) {
    const tabContainer = document.querySelector('#stepPanel2 .overflow-x-auto');
    if (!tabContainer) return;
    
    let html = '';
    days.forEach((d, idx) => {
        const activeClass = d === selectedTimeslotDay ? 'active' : '';
        html += `<button class="timeslot-day-tab ${activeClass}" data-day="${d}" onclick="selectTimeslotDay(${d}, this)">${DAY_NAMES[d]}</button>`;
    });
    tabContainer.innerHTML = html;
}

// ═══════════════════════════════════════════════════════════════
// STEP 2 FUNCTIONS: SLOT WAKTU
// ═══════════════════════════════════════════════════════════════
async function loadTimeslotsList() {
    const listBody = document.getElementById('timeslotsListBody');
    if (!listBody) return;
    
    listBody.innerHTML = `<tr><td colspan="7" class="text-center text-muted py-3"><div class="spinner-border spinner-border-sm me-2"></div>Memuat data slot waktu...</td></tr>`;
    
    // Sync the Day select input in case it's not in sync
    const slotDaySelect = document.getElementById('slotDay');
    if (slotDaySelect) {
        slotDaySelect.value = selectedTimeslotDay;
    }
    
    try {
        const res = await fetch('/schedule-generator/get-timeslots/' + SCHED_ID, {
            headers: { 'X-Requested-With': 'XMLHttpRequest' }
        });
        const data = await res.json();
        if (data.success) {
            const list = data.timeslots.filter(t => parseInt(t.day) === parseInt(selectedTimeslotDay));
            
            // Calculate next slot number suggestion
            let nextSlot = 1;
            if (list.length > 0) {
                const maxSlot = Math.max(...list.map(t => parseInt(t.slot_number) || 0));
                nextSlot = maxSlot + 1;
            }
            const slotNumberInput = document.getElementById('slotNumber');
            if (slotNumberInput) {
                slotNumberInput.value = nextSlot;
            }
            
            if (list.length === 0) {
                listBody.innerHTML = `<tr><td colspan="7" class="text-center text-muted py-3">Belum ada slot waktu di hari ini. Sediakan struktur KBM Anda.</td></tr>`;
                return;
            }
            
            let html = '';
            list.forEach(t => {
                const checked = t.is_active == 1 ? 'checked' : '';
                html += `
                <tr data-slot-id="${t.id}">
                    <td class="text-center fw-bold">${t.slot_number}</td>
                    <td><strong>${esc(t.label)}</strong></td>
                    <td class="text-center text-capitalize"><span class="badge bg-light text-dark border">${t.slot_type}</span></td>
                    <td class="text-center">${t.start_time.substring(0, 5)}</td>
                    <td class="text-center">${t.end_time.substring(0, 5)}</td>
                    <td class="text-center">
                        <input type="checkbox" ${checked} onchange="toggleTimeslotActive(${t.id}, this)" style="width:18px;height:18px;cursor:pointer">
                    </td>
                    <td class="text-center">
                        <button class="btn btn-outline-danger btn-xs py-0 px-2" onclick="deleteTimeslot(${t.id})">
                            <i class="bi bi-trash3"></i>
                        </button>
                    </td>
                </tr>
                `;
            });
            listBody.innerHTML = html;
        }
    } catch(e) {
        listBody.innerHTML = `<tr><td colspan="7" class="text-center text-danger py-3">Gagal memuat data: ${e.message}</td></tr>`;
    }
}

function selectTimeslotDay(day, btn) {
    selectedTimeslotDay = day;
    document.querySelectorAll('#stepPanel2 .timeslot-day-tab').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    loadTimeslotsList();
}

document.getElementById('formAddTimeslot').addEventListener('submit', async function(e) {
    e.preventDefault();
    const fd = new FormData(this);
    try {
        const res = await fetch('/schedule-timeslot/store', {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF },
            body: fd
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            document.getElementById('slotLabel').value = '';
            document.getElementById('slotStart').value = '';
            document.getElementById('slotEnd').value = '';
            loadTimeslotsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menambah Slot', text: data.message });
        }
    } catch (err) {
        Swal.fire({ icon: 'error', title: 'Error', text: err.message });
    }
});

document.getElementById('formCopyTimeslots').addEventListener('submit', async function(e) {
    e.preventDefault();
    const fd = new FormData(this);
    try {
        const res = await fetch('/schedule-timeslot/copy-day', {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF },
            body: fd
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            loadTimeslotsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menyalin', text: data.message });
        }
    } catch (err) {
        Swal.fire({ icon: 'error', title: 'Error', text: err.message });
    }
});

async function toggleTimeslotActive(id, cb) {
    try {
        const res = await fetch('/schedule-timeslot/toggle-active/' + id, {
            headers: { 'X-Requested-With': 'XMLHttpRequest' }
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
        } else {
            cb.checked = !cb.checked;
            showToast(data.message || 'Gagal mengubah status.', 'error');
        }
    } catch(e) {
        cb.checked = !cb.checked;
        showToast('Error: ' + e.message, 'error');
    }
}

async function deleteTimeslot(id) {
    const confirm = await Swal.fire({
        title: 'Hapus slot waktu?',
        text: 'Tindakan ini permanen.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonText: 'Hapus',
        cancelButtonText: 'Batal'
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const res = await fetch('/schedule-timeslot/delete/' + id, {
            headers: { 'X-Requested-With': 'XMLHttpRequest' }
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            loadTimeslotsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menghapus', text: data.message });
        }
    } catch(e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

async function clearActiveDayTimeslots() {
    const dayNum = parseInt(selectedTimeslotDay);
    const dayName = DAY_NAMES[dayNum] || 'hari ini';
    
    const confirm = await Swal.fire({
        title: 'Kosongkan Hari ' + dayName + '?',
        text: 'Apakah Anda yakin ingin menghapus SEMUA slot waktu pada hari ' + dayName + '? Tindakan ini tidak dapat dibatalkan.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#d33',
        confirmButtonText: 'Ya, Kosongkan',
        cancelButtonText: 'Batal'
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const fd = new FormData();
        fd.append('day', dayNum);
        
        const res = await fetch('/schedule-timeslot/delete-day', {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF },
            body: fd
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            loadTimeslotsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Mengosongkan', text: data.message });
        }
    } catch(e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

// ═══════════════════════════════════════════════════════════════
// STEP 3 FUNCTIONS: TARGET JTM
// ═══════════════════════════════════════════════════════════════
async function saveJtmTarget(subjectId, btn) {
    const row = document.querySelector(`tr[data-subject-id="${subjectId}"]`);
    const vii = row.querySelector('input[data-grade="1"]').value;
    const viii = row.querySelector('input[data-grade="2"]').value;
    const ix = row.querySelector('input[data-grade="3"]').value;
    
    btn.disabled = true;
    btn.textContent = 'Menyimpan...';
    
    try {
        const res = await fetch('/schedule-generator/save-subject-targets', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF
            },
            body: JSON.stringify({ subject_id: subjectId, vii: vii, viii: viii, ix: ix })
        });
        const data = await res.json();
        btn.disabled = false;
        btn.textContent = 'Simpan';
        
        if (data.success) {
            showToast('Target jam mapel berhasil disimpan', 'success');
        } else {
            showToast('Gagal menyimpan target', 'error');
        }
    } catch (e) {
        btn.disabled = false;
        btn.textContent = 'Simpan';
        showToast('Error: ' + e.message, 'error');
    }
}

async function saveStep3All() {
    // Standard validation
    return true;
}

// ═══════════════════════════════════════════════════════════════
// STEP 4 FUNCTIONS: BEBAN MENGAJAR & SPLIT
// ═══════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════
// STEP 4 FUNCTIONS: BEBAN MENGAJAR & SPLIT
// ═══════════════════════════════════════════════════════════════
function setupLoadTeacherDropdown() {
    const loadTeacher = document.getElementById('loadTeacher');
    const switchShowAllLoads = document.getElementById('switchShowAllLoads');
    
    loadTeacher.addEventListener('change', function() {
        const tid = this.value;
        if (tid) {
            if (switchShowAllLoads) {
                switchShowAllLoads.checked = false;
            }
        }
        filterLoadsTable();
    });

    // Auto-split configuration logic
    const loadHours = document.getElementById('loadHours');
    const loadSplit = document.getElementById('loadSplit');
    const suggestContainer = document.getElementById('suggestSplitContainer');
    const suggestPills = document.getElementById('suggestSplitPills');

    loadHours.addEventListener('input', async function() {
        const hours = parseInt(this.value);
        if (isNaN(hours) || hours <= 0) {
            suggestContainer.style.display = 'none';
            return;
        }

        try {
            const res = await fetch('/schedule-load/get-suggest-split?total_jam=' + hours, {
                headers: { 'X-Requested-With': 'XMLHttpRequest' }
            });
            const data = await res.json();
            if (data.success && data.split && data.split.length > 0) {
                suggestContainer.style.display = 'block';
                let html = '';
                data.split.forEach(s => {
                    html += `<button type="button" class="btn btn-outline-secondary btn-xs py-0 px-2 fw-bold" onclick="selectSuggestSplit('${s}')">${s}</button>`;
                });
                suggestPills.innerHTML = html;
            } else {
                suggestContainer.style.display = 'none';
            }
        } catch (e) {
            suggestContainer.style.display = 'none';
        }
    });
}

function selectSuggestSplit(split) {
    document.getElementById('loadSplit').value = split;
}

// Handler submit form alokasi beban mengajar guru (AJAX POST)
document.getElementById('formAddLoad').addEventListener('submit', async function(e) {
    e.preventDefault();
    const fd = new FormData(this);
    
    const btn = this.querySelector('button[type="submit"]');
    btn.disabled = true;
    btn.innerHTML = `<span class="spinner-border spinner-border-sm me-1"></span>Memproses...`;
    
    try {
        const res = await fetch('/schedule-load/store', {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF },
            body: fd
        });
        const data = await res.json();
        btn.disabled = false;
        btn.innerHTML = `<i class="bi bi-plus-circle me-1"></i> Alokasikan Beban`;
        
        if (data.success) {
            showToast(data.message, 'success');
            // Reset input kelas
            this.querySelectorAll('.classroom-cb').forEach(cb => cb.checked = false);
            // Reset input jam & split
            document.getElementById('loadHours').value = '';
            document.getElementById('loadSplit').value = '';
            document.getElementById('suggestSplitContainer').style.display = 'none';
            
            // Reload table loads secara dinamis
            reloadLoadsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Alokasi Beban', html: data.message });
        }
    } catch (err) {
        btn.disabled = false;
        btn.innerHTML = `<i class="bi bi-plus-circle me-1"></i> Alokasikan Beban`;
        Swal.fire({ icon: 'error', title: 'Error', text: err.message });
    }
});

function filterLoadsTable() {
    const loadTeacher = document.getElementById('loadTeacher');
    const switchShowAllLoads = document.getElementById('switchShowAllLoads');
    const listBody = document.getElementById('loadsListBody');
    const selectAllLoads = document.getElementById('selectAllLoads');
    
    if (!listBody || !loadTeacher) return;
    
    const selectedTeacherId = loadTeacher.value;
    const showAll = switchShowAllLoads ? switchShowAllLoads.checked : true;
    
    if (selectAllLoads) selectAllLoads.checked = false;
    
    const rows = listBody.querySelectorAll('tr[data-load-id]');
    let visibleCount = 0;
    
    rows.forEach(row => {
        const rowTeacherId = row.getAttribute('data-teacher-id');
        let showRow = false;
        
        if (showAll) {
            showRow = true;
        } else {
            if (selectedTeacherId) {
                showRow = (rowTeacherId === selectedTeacherId);
            } else {
                showRow = false;
            }
        }
        
        if (showRow) {
            row.style.display = '';
            visibleCount++;
        } else {
            row.style.display = 'none';
            const cb = row.querySelector('.load-item-cb');
            if (cb) cb.checked = false;
        }
    });
    
    const oldPlaceholders = listBody.querySelectorAll('.placeholder-row');
    oldPlaceholders.forEach(el => el.remove());
    
    if (visibleCount === 0) {
        let msg = 'Belum ada beban mengajar terdaftar.';
        if (!showAll && !selectedTeacherId) {
            msg = 'Silakan pilih guru di dropdown terlebih dahulu, atau aktifkan "Tampilkan Semua Guru".';
        } else if (!showAll && selectedTeacherId) {
            const selectedText = loadTeacher.options[loadTeacher.selectedIndex].text;
            msg = `Belum ada beban mengajar untuk guru: ${selectedText}.`;
        }
        
        const tr = document.createElement('tr');
        tr.className = 'placeholder-row';
        tr.innerHTML = `<td colspan="7" class="text-center text-muted py-3">${msg}</td>`;
        listBody.appendChild(tr);
    }
    
    const clearBtn = document.getElementById('btnClearTeacher');
    if (clearBtn) {
        if (selectedTeacherId && visibleCount > 0) {
            const selectedText = loadTeacher.options[loadTeacher.selectedIndex].text;
            clearBtn.innerHTML = `<i class="bi bi-x-circle me-1"></i>Kosongkan Beban: ${esc(selectedText.split(' ').slice(0, 2).join(' '))}`;
            clearBtn.style.display = '';
        } else {
            clearBtn.style.display = 'none';
        }
    }
    
    updateBulkDeleteUI();
}

function toggleShowAllLoads(el) {
    filterLoadsTable();
}

function toggleSelectAllLoads(cb) {
    const listBody = document.getElementById('loadsListBody');
    if (!listBody) return;
    
    const checkboxes = listBody.querySelectorAll('tr[data-load-id]:not([style*="display: none"]) .load-item-cb');
    checkboxes.forEach(c => {
        c.checked = cb.checked;
    });
    updateBulkDeleteUI();
}

function updateBulkDeleteUI() {
    const listBody = document.getElementById('loadsListBody');
    if (!listBody) return;
    
    const checkedBoxes = listBody.querySelectorAll('.load-item-cb:checked');
    const bulkBtn = document.getElementById('btnBulkDelete');
    const bulkCount = document.getElementById('bulkCount');
    
    if (bulkBtn && bulkCount) {
        if (checkedBoxes.length > 0) {
            bulkCount.textContent = checkedBoxes.length;
            bulkBtn.style.display = '';
        } else {
            bulkBtn.style.display = 'none';
        }
    }
}

async function deleteBulkLoads() {
    const listBody = document.getElementById('loadsListBody');
    if (!listBody) return;
    
    const checkedBoxes = listBody.querySelectorAll('.load-item-cb:checked');
    const ids = Array.from(checkedBoxes).map(cb => parseInt(cb.value));
    
    if (ids.length === 0) return;
    
    const confirm = await Swal.fire({
        title: `Hapus ${ids.length} beban mengajar?`,
        text: 'Tindakan ini akan menghapus alokasi jam mengajar terpilih.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonText: 'Hapus Terpilih',
        cancelButtonText: 'Batal'
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const res = await fetch('/schedule-load/delete-bulk', {
            method: 'POST',
            headers: { 
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest', 
                'X-CSRF-TOKEN': CSRF 
            },
            body: JSON.stringify({ ids: ids })
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            reloadLoadsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menghapus', text: data.message });
        }
    } catch(e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

async function clearTeacherLoads() {
    const loadTeacher = document.getElementById('loadTeacher');
    if (!loadTeacher) return;
    
    const tid = loadTeacher.value;
    if (!tid) return;
    
    const selectedText = loadTeacher.options[loadTeacher.selectedIndex].text;
    
    const confirm = await Swal.fire({
        title: `Kosongkan semua beban ${selectedText}?`,
        text: 'Seluruh alokasi jam mengajar guru ini untuk semua kelas akan dihapus permanen.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonText: 'Hapus Semua',
        cancelButtonText: 'Batal'
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const res = await fetch(`/schedule-load/delete-all-by-teacher/${tid}`, {
            method: 'POST',
            headers: { 
                'X-Requested-With': 'XMLHttpRequest', 
                'X-CSRF-TOKEN': CSRF 
            }
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            reloadLoadsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Mengosongkan', text: data.message });
        }
    } catch(e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

async function reloadLoadsList() {
    const listBody = document.getElementById('loadsListBody');
    if (!listBody) return;
    
    listBody.innerHTML = `<tr><td colspan="7" class="text-center text-muted py-3"><div class="spinner-border spinner-border-sm me-2"></div>Memuat daftar beban kerja...</td></tr>`;
    
    try {
        const res = await fetch('/schedule-load/get-rekap', {
            headers: { 'X-Requested-With': 'XMLHttpRequest' }
        });
        const data = await res.json();
        if (data.success) {
            const list = data.detail_by_classroom;
            document.getElementById('totalLoadsBadge').textContent = list.length + ' Beban';
            
            if (list.length === 0) {
                listBody.innerHTML = `<tr><td colspan="7" class="text-center text-muted py-3">Belum ada beban mengajar teralokasi.</td></tr>`;
                return;
            }
            
            let html = '';
            list.forEach(l => {
                const blocks = l.split_config.split(',');
                let badges = '';
                blocks.forEach(b => {
                    badges += `<span class="load-split-badge">${b} JP</span> `;
                });
                
                html += `
                <tr data-load-id="${l.id}" data-teacher-id="${l.teacher_id}">
                    <td class="text-center">
                        <input type="checkbox" class="load-item-cb" value="${l.id}" onclick="updateBulkDeleteUI()">
                    </td>
                    <td><strong>${esc(l.teacher_name)}</strong></td>
                    <td>${esc(l.subject_name)}</td>
                    <td>${esc(l.classroom_name)}</td>
                    <td class="text-center fw-bold">${l.hours_per_week} jam</td>
                    <td class="text-center">${badges}</td>
                    <td class="text-center">
                        <button class="btn btn-outline-danger btn-xs py-0 px-2" onclick="deleteLoad(${l.id}, this)">
                            <i class="bi bi-trash3"></i>
                        </button>
                    </td>
                </tr>
                `;
            });
            listBody.innerHTML = html;
            filterLoadsTable();
        }
    } catch(e) {
        listBody.innerHTML = `<tr><td colspan="7" class="text-center text-danger py-3">Gagal memuat rekap: ${e.message}</td></tr>`;
    }
}

async function deleteLoad(id, btn) {
    const confirm = await Swal.fire({
        title: 'Hapus beban mengajar?',
        text: 'Tindakan ini akan menghapus alokasi jam mengajar guru untuk kelas bersangkutan.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonText: 'Hapus',
        cancelButtonText: 'Batal'
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const res = await fetch('/schedule-load/delete-ajax/' + id, {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF }
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            reloadLoadsList();
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menghapus', text: data.message });
        }
    } catch(e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

// ═══════════════════════════════════════════════════════════════
// STEP 5 FUNCTIONS: KETERSERIAAN GURU
// ═══════════════════════════════════════════════════════════════
async function selectAvailTeacher(teacherId, element) {
    currentTeacherAvailId = teacherId;
    document.querySelectorAll('#availTeacherList .avail-teacher-list-item').forEach(el => el.classList.remove('active'));
    element.classList.add('active');
    
    const titleEl = document.getElementById('availTeacherNameTitle');
    titleEl.innerHTML = `<span class="spinner-border spinner-border-sm me-2"></span>Memuat...`;
    
    try {
        const res = await fetch(`/schedule-generator/get-teacher-availability/${SCHED_ID}/${teacherId}`, {
            headers: { 'X-Requested-With': 'XMLHttpRequest' }
        });
        const data = await res.json();
        if (data.success) {
            titleEl.textContent = 'Ketersediaan — ' + data.teacher.name;
            
            // Set max hours input
            const maxInput = document.getElementById('teacherMaxHoursInput');
            maxInput.value = data.setting.max_hours_per_day || '';
            maxInput.placeholder = data.globalMaxHours + ' (Global)';
            
            currentAvailTimeslots = data.timeslots;
            currentAvailGridData = data.blockedMap; // [day][slot_number] = true (blocked)
            
            renderAvailTeacherGrid();
        }
    } catch (e) {
        titleEl.textContent = 'Gagal Memuat Ketersediaan';
    }
}

function renderAvailTeacherGrid() {
    const container = document.getElementById('teacherAvailGridContainer');
    if (!container) return;
    
    // Group active timeslots by slot number
    const uniqueSlots = [];
    const slotMap = {};
    currentAvailTimeslots.forEach(ts => {
        if (!slotMap[ts.slot_number]) {
            slotMap[ts.slot_number] = ts;
            uniqueSlots.push(ts.slot_number);
        }
    });
    uniqueSlots.sort((a,b) => a-b);
    
    let html = '<div class="avail-grid">';
    
    // Header labels
    html += '<div class="avail-grid-header d-flex align-items-center justify-content-center">Slot</div>';
    ACTIVE_DAYS.forEach(d => {
        html += `<div class="avail-grid-header d-flex align-items-center justify-content-center">${DAY_NAMES[d]}</div>`;
    });
    
    uniqueSlots.forEach(slotNum => {
        html += `<div class="avail-grid-header d-flex flex-column align-items-center justify-content-center border" style="background:#f1f5f9; height:58px">`;
        html += `<div class="fw-bold" style="font-size:11px">Slot ${slotNum}</div>`;
        html += `</div>`;
        
        ACTIVE_DAYS.forEach(day => {
            const hasSlot = currentAvailTimeslots.find(t => parseInt(t.day) === day && parseInt(t.slot_number) === parseInt(slotNum));
            if (!hasSlot) {
                html += `<div style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:6px; height:58px"></div>`;
                return;
            }
            
            // Check if blocked in map
            const isBlocked = currentAvailGridData[day] && currentAvailGridData[day][slotNum];
            const stateClass = isBlocked ? 'blocked' : 'available';
            const stateIcon = isBlocked ? '🚫 Libur' : '✓ Bersedia';
            const slotLabel = hasSlot.label;
            const start = hasSlot.start_time.substring(0, 5);
            const end = hasSlot.end_time.substring(0, 5);
            
            html += `
            <div class="avail-grid-cell ${stateClass} d-flex flex-column align-items-center justify-content-center" data-day="${day}" data-slot="${slotNum}" onclick="toggleAvailCell(this)" style="height:58px; aspect-ratio:auto; padding:4px">
                <div style="font-size:9px; font-weight:700; opacity:0.9; margin-bottom:1px">${esc(slotLabel)}</div>
                <div style="font-size:8px; opacity:0.7; margin-bottom:2px">${start}-${end}</div>
                <div class="avail-label" style="font-size:9px">${stateIcon}</div>
            </div>
            `;
        });
    });
    
    html += '</div>';
    container.innerHTML = html;
}

function toggleAvailCell(cell) {
    const day = parseInt(cell.dataset.day);
    const slot = parseInt(cell.dataset.slot);
    
    if (cell.classList.contains('available')) {
        cell.classList.remove('available');
        cell.classList.add('blocked');
        cell.querySelector('.avail-label').textContent = '🚫 Libur';
        
        // Add to local state
        if (!currentAvailGridData[day]) currentAvailGridData[day] = {};
        currentAvailGridData[day][slot] = true;
    } else {
        cell.classList.remove('blocked');
        cell.classList.add('available');
        cell.querySelector('.avail-label').textContent = '✓ Bersedia';
        
        // Remove from local state
        if (currentAvailGridData[day]) {
            delete currentAvailGridData[day][slot];
        }
    }
}

async function saveGlobalMaxHours() {
    const val = parseInt(document.getElementById('globalMaxHoursInput').value);
    if (isNaN(val) || val < 1 || val > 12) {
        Swal.fire({ icon: 'warning', title: 'Aturan Global', text: 'Batas jam harian harus antara 1 s/d 12.' });
        return;
    }
    
    try {
        const res = await fetch('/schedule-generator/save-global-max-hours', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF
            },
            body: JSON.stringify({ global_max_hours: val })
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            // Update placeholders dynamically
            document.getElementById('teacherMaxHoursInput').placeholder = val + ' (Global)';
        } else {
            showToast(data.message || 'Gagal menyimpan.', 'error');
        }
    } catch(e) {
        showToast('Error: ' + e.message, 'error');
    }
}

async function saveTeacherSettings() {
    if (!currentTeacherAvailId) return;
    const maxVal = document.getElementById('teacherMaxHoursInput').value;
    
    try {
        const res = await fetch(`/schedule-availability/save-settings/${currentTeacherAvailId}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF
            },
            body: JSON.stringify({ max_hours_per_day: maxVal })
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
        } else {
            Swal.fire({ icon: 'error', title: 'Batas Gagal', text: data.message });
        }
    } catch (e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

async function saveAvailTeacherGrid() {
    if (!currentTeacherAvailId) return true;
    
    // Compile current local state of blocked slots
    const blockedList = [];
    for (let day in currentAvailGridData) {
        for (let slot in currentAvailGridData[day]) {
            blockedList.push({ day: parseInt(day), slot_number: parseInt(slot) });
        }
    }
    
    try {
        const res = await fetch(`/schedule-availability/save/${currentTeacherAvailId}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF
            },
            body: JSON.stringify({ blocked: blockedList })
        });
        const data = await res.json();
        if (data.success) {
            showToast('Ketersediaan slot guru berhasil disimpan', 'success');
            return true;
        } else {
            Swal.fire({ icon: 'error', title: 'Gagal Menyimpan Grid', text: data.message });
            return false;
        }
    } catch (e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
        return false;
    }
}

async function resetAvailTeacher() {
    if (!currentTeacherAvailId) return;
    const confirm = await Swal.fire({
        title: 'Reset ketersediaan?',
        text: 'Semua dilarang mengajar (blokir merah) akan dihapus, guru bersedia penuh.',
        icon: 'warning',
        showCancelButton: true
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const res = await fetch(`/schedule-availability/reset/${currentTeacherAvailId}`, {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF }
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            currentAvailGridData = [];
            renderAvailTeacherGrid();
        }
    } catch (e) {
        showToast('Error: ' + e.message, 'error');
    }
}

// ═══════════════════════════════════════════════════════════════
// STEP 6 FUNCTIONS: PRE-VALIDASI & RUN ENGINE
// ═══════════════════════════════════════════════════════════════
async function loadValidationStep() {
    const container = document.getElementById('validationWizardContent');
    container.innerHTML = `<div class="text-center py-4">
        <div class="spinner-border text-primary"></div>
        <p class="mt-2 text-muted">Mengevaluasi kesiapan data penjadwalan...</p>
    </div>`;
    
    try {
        const res = await fetch('/schedule-generator/validateSchedule/' + SCHED_ID, {
            headers: { 'X-Requested-With': 'XMLHttpRequest' }
        });
        const data = await res.json();
        if (!data.success) {
            container.innerHTML = `<div class="alert alert-danger">${data.message}</div>`;
            return;
        }
        
        container.innerHTML = renderValidationWizard(data);
        
        // Enable/Disable generate trigger based on error counts
        const runBtn = document.getElementById('btnRunWizardGenerator');
        runBtn.disabled = (data.errors && data.errors.length > 0);
    } catch (e) {
        container.innerHTML = `<div class="alert alert-danger">Gagal memuat validasi: ${e.message}</div>`;
    }
}

function renderValidationWizard(data) {
    const errors = data.errors || [];
    const warnings = data.warnings || [];
    const summary = data.summary || {};
    const canGen = errors.length === 0;

    let html = '';

    if (canGen && warnings.length === 0) {
        html += `<div class="v-item v-ok mb-3"><i class="bi bi-check-circle-fill fs-5 flex-shrink-0 mt-1"></i><div><div class="fw-bold">VALIDASI LULUS!</div><div class="text-muted small">Semua data siap, tidak ada error atau peringatan terdeteksi.</div></div></div>`;
    } else if (canGen) {
        html += `<div class="v-item v-warn mb-3"><i class="bi bi-exclamation-triangle-fill fs-5 flex-shrink-0 mt-1"></i><div><div class="fw-bold text-warning">DAPAT DIGENERATE DENGAN PERINGATAN</div><div class="text-muted small">Terdapat beberapa potensi masalah terdeteksi di bawah. Anda masih bisa melanjutkan.</div></div></div>`;
    } else {
        html += `<div class="v-item v-err mb-3"><i class="bi bi-x-octagon-fill fs-5 flex-shrink-0 mt-1"></i><div><div class="fw-bold text-danger">VALIDASI GAGAL (${errors.length} ERROR)</div><div class="text-muted small">Anda wajib memperbaiki error di bawah sebelum generator diizinkan berjalan.</div></div></div>`;
    }

    if (summary.total_slots) {
        const pct = summary.utilization_pct ?? 0;
        const pctColor = pct > 95 ? '#ef4444' : (pct > 80 ? '#f59e0b' : '#10b981');
        html += `
        <div class="row g-2 mb-3">
            <div class="col-6 col-md-3">
                <div class="stat-box text-center" style="background:#eff6ff">
                    <div style="font-size:1.3rem;font-weight:800;color:#1e3a8a">${summary.total_slots}</div>
                    <div style="font-size:10px;color:#1e3a8a">Slot KBM Tersedia</div>
                </div>
            </div>
            <div class="col-6 col-md-3">
                <div class="stat-box text-center" style="background:#ecfdf5">
                    <div style="font-size:1.3rem;font-weight:800;color:#065f46">${summary.total_load_hours}</div>
                    <div style="font-size:10px;color:#065f46">Beban JTM Terisi</div>
                </div>
            </div>
            <div class="col-6 col-md-3">
                <div class="stat-box text-center" style="background:#fafafa">
                    <div style="font-size:1.3rem;font-weight:800;color:${pctColor}">${pct}%</div>
                    <div style="font-size:10px;color:${pctColor}">Utilisasi Kelas</div>
                </div>
            </div>
            <div class="col-6 col-md-3">
                <div class="stat-box text-center" style="background:#fafafa">
                    <div style="font-size:1.3rem;font-weight:800;color:#334155">${summary.total_classrooms}</div>
                    <div style="font-size:10px;color:#334155">Jumlah Rombel</div>
                </div>
            </div>
        </div>`;
    }

    if (errors.length > 0) {
        html += `<div class="fw-bold mb-2 text-danger" style="font-size:12px"><i class="bi bi-x-circle me-1"></i>ERROR KRITIS YANG HARUS DIPERBAIKI:</div>`;
        errors.forEach(e => {
            html += `<div class="v-item v-err mb-2"><i class="bi bi-x-circle flex-shrink-0 mt-1"></i><div class="flex-grow-1"><div class="fw-bold">${e.message}</div>${e.detail ? `<div class="small mt-1">${e.detail}</div>` : ''}</div></div>`;
        });
    }

    if (warnings.length > 0) {
        html += `<div class="fw-bold mb-2 mt-3 text-warning" style="font-size:12px"><i class="bi bi-exclamation-triangle me-1"></i>PERINGATAN OPERASIONAL:</div>`;
        warnings.forEach(w => {
            html += `<div class="v-item v-warn mb-2"><i class="bi bi-exclamation-triangle flex-shrink-0 mt-1"></i><div class="flex-grow-1"><div class="fw-bold">${w.message}</div>${w.detail ? `<div class="small mt-1">${w.detail}</div>` : ''}</div></div>`;
        });
    }

    return html;
}

// Log terminal handler
function logConsole(msg, cls = '') {
    const wrap = document.getElementById('generateLog');
    if (!wrap) return;
    const line = document.createElement('div');
    line.className = 'log-line ' + cls;
    line.textContent = new Date().toLocaleTimeString() + ' — ' + msg;
    wrap.appendChild(line);
    wrap.scrollTop = wrap.scrollHeight;
}

let _progressTimer = null;
function startGeneratorProgress() {
    const wrap  = document.getElementById('genProgressWrap');
    const fill  = document.getElementById('genProgressFill');
    const label = document.getElementById('genProgressLabel');
    if (!wrap) return;
    wrap.style.display = 'block';
    let pct = 0;
    if (_progressTimer) clearInterval(_progressTimer);
    _progressTimer = setInterval(() => {
        if (pct < 92) {
            pct += pct < 45 ? 4 : 1;
            fill.style.width  = pct + '%';
            label.textContent = pct < 25 ? 'Membaca ketersediaan...' :
                                pct < 55 ? 'Meletakkan pelajaran anti-bentrok...' :
                                pct < 80 ? 'Mencari kecocokan terbaik...' : 'Merampungkan database...';
        }
    }, 450);
}
function finishGeneratorProgress(success) {
    if (_progressTimer) clearInterval(_progressTimer);
    const fill  = document.getElementById('genProgressFill');
    const label = document.getElementById('genProgressLabel');
    if (!fill) return;
    fill.style.width      = '100%';
    fill.style.background = success ? '#10b981' : '#ef4444';
    if (label) label.textContent = success ? 'Generate Sukses!' : 'Selesai dengan konflik.';
    setTimeout(() => {
        const wrap = document.getElementById('genProgressWrap');
        if (wrap) wrap.style.display = 'none';
    }, 2000);
}

document.getElementById('btnRunWizardGenerator').addEventListener('click', async function() {
    const keepManual = document.getElementById('keepManualCb').checked;
    
    const confirm = await Swal.fire({
        title: 'Jalankan Generator Jadwal?',
        html: keepManual 
            ? 'Entry manual dan locked akan **tetap dipertahankan**.' 
            : 'Semua hasil generate sebelumnya akan **dihapus dan dirombak ulang**.',
        icon: 'question',
        showCancelButton: true,
        confirmButtonText: 'Mulai Sekarang',
        cancelButtonColor: '#d33'
    });
    if (!confirm.isConfirmed) return;
    
    const btn = this;
    btn.disabled = true;
    logConsole('Memulai generate jadwal otomatis...', 'log-info');
    startGeneratorProgress();
    
    try {
        const res = await fetch('/schedule-generator/run/' + SCHED_ID, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF
            },
            body: JSON.stringify({ keep_manual: keepManual })
        });
        const data = await res.json();
        btn.disabled = false;
        
        if (data.success) {
            logConsole(data.message, 'log-ok');
            finishGeneratorProgress(true);
            
            showToast('Penjadwalan otomatis selesai dijalankan.', 'success');
            
            Swal.fire({
                icon: 'success',
                title: 'Generate Sukses!',
                text: data.message,
                confirmButtonText: 'Tinjau Hasil'
            }).then(() => {
                // Auto-advance to Step 7
                currentStep = 7;
                updateWizardUI();
                location.href = '/schedule-generator/detail/' + SCHED_ID + '?step=7';
            });
        } else {
            logConsole('Generate Gagal: ' + data.message, 'log-err');
            finishGeneratorProgress(false);
            Swal.fire({ icon: 'error', title: 'Generate Gagal', html: data.message });
        }
    } catch(err) {
        btn.disabled = false;
        logConsole('Error: ' + err.message, 'log-err');
        finishGeneratorProgress(false);
        Swal.fire({ icon: 'error', title: 'Error Engine', text: err.message });
    }
});

// ═══════════════════════════════════════════════════════════════
// STEP 7 FUNCTIONS: TINJAU JADWAL, DRAG & DROP & PUBLISH
// ═══════════════════════════════════════════════════════════════
function switchTimetableMode(mode, btn) {
    document.querySelectorAll('#stepPanel7 .vmode-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    
    document.querySelectorAll('.timetable-mode-panel').forEach(p => p.classList.add('d-none'));
    if (mode === 'master') {
        document.getElementById('timetableModeMaster').classList.remove('d-none');
    } else if (mode === 'classroom') {
        document.getElementById('timetableModeClassroom').classList.remove('d-none');
    } else if (mode === 'teacher') {
        document.getElementById('timetableModeTeacher').classList.remove('d-none');
    }
}

// TIMETABLE DRAG DROP IMPLEMENTATION FOR STEP 7
let _dragEntryId   = null;
let _dragSubjName  = null;
let _dragTeachName = null;

function setupStep7DragDrop() {
    document.querySelectorAll('#stepPanel7 .ec:not(.locked-entry)').forEach(cell => {
        cell.setAttribute('draggable', 'true');
        cell.classList.add('draggable');

        cell.addEventListener('dragstart', function(e) {
            _dragEntryId   = this.dataset.entryId;
            _dragSubjName  = this.dataset.subjectName || '—';
            _dragTeachName = this.dataset.teacherName || '—';
            this.classList.add('dragging');
            e.dataTransfer.setData('text/plain', _dragEntryId);
        });

        cell.addEventListener('dragend', function() {
            this.classList.remove('dragging');
        });
    });

    document.querySelectorAll('#stepPanel7 td.drop-zone').forEach(td => {
        td.addEventListener('dragover', function(e) {
            if (!_dragEntryId) return;
            e.preventDefault();
            this.classList.add('drag-over');
        });

        td.addEventListener('dragleave', function() {
            this.classList.remove('drag-over');
        });

        td.addEventListener('drop', function(e) {
            e.preventDefault();
            this.classList.remove('drag-over');
            const newDay  = parseInt(this.dataset.day);
            const newSlot = parseInt(this.dataset.slot);
            if (!_dragEntryId || !newDay || !newSlot) return;
            triggerTimetableMove(_dragEntryId, newDay, newSlot, _dragSubjName, _dragTeachName);
        });
    });
}

async function triggerTimetableMove(entryId, newDay, newSlot, subjName, teachName) {
    const confirm = await Swal.fire({
        title: 'Geser Jadwal?',
        html: `Pindahkan **${subjName}** (${teachName}) ke **${DAY_NAMES[newDay]} slot ${newSlot}**?`,
        icon: 'question',
        showCancelButton: true
    });
    if (!confirm.isConfirmed) return;
    
    try {
        const res = await fetch(`/schedule-generator/move-entry/${SCHED_ID}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF
            },
            body: JSON.stringify({
                entry_id: parseInt(entryId),
                target_day: newDay,
                target_slot: newSlot
            })
        });
        const data = await res.json();
        if (data.success) {
            showToast('Jadwal berhasil digeser.', 'success');
            setTimeout(() => location.reload(), 600);
        } else {
            Swal.fire({ icon: 'error', title: 'Bentrok / Kendala', html: data.message });
        }
    } catch(e) {
        Swal.fire({ icon: 'error', title: 'Error', text: e.message });
    }
}

// RENDER INDIVIDUAL GRIDS FOR CLASSROOM & TEACHER
function renderGridStep7(entityId, gridData, metaKey, titleEl, containerEl, counterType) {
    const list = counterType === 'cls' ? CLASSROOMS : TEACHERS;
    const entity = Object.entries(list).map(([id, name]) => ({id, name})).find(e => e.id == entityId) || list.find(e => e.id == entityId);
    const displayName = entity ? entity.name : '—';
    titleEl.textContent = displayName;
    
    let html = '<div class="grid-wrap"><table class="table table-bordered mb-0 schedule-matrix" id="' + (counterType === 'cls' ? 'classGrid' : 'teacherGrid') + '"><thead><tr>';
    html += '<th class="text-center align-middle header-period-col">Jam</th>';
    ACTIVE_DAYS.forEach(d => {
        const dName = DAY_NAMES[d] || '';
        const shortName = dName.substring(0, 3).toUpperCase();
        html += `<th class="text-center align-middle header-day">
            ${shortName}
            <div class="day-full small fw-normal">${dName}</div>
        </th>`;
    });
    html += '</tr></thead><tbody>';

    // Unique slot numbers
    const uniqueSlots = [];
    const slotMap = {};
    currentAvailTimeslots.forEach(ts => {
        if (!slotMap[ts.slot_number]) {
            slotMap[ts.slot_number] = ts;
            uniqueSlots.push(ts.slot_number);
        }
    });
    uniqueSlots.sort((a,b) => a-b);

    uniqueSlots.forEach(slotNum => {
        const firstDaySlot = currentAvailTimeslots.find(t => parseInt(t.slot_number) === parseInt(slotNum));
        const startStr = firstDaySlot && firstDaySlot.start_time ? firstDaySlot.start_time.substring(0, 5) : '';
        const endStr = firstDaySlot && firstDaySlot.end_time ? firstDaySlot.end_time.substring(0, 5) : '';
        
        let allNonKbm = true;
        let anyKbm = false;
        ACTIVE_DAYS.forEach(day => {
            const hasSlot = currentAvailTimeslots.find(t => parseInt(t.day) === day && parseInt(t.slot_number) === parseInt(slotNum));
            if (hasSlot && hasSlot.slot_type === 'kbm') {
                allNonKbm = false;
                anyKbm = true;
            }
        });

        // Jika semua hari non-KBM
        if (allNonKbm && anyKbm === false) {
            const icon = firstDaySlot?.slot_type === 'istirahat' ? '☕' : 
                        (firstDaySlot?.slot_type === 'upacara' ? '🚩' : 
                        (firstDaySlot?.slot_type === 'keagamaan' ? '🌙' : '•'));
            html += `<tr class="row-nonkbm"><td class="text-center align-middle period-label"><div class="period-num">${slotNum}</div></td>`;
            ACTIVE_DAYS.forEach(day => {
                const hasSlot = currentAvailTimeslots.find(t => parseInt(t.day) === day && parseInt(t.slot_number) === parseInt(slotNum));
                const label = hasSlot ? hasSlot.label : (firstDaySlot ? firstDaySlot.label : 'Istirahat');
                html += `<td class="cell-nonkbm text-center align-middle" style="background:#fffbeb !important;"><span class="cell-nonkbm-label" style="font-size:10px; font-weight:600; color:#92400e;">${icon} ${esc(label)}</span></td>`;
            });
            html += '</tr>';
            return;
        }

        html += `<tr><td class="text-center align-middle period-label">
            <div class="period-num">${slotNum}</div>
            <div class="period-time">${startStr}–${endStr}</div>
        </td>`;

        ACTIVE_DAYS.forEach(day => {
            const hasSlot = currentAvailTimeslots.find(t => parseInt(t.day) === day && parseInt(t.slot_number) === parseInt(slotNum));
            
            if (!hasSlot) {
                html += '<td class="empty-slot" style="background:#fafafa !important"></td>';
                return;
            }
            
            if (hasSlot.slot_type !== 'kbm') {
                const icon = hasSlot.slot_type === 'istirahat' ? '☕' : 
                            (hasSlot.slot_type === 'upacara' ? '🚩' : 
                            (hasSlot.slot_type === 'keagamaan' ? '🌙' : '•'));
                html += `<td class="cell-nonkbm text-center align-middle" style="background:#fffbeb !important;"><span class="cell-nonkbm-label" style="font-size:10px; font-weight:600; color:#92400e;">${icon} ${esc(hasSlot.label)}</span></td>`;
                return;
            }
            
            const entries = gridData[entityId]?.[day]?.[slotNum] || [];
            
            if (entries.length === 0) {
                html += `<td class="drop-zone empty-slot" data-day="${day}" data-slot="${slotNum}" style="background:#fafafa !important"></td>`;
                return;
            }

            const isClash = entries.length > 1;
            let cellHtml = '';
            
            entries.forEach(entry => {
                const tc = getTeacherColor(entry.teacher_id, entry.teacher_color);
                const isManual = +entry.is_manual || 0;
                const isLocked = +entry.is_locked || 0;
                let cls = isManual ? 'is-manual' : '';
                if (isLocked) cls += ' locked-entry';
                
                const code = esc(entry.subject_code || (entry.subject_name || '').substring(0,8));
                let displayMeta = entry[metaKey];
                if (metaKey === 'teacher_name') {
                    displayMeta = entry.teacher_short_code || entry.teacher_user_id || (entry.teacher_name ? entry.teacher_name.substring(0, 10) : '');
                }
                const displayMetaEsc = esc(displayMeta || '');
                const entryId = entry.id || '';
                const subjName = esc(entry.subject_name || '');
                const teachName = esc(entry.teacher_name || '');

                const lockIcon = isLocked ? `<i class="bi bi-lock-fill" style="position:absolute;top:2px;right:3px;font-size:9px;opacity:0.6"></i>` : '';

                let dimmedClass = '';
                let highlightedClass = '';
                if (activeHighlightTeacherId !== null) {
                    if (parseInt(entry.teacher_id) === activeHighlightTeacherId) {
                        highlightedClass = ' highlighted';
                    } else {
                        dimmedClass = ' dimmed';
                    }
                }

                const itemStyle = isClash
                    ? `background:${tc.bg}; color:${tc.text}; border: 1px solid #ef4444; margin: 2px; padding: 2px 4px; border-radius: 4px; font-size: 10px; position: relative; display: block;`
                    : `width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 65px; border: none; border-radius: 0; padding: 4px 2px; position: relative;`;

                cellHtml += `<div class="ec ${cls}${dimmedClass}${highlightedClass}"
                            data-entry-id="${entryId}"
                            data-teacher-id="${entry.teacher_id}"
                            data-day="${day}"
                            data-slot="${slotNum}"
                            data-subject-name="${subjName}"
                            data-teacher-name="${teachName}"
                            title="${subjName} — ${teachName}"
                            style="${itemStyle}">
                            ${lockIcon}
                            <div class="${counterType === 'cls' ? 'slot-subject' : 'slot-class'}">${counterType === 'cls' ? code : displayMetaEsc}</div>
                            <div class="${counterType === 'cls' ? 'slot-teacher' : 'slot-subject'}">${counterType === 'cls' ? '[' + displayMetaEsc + ']' : code}</div>
                        </div>`;
            });

            const firstTc = getTeacherColor(entries[0].teacher_id, entries[0].teacher_color);
            const tdBgStyle = isClash ? '' : `background:${firstTc.bg}; color:${firstTc.text};`;
            html += `<td class="text-center align-middle schedule-cell drop-zone has-slot ${isClash ? 'table-danger' : ''}" data-day="${day}" data-slot="${slotNum}" style="${tdBgStyle} padding: 0 !important; cursor: default;">`;
            html += cellHtml;
            html += '</td>';
        });
        html += '</tr>';
    });

    html += '</tbody></table></div>';
    containerEl.innerHTML = html;
    
    // Wire drag drop triggers
    setupStep7DragDrop();
}


function renderClassroomGrid(id) {
    renderGridStep7(id, GRID_CLS, 'teacher_name', document.getElementById('clsTitle'), document.getElementById('gridClassroomContainer'), 'cls');
}

function renderTeacherGrid(id) {
    renderGridStep7(id, GRID_TCH, 'classroom_name', document.getElementById('tchTitle'), document.getElementById('gridTeacherContainer'), 'tch');
}

// Locking triggers
let activeHighlightTeacherId = null;
function highlightTeacherInTimetable(tid, element) {
    if (activeHighlightTeacherId === tid) {
        clearTimetableHighlight();
        return;
    }
    
    activeHighlightTeacherId = tid;
    document.querySelectorAll('#teacherLegend .legend-item').forEach(el => el.classList.remove('active-highlight'));
    element.classList.add('active-highlight');
    
    // Dim chips of other teachers, highlight chips of this teacher across master and details
    document.querySelectorAll('#masterTimetableTable .mt-chip, #gridClassroomContainer .ec, #gridTeacherContainer .ec').forEach(c => {
        if (parseInt(c.dataset.teacherId) === tid) {
            c.classList.add('highlighted');
            c.classList.remove('dimmed');
        } else {
            c.classList.remove('highlighted');
            c.classList.add('dimmed');
        }
    });

    // Populate lock bar
    const meta = TEACHER_META[tid] || {name: element.querySelector('span').textContent, nip:'-'};
    const status = TEACHER_LOCK_STATUS[tid] || 'none';
    
    document.getElementById('timetableLockName').textContent = meta.name;
    document.getElementById('timetableLockSub').textContent = (meta.nip_label || 'NIP') + ': ' + (meta.nip || '-');
    document.getElementById('timetableLockBadge').textContent = status === 'all' ? '🔒 Terkunci' : 'Bebas';
    document.getElementById('timetableLockBadge').className = 'ms-2 badge rounded-pill ' + (status === 'all' ? 'bg-warning text-dark' : 'bg-secondary');
    document.getElementById('timetableLockBar').classList.add('visible');
    document.getElementById('timetableLockBar').dataset.teacherId = tid;
}

function clearTimetableHighlight() {
    activeHighlightTeacherId = null;
    document.querySelectorAll('#masterTimetableTable .mt-chip, #gridClassroomContainer .ec, #gridTeacherContainer .ec').forEach(c => {
        c.classList.remove('dimmed', 'highlighted');
    });
    document.querySelectorAll('#teacherLegend .legend-item').forEach(el => el.classList.remove('active-highlight'));
    document.getElementById('timetableLockBar').classList.remove('visible');
}

async function lockHighlightedTeacher(action) {
    const tid = document.getElementById('timetableLockBar').dataset.teacherId;
    if (!tid) return;
    
    try {
        const res = await fetch(`/schedule-generator/lock-teacher/${SCHED_ID}/${tid}/${action}`, {
            method: 'POST',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': CSRF }
        });
        const data = await res.json();
        if (data.success) {
            showToast(data.message, 'success');
            setTimeout(() => location.reload(), 600);
        } else {
            Swal.fire({ icon: 'error', title: 'Lock Gagal', text: data.message });
        }
    } catch(e) {
        showToast('Error: ' + e.message, 'error');
    }
}

// ═══════════════════════════════════════════════════════════════
// OTHER CONFIRMS (SWEETALERT COPIED FROM OLD TEMPLATE)
// ═══════════════════════════════════════════════════════════════
function confirmPublish(e, link) {
    e.preventDefault();
    Swal.fire({
        title: 'Publish jadwal pelajaran?',
        text: 'Seluruh guru dapat melihat jadwal aktif ini di dashboard masing-masing.',
        icon: 'question',
        showCancelButton: true,
        confirmButtonText: 'Ya, Publish',
        cancelButtonText: 'Batal',
        confirmButtonColor: '#10b981'
    }).then(r => { if (r.isConfirmed) location.href = link.href; });
    return false;
}

function confirmReset(e, link) {
    e.preventDefault();
    Swal.fire({
        title: 'Reset hasil generate?',
        text: 'Semua jam pelajaran yang digenerate otomatis akan dihapus. Entry manual & terkunci tetap dipertahankan.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonText: 'Reset',
        cancelButtonText: 'Batal'
    }).then(r => { if (r.isConfirmed) location.href = link.href; });
    return false;
}

// HTML Escaper
function esc(str) {
    if (!str) return '';
    return String(str)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}
</script>
<?= $this->endSection() ?>
