<?php

declare(strict_types=1);



session_start();

require_once '../../config.php';

requireModule('timetable');



// Tutors see their own timetable view only

if (($_SESSION['role'] ?? '') === 'tutor') {

    $teacherView = __DIR__ . '/teacher_view.php';

    if (file_exists($teacherView)) {

        header('Location: teacher_view.php');

    } else {

        header('Location: ../../dashboard.php?error=no_access');

    }

    exit;

}

require_once __DIR__ . '/helpers.php';



if (!isset($_SESSION['user_id'])) {

    header('Location: ../../login.php');

    exit;

}



$conn = getDBConnection();

if (!$conn instanceof mysqli) {

    http_response_code(500);

    exit('Database connection failed.');

}



$classes      = timetableGetClasses($conn);

$subjects     = timetableGetSubjects($conn);

$teachers     = timetableGetTeachers($conn);

$terms        = timetableTerms();

$defaultTerm  = timetableGetCurrentTerm($conn);

$defaultYear  = timetableGetCurrentYear($conn);

?>

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Timetable Manager</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">

    <link rel="stylesheet" href="../../css/style.css">

    <style>

        .wrapper{display:block}

        #sidebar{width:250px;position:fixed;top:0;left:0;height:100vh;z-index:1000}

        #content{margin-left:250px;width:calc(100% - 250px);min-width:0;position:relative}

        .tt td,.tt th{vertical-align:top;min-width:150px}

        .tt thead th{white-space:nowrap;text-align:center}

        .special-period-row td{font-weight:700;text-align:center;vertical-align:middle}

        .special-period-row td:first-child{text-align:left;font-weight:600}

        .slot-box{min-height:105px;border-radius:.75rem}

        .slot-meta{font-size:.85rem;color:#6c757d}

        .empty-cell{min-height:105px;display:flex;align-items:center;justify-content:center}

        .toolbar-actions .btn{white-space:nowrap}

        .timetable-shell{max-width:100%;overflow-x:hidden}

        .filter-card .card-body{padding:1.25rem}

        .filter-card .row{margin-left:0;margin-right:0}

        .filter-card .col-md-3,

        .filter-card .col-md-2,

        .filter-card .col-md-5{padding-left:.5rem;padding-right:.5rem}

        .filter-card .form-select,

        .filter-card .form-control{width:100%}

        .toolbar-actions{justify-content:flex-start}

        @media (max-width: 991.98px){

            #sidebar{position:relative;width:100%;height:auto}

            #content{margin-left:0;width:100%}

            .filter-card .col-md-3,

            .filter-card .col-md-2,

            .filter-card .col-md-5{padding-left:0;padding-right:0}

            .toolbar-actions .btn{flex:1 1 auto}

        }

    </style>

</head>

<body>

<div class="wrapper">

    <nav id="sidebar" class="sidebar">

        <?php echo buildSidebar('modules/timetable/' . basename($_SERVER['PHP_SELF'])); ?>

        </nav>



    <div id="content" class="content">

        <header class="top-navbar d-flex justify-content-between align-items-center flex-wrap gap-2">

            <div>

                <h4 class="mb-1">Timetable Manager</h4>

                <div class="text-muted small">Class timetable builder with conflict checks and term copy tools.</div>

            </div>

        </header>



        <main class="container-fluid py-4 timetable-shell">

            <div class="card shadow-sm border-0 mb-4 filter-card">

                <div class="card-body">

                    <div class="row g-2 align-items-end">

                        <div class="col-md-3">

                            <label class="form-label">Class</label>

                            <select id="class_name" class="form-select">

                                <option value="">Select class</option>

                                <?php foreach ($classes as $className): ?>

                                    <option value="<?= htmlspecialchars($className) ?>"><?= htmlspecialchars($className) ?></option>

                                <?php endforeach; ?>

                            </select>

                        </div>

                        <div class="col-md-2">

                            <label class="form-label">Term</label>

                            <select id="term" class="form-select">

                                <?php foreach ($terms as $term): ?>

                                    <option value="<?= htmlspecialchars($term) ?>" <?= $term === $defaultTerm ? 'selected' : '' ?>><?= htmlspecialchars($term) ?></option>

                                <?php endforeach; ?>

                            </select>

                        </div>

                        <div class="col-md-2">

                            <label class="form-label">Academic Year</label>

                            <input type="text" id="academic_year" class="form-control" value="<?= htmlspecialchars($defaultYear) ?>">

                        </div>

                        <div class="col-md-5">

                                <div class="d-flex flex-wrap gap-2 toolbar-actions">

                                <button class="btn btn-primary" id="loadBtn"><i class="fas fa-sync-alt me-1"></i>Load Timetable</button>

                                <button class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#copyModal"><i class="fas fa-copy me-1"></i>Copy From Term</button>

                                <a href="periods.php" class="btn btn-outline-dark"><i class="fas fa-clock me-1"></i>Setup Periods</a>

                                <button class="btn btn-outline-success" id="printBtn"><i class="fas fa-print me-1"></i>Print Timetable</button>

                            </div>

                        </div>

                    </div>

                </div>

            </div>



            <div class="card shadow-sm border-0">

                <div class="card-body">

                    <div class="table-responsive">

                        <table class="table table-bordered tt mb-0">

                            <thead class="table-light">

                                <tr><th style="width:210px">Period</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>

                            </thead>

                            <tbody id="timetableBody">

                                <tr><td colspan="7" class="text-center py-5 text-muted fs-5">

                                    <i class="fas fa-chalkboard-teacher fa-2x mb-2 d-block text-secondary"></i>

                                    SELECT CLASS TO VIEW

                                </td></tr>

                            </tbody>

                        </table>

                    </div>

                </div>

            </div>

        </main>

    </div>

</div>



<div class="modal fade" id="slotModal" tabindex="-1" aria-hidden="true">

    <div class="modal-dialog">

        <div class="modal-content">

            <form id="slotForm">

                <div class="modal-header"><h5 class="modal-title">Timetable Slot</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>

                <div class="modal-body">

                    <input type="hidden" name="id" id="slot_id" value="0">

                    <input type="hidden" name="force_save" id="force_save" value="0">

                    <input type="hidden" name="class_name" id="slot_class_name">

                    <input type="hidden" name="academic_year" id="slot_year">

                    <input type="hidden" name="term" id="slot_term">

                    <input type="hidden" name="day_of_week" id="slot_day">

                    <input type="hidden" name="period_id" id="slot_period_id">

                    <div class="mb-3">

                        <label class="form-label">Subject</label>

                        <select name="subject_id" id="subject_id" class="form-select" required>

                            <option value="">Select subject</option>

                            <?php foreach ($subjects as $subject): ?>

                                <option value="<?= (int) $subject['id'] ?>"><?= htmlspecialchars($subject['subject_name']) ?></option>

                            <?php endforeach; ?>

                        </select>

                    </div>

                    <div class="mb-3">

                        <label class="form-label">Teacher</label>

                        <select name="teacher_id" id="teacher_id" class="form-select" required>

                            <option value="">Select teacher</option>

                            <?php foreach ($teachers as $teacher): ?>

                                <option value="<?= (int) $teacher['id'] ?>"><?= htmlspecialchars($teacher['full_name']) ?></option>

                            <?php endforeach; ?>

                        </select>

                    </div>

                    <div class="mb-3"><label class="form-label">Room</label><input type="text" name="room" id="room" class="form-control"></div>

                    <div class="row g-3">

                        <div class="col-md-6"><label class="form-label">Day</label><input type="text" id="slot_day_label" class="form-control" readonly></div>

                        <div class="col-md-6"><label class="form-label">Period</label><input type="text" id="slot_period_label" class="form-control" readonly></div>

                    </div>

                    <div id="conflictBox" class="alert alert-warning d-none mt-3 mb-0"></div>

                </div>

                <div class="modal-footer"><button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button><button type="submit" class="btn btn-primary">Save Slot</button></div>

            </form>

        </div>

    </div>

</div>



<div class="modal fade" id="copyModal" tabindex="-1" aria-hidden="true">

    <div class="modal-dialog">

        <div class="modal-content">

            <form id="copyForm">

                <div class="modal-header"><h5 class="modal-title">Copy Timetable</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>

                <div class="modal-body">

                    <div class="row g-3">

                        <div class="col-md-6"><label class="form-label">Source Class</label><select name="source_class" class="form-select" required><option value="">Select class</option><?php foreach ($classes as $className): ?><option value="<?= htmlspecialchars($className) ?>"><?= htmlspecialchars($className) ?></option><?php endforeach; ?></select></div>

                        <div class="col-md-3"><label class="form-label">Source Term</label><select name="source_term" class="form-select" required><?php foreach ($terms as $term): ?><option value="<?= htmlspecialchars($term) ?>" <?= $term === $defaultTerm ? 'selected' : '' ?>><?= htmlspecialchars($term) ?></option><?php endforeach; ?></select></div>

                        <div class="col-md-3"><label class="form-label">Source Year</label><input type="text" name="source_year" class="form-control" value="<?= htmlspecialchars($defaultYear) ?>" required></div>

                        <div class="col-md-6"><label class="form-label">Target Class</label><select name="target_class" class="form-select" required><option value="">Select class</option><?php foreach ($classes as $className): ?><option value="<?= htmlspecialchars($className) ?>"><?= htmlspecialchars($className) ?></option><?php endforeach; ?></select></div>

                        <div class="col-md-3"><label class="form-label">Target Term</label><select name="target_term" class="form-select" required><?php foreach ($terms as $term): ?><option value="<?= htmlspecialchars($term) ?>" <?= $term === $defaultTerm ? 'selected' : '' ?>><?= htmlspecialchars($term) ?></option><?php endforeach; ?></select></div>

                        <div class="col-md-3"><label class="form-label">Target Year</label><input type="text" name="target_year" class="form-control" value="<?= htmlspecialchars($defaultYear) ?>" required></div>

                    </div>

                </div>

                <div class="modal-footer"><button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button><button type="submit" class="btn btn-primary">Copy Timetable</button></div>

            </form>

        </div>

    </div>

</div>



<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>

<script>

const DAYS = ['Mon','Tue','Wed','Thu','Fri','Sat'];

let PERIODS = [];

let slots = [];



// span:true  = one row across all days (breaks, lunch, etc.)

// span:false = individual cell per day (worship, closing time)

const PERIOD_TYPE_META = <?php echo json_encode(timetablePeriodTypes($conn), JSON_UNESCAPED_UNICODE); ?>;

// Periods that can hold a lesson: their cells stay addable, so they must not

// be treated as "special" even though they have display metadata.

const LESSON_CAPABLE_TYPES = <?php echo json_encode(timetableLessonCapableTypes()); ?>;



function getPeriodType(p) {

    if (p.period_type && p.period_type !== 'teaching') return p.period_type;

    const n = (p.period_name || '').toLowerCase();

    if (/\bnap\b/.test(n)) return 'nap';

    if (/circle/.test(n)) return 'circle_time';

    if (/assembly/.test(n)) return 'assembly';

    if (/\blunch\b|launch/.test(n)) return 'lunch';

    if (/recess/.test(n)) return 'recess';

    if (/arrival|settling|reporting/.test(n)) return 'arrival';

    if (/routine/.test(n)) return 'routines';

    if (/silent/.test(n)) return 'silent_hour';

    if (/worship/.test(n)) return 'worship';

    if (/closing/.test(n)) return 'closing_time';

    if (Number(p.is_break) === 1) return 'break';

    return 'teaching';

}

const modal = new bootstrap.Modal(document.getElementById('slotModal'));

const copyModal = new bootstrap.Modal(document.getElementById('copyModal'));

const esc = (v) => String(v ?? '').replace(/[&<>"']/g, (c) => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[c]));

const msg = (text, type='success') => { const d=document.createElement('div'); d.className=`alert alert-${type} alert-dismissible fade show position-fixed top-0 end-0 m-3`; d.style.zIndex='1080'; d.innerHTML=`${esc(text)}<button type="button" class="btn-close" data-bs-dismiss="alert"></button>`; document.body.appendChild(d); setTimeout(()=>d.remove(),3500); };

const filters = () => ({class_name:document.getElementById('class_name').value, term:document.getElementById('term').value, academic_year:document.getElementById('academic_year').value});

const periodText = (p) => `${p.period_name} (${String(p.start_time).slice(0,5)} - ${String(p.end_time).slice(0,5)})`;



async function loadPeriodsForClass(className) {

    if (!className) { PERIODS = []; render(); return; }

    const r = await fetch('ajax/get_periods.php?class_name=' + encodeURIComponent(className));

    PERIODS = await r.json();

}



// Reload periods when class changes, reset timetable

document.getElementById('class_name').addEventListener('change', function () {

    const body = document.getElementById('timetableBody');

    slots = [];

    if (!this.value) {

        PERIODS = [];

        body.innerHTML = '<tr><td colspan="7" class="text-center py-5 text-muted fs-5"><i class="fas fa-chalkboard-teacher fa-2x mb-2 d-block text-secondary"></i>SELECT CLASS TO VIEW</td></tr>';

    } else {

        body.innerHTML = '<tr><td colspan="7" class="text-center py-4 text-muted">Select term and year, then click Load Timetable.</td></tr>';

        loadPeriodsForClass(this.value);

    }

});



function render() {

    const body = document.getElementById('timetableBody');

    const className = document.getElementById('class_name').value;

    if (!className) {

        body.innerHTML = '<tr><td colspan="7" class="text-center py-5 text-muted fs-5"><i class="fas fa-chalkboard-teacher fa-2x mb-2 d-block text-secondary"></i>SELECT CLASS TO VIEW</td></tr>';

        return;

    }

    if (!PERIODS.length) {

        body.innerHTML = '<tr><td colspan="7" class="text-center py-5 text-muted">No periods configured for this class. <a href="periods.php">Set up periods</a>.</td></tr>';

        return;

    }

    body.innerHTML = PERIODS.map((p) => {

        const left = `<div class="fw-semibold">${esc(p.period_name)}</div><div class="small text-muted">${String(p.start_time).slice(0,5)} - ${String(p.end_time).slice(0,5)}</div>`;

        const pType = getPeriodType(p);

        const meta = LESSON_CAPABLE_TYPES.includes(pType) ? null : PERIOD_TYPE_META[pType];

        if (meta && meta.span) {

            return `<tr class="special-period-row" style="background:${meta.bg};color:${meta.text}"><td style="min-width:210px">${left}</td><td colspan="6">${meta.icon} ${meta.label.toUpperCase()}</td></tr>`;

        }

        const cells = DAYS.map((day) => {

            const slot = slots.find((s) => Number(s.period_id) === Number(p.id) && s.day_of_week === day);

            if (!slot) {

                if (meta) {

                    return `<td style="background:${meta.bg};color:${meta.text};text-align:center;vertical-align:middle"><div style="padding:6px 2px;font-size:.85rem">${meta.icon} ${meta.label}</div></td>`;

                }

                return `<td><div class="empty-cell"><button class="btn btn-sm btn-outline-primary" onclick="openAdd('${day}',${p.id})"><i class="fas fa-plus me-1"></i>Add</button></div></td>`;

            }

            return `<td><div class="slot-box border p-2 bg-light"><div class="fw-semibold">${esc(slot.subject_name || 'Unassigned Subject')}</div><div class="slot-meta">${esc(slot.teacher_name || 'No teacher')}</div><div class="slot-meta">${esc(slot.room || 'No room')}</div><div class="d-flex justify-content-end gap-1 mt-2"><button class="btn btn-sm btn-outline-primary" onclick="openEditById(${slot.id})"><i class="fas fa-pen"></i></button><button class="btn btn-sm btn-outline-danger" onclick="delSlot(${slot.id})"><i class="fas fa-trash"></i></button></div></div></td>`;

        }).join('');

        return `<tr><td>${left}</td>${cells}</tr>`;

    }).join('');

}



async function loadTimetable() {

    const f = filters();

    if (!f.class_name || !f.term || !f.academic_year) { msg('Select class, term, and academic year first.', 'warning'); return; }

    // Ensure periods for this class are loaded

    if (!PERIODS.length) { await loadPeriodsForClass(f.class_name); }

    const r = await fetch('ajax/get_timetable.php', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:new URLSearchParams(f)});

    slots = await r.json();

    render();

}



function resetForm() {

    document.getElementById('slotForm').reset();

    document.getElementById('slot_id').value = '0';

    document.getElementById('force_save').value = '0';

    document.getElementById('conflictBox').classList.add('d-none');

    document.getElementById('conflictBox').textContent = '';

}



function openAdd(day, periodId) {

    const f = filters();

    if (!f.class_name) { msg('Load a class timetable first.', 'warning'); return; }

    const p = PERIODS.find((item) => Number(item.id) === Number(periodId));

    resetForm();

    document.getElementById('slot_class_name').value = f.class_name;

    document.getElementById('slot_year').value = f.academic_year;

    document.getElementById('slot_term').value = f.term;

    document.getElementById('slot_day').value = day;

    document.getElementById('slot_period_id').value = String(periodId);

    document.getElementById('slot_day_label').value = day;

    document.getElementById('slot_period_label').value = p ? periodText(p) : '';

    modal.show();

}



function openEdit(slot) {

    resetForm();

    const p = PERIODS.find((item) => Number(item.id) === Number(slot.period_id));

    document.getElementById('slot_id').value = slot.id;

    document.getElementById('slot_class_name').value = slot.class_name;

    document.getElementById('slot_year').value = slot.academic_year;

    document.getElementById('slot_term').value = slot.term;

    document.getElementById('slot_day').value = slot.day_of_week;

    document.getElementById('slot_period_id').value = slot.period_id;

    document.getElementById('slot_day_label').value = slot.day_of_week;

    document.getElementById('slot_period_label').value = p ? periodText(p) : '';

    document.getElementById('subject_id').value = slot.subject_id || '';

    document.getElementById('teacher_id').value = slot.teacher_id || '';

    document.getElementById('room').value = slot.room || '';

    modal.show();

}



function openEditById(id) {

    const slot = slots.find((item) => Number(item.id) === Number(id));

    if (slot) openEdit(slot);

}



async function doSave(force) {

    const fd = new FormData(document.getElementById('slotForm'));

    fd.set('force_save', force ? '1' : '0');

    const r = await fetch('ajax/save_slot.php', {method:'POST', body:new URLSearchParams(fd)});

    const data = await r.json();

    if (!data.success && data.conflict) {

        const box = document.getElementById('conflictBox');

        box.classList.remove('d-none');

        box.textContent = data.details || data.message || 'Teacher conflict detected.';

        if (confirm((data.details || data.message || 'Teacher conflict detected.') + ' Save anyway?')) return doSave(true);

        return;

    }

    msg(data.message || (data.success ? 'Slot saved.' : 'Save failed.'), data.success ? 'success' : 'danger');

    if (data.success) { modal.hide(); loadTimetable(); }

}



async function delSlot(id) {

    if (!confirm('Delete this timetable slot?')) return;

    const r = await fetch('ajax/delete_slot.php', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:new URLSearchParams({id:String(id)})});

    const data = await r.json();

    msg(data.message || (data.success ? 'Slot deleted.' : 'Delete failed.'), data.success ? 'success' : 'danger');

    if (data.success) loadTimetable();

}



document.getElementById('slotForm').addEventListener('submit', async (e) => { e.preventDefault(); await doSave(false); });

document.getElementById('copyForm').addEventListener('submit', async (e) => {

    e.preventDefault();

    const r = await fetch('ajax/copy_timetable.php', {method:'POST', body:new URLSearchParams(new FormData(e.target))});

    const data = await r.json();

    msg(data.message || `Copied ${data.copied_count || 0} slots. Skipped ${data.skipped_count || 0}.`, data.success ? 'success' : 'danger');

    if (data.success) { copyModal.hide(); loadTimetable(); }

});

document.getElementById('loadBtn').addEventListener('click', loadTimetable);

document.getElementById('printBtn').addEventListener('click', () => {

    const f = filters();

    if (!f.class_name) { msg('Select a class first.', 'warning'); return; }

    window.open(`print.php?${new URLSearchParams(f).toString()}`, '_blank');

});

render();

</script>

</body>

</html>

