<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<?= csrf_meta() ?>

<?php
$queryParams = [
    'semester'    => $semester ?? '',
    'school_year' => $schoolYear ?? '',
];
$queryString = http_build_query(array_filter($queryParams, static function ($value) {
    return $value !== '';
}));
?>

<div
    class="container-fluid py-4"
    data-endpoint="<?= esc($endpoint ?? '') ?>"
    data-save-endpoint="<?= esc($saveEndpoint ?? '') ?>"
    data-csrf-name="<?= esc(csrf_token()) ?>"
    data-csrf-value="<?= esc(csrf_hash()) ?>"
    data-semester="<?= esc($semester ?? '') ?>"
    data-school-year="<?= esc($schoolYear ?? '') ?>"
    data-is-current="<?= isset($isCurrentYear) && $isCurrentYear ? '1' : '0' ?>"
>
  <div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3">
    <h2 class="mb-0">Admin &amp; Teacher — Monthly Attendance</h2>
    <div class="legend">
      <span class="badge bg-success">P</span><span class="ms-1">Present</span>
      <span class="badge bg-danger ms-3">A</span><span class="ms-1">Absent</span>
      <span class="badge bg-warning text-dark ms-3">L</span><span class="ms-1">Late</span>
      <span class="badge bg-info text-dark ms-3">NS</span><span class="ms-1">No School</span>
      <span class="ms-3 cell-empty">—</span><span class="ms-1">No entry</span>
    </div>
  </div>
  <?php if (!empty($missingYear)): ?>
    <div class="alert alert-warning" role="alert">
      Current school year is not configured. This page is read-only until configured in
      <a href="<?= site_url('configuration/configuration_view') ?>" class="alert-link">Add/Edit Configuration</a> (key: <code>school_year</code>).
    </div>
  <?php endif; ?>

  <form class="row gy-2 gx-3 align-items-end justify-content-center mb-4" method="get" action="<?= site_url('admin/teacher-attendance/month') ?>">
    <div class="col-md-3">
      <label class="form-label">School Year</label>
      <select name="school_year" class="form-select">
        <?php
          $years = isset($schoolYears) && is_array($schoolYears) ? $schoolYears : [];
          if (empty($years) && !empty($schoolYear)) $years = [$schoolYear];
          foreach ($years as $y): $val = is_array($y) && isset($y['school_year']) ? $y['school_year'] : (string)$y; ?>
            <option value="<?= esc($val) ?>" <?= ((string)($schoolYear ?? '') === (string)$val) ? 'selected' : '' ?>>
              <?= esc($val) ?>
            </option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-md-2">
      <label class="form-label">Semester</label>
      <select name="semester" class="form-select">
        <?php $semVal = (string)($semester ?? ''); ?>
        <?php foreach (['---','Fall','Spring'] as $sem): ?>
          <option value="<?= esc($sem) ?>" <?= ($semVal === $sem ? 'selected' : '') ?>><?= esc($sem) ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-md-4 d-flex gap-2">
      <button type="submit" class="btn btn-secondary">Load</button>
      <a class="btn btn-outline-secondary" href="<?= site_url('admin/teacher-attendance/month') ?>">Reset</a>
      <a class="btn btn-outline-primary"
        href="<?= site_url('admin/teacher-attendance/month.csv' . ($queryString ? ('?' . $queryString) : '')) ?>">
        Export CSV
      </a>
    </div>
  </form>

  <style>
    .att-select.form-select.form-select-sm {
      min-width: 54px;
      padding-left: 6px;
      padding-right: 18px;
      line-height: 1.1;
    }

    .att-none {
      background: transparent;
      color: #6c757d;
    }

    .att-present {
      background: #19875422;
    }

    .att-absent {
      background: #dc354522;
    }

    .att-late {
      background: #ffc10755;
    }

    .month-grid-wrap {
      overflow-x: auto;
    }

    .month-grid thead th {
      position: sticky;
      top: 0;
      z-index: 2;
      background: #f8f9fa;
    }

    .month-grid .sticky-col {
      position: sticky;
      left: 0;
      z-index: 3;
      background: #fff;
      max-width: 140px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .month-grid .sticky-col-2 {
      position: sticky;
      left: 180px;
      z-index: 3;
      background: #fff;
    }

    .month-grid .sticky-col-3 {
      position: sticky;
      left: 460px; /* 180 (col1) + 280 (col2) */
      z-index: 3;
      background: #fff;
    }

    .badge-cell {
      display: inline-block;
      min-width: 18px;
      text-align: center;
      border-radius: 4px;
      padding: 2px 0;
      font-weight: 600;
    }

    .cell-empty {
      color: #999;
    }

    .legend .badge {
      min-width: 28px;
    }

    .month-grid .badge-cell {
      min-width: 32px;
      padding: 4px 0;
      border-radius: 6px;
      font-weight: 700;
      border: 1px solid transparent;
    }

    .month-grid .badge-cell.bg-success {
      background-color: #157347 !important;
      border-color: #0f5132;
      color: #fff !important;
      box-shadow: 0 0 0 1px rgba(0, 0, 0, .25) inset, 0 0 0 3px rgba(21, 115, 71, .18);
    }

    .month-grid .badge-cell.bg-danger {
      background-color: #bb2d3b !important;
      border-color: #842029;
      color: #fff !important;
      box-shadow: 0 0 0 1px rgba(0, 0, 0, .25) inset, 0 0 0 3px rgba(187, 45, 59, .18);
    }

    .month-grid .badge-cell.bg-warning {
      background-color: #ffca2c !important;
      border-color: #997404;
      color: #111 !important;
      box-shadow: 0 0 0 1px rgba(0, 0, 0, .18) inset, 0 0 0 3px rgba(255, 202, 44, .25);
    }

    .month-grid .badge-cell.bg-info {
      background-color: #0dcaf0 !important; /* Bootstrap info */
      border-color: #055160; /* darker info border */
      color: #111 !important;
      box-shadow: 0 0 0 1px rgba(0, 0, 0, .18) inset, 0 0 0 3px rgba(13, 202, 240, .25);
    }

    .month-grid .cell-empty {
      color: #adb5bd;
    }

    .att-select.form-select.form-select-sm {
      min-width: 54px;
      padding-left: 6px;
      padding-right: 18px;
      line-height: 1.1;
      border: 1px solid #adb5bd;
      transition: background-color .12s ease, border-color .12s ease, color .12s ease;
    }

    /* No School column/day highlight */
    .no-school-day {
      background-color: #cff4fc !important; /* Bootstrap info-subtle */
    }

    .att-select.att-present {
      background: #157347;
      color: #fff;
      border-color: #0f5132;
      box-shadow: 0 0 0 2px rgba(21, 115, 71, .18);
    }

    .att-select.att-absent {
      background: #bb2d3b;
      color: #fff;
      border-color: #842029;
      box-shadow: 0 0 0 2px rgba(187, 45, 59, .18);
    }

    .att-select.att-late {
      background: #ffca2c;
      color: #111;
      border-color: #997404;
      box-shadow: 0 0 0 2px rgba(255, 202, 44, .25);
    }

    .att-select.att-none {
      background: #fff;
      color: #212529;
      border-color: #adb5bd;
    }
  </style>

  <div class="card shadow-sm mb-4">
    <div class="card-header d-flex justify-content-between align-items-center">
      <div>
        <strong>Teachers &amp; Assistants — Sundays in <span id="teacherMonthLabel"><?= esc($rangeLabel ?? ('School Year ' . ($schoolYear ?? ''))) ?></span></strong>
        <?php if (isset($isCurrentYear) && !$isCurrentYear): ?>
          <span class="badge bg-secondary ms-2">Read-only (Past Year)</span>
        <?php endif; ?>
      </div>
      <small class="text-muted">Use the dropdowns to set attendance inline</small>
    </div>
    <div class="card-body month-grid-wrap">
      <div id="teachersGrid" class="text-center text-muted py-4">Loading...</div>
    </div>
  </div>

  <div class="card shadow-sm mb-4">
    <div class="card-header d-flex justify-content-between align-items-center">
      <div>
        <strong>Admins — Sundays in <span id="adminMonthLabel"><?= esc($rangeLabel ?? ('School Year ' . ($schoolYear ?? ''))) ?></span></strong>
        <span class="text-muted ms-2">(All roles except Parent/Guest/Teacher/Teacher Assistant)</span>
      </div>
    </div>
    <div class="card-body month-grid-wrap">
      <div id="adminsGrid" class="text-center text-muted py-4">Loading...</div>
    </div>
  </div>
</div>

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

<?= $this->section('scripts') ?>
<script>
// Bootstrap 5 Toast utility
(function(){
  function ensureToastContainer() {
    var c = document.getElementById('toast-container');
    if (!c) {
      c = document.createElement('div');
      c.id = 'toast-container';
      c.className = 'toast-container position-fixed top-0 end-0 p-3';
      c.style.zIndex = '1080';
      document.body.appendChild(c);
    }
    return c;
  }
  window.showToast = function(message, ok) {
    var c = ensureToastContainer();
    var el = document.createElement('div');
    el.className = 'toast align-items-center text-bg-' + (ok === false ? 'danger' : 'success') + ' border-0';
    el.setAttribute('role','alert');
    el.setAttribute('aria-live','assertive');
    el.setAttribute('aria-atomic','true');
    el.innerHTML = '<div class="d-flex">'
      + '<div class="toast-body">' + (message || (ok === false ? 'Action failed' : 'Saved')) + '</div>'
      + '<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>'
      + '</div>';
    c.appendChild(el);
    try {
      var t = new bootstrap.Toast(el, { delay: 2500, autohide: true });
      el.addEventListener('hidden.bs.toast', function(){ el.remove(); });
      t.show();
    } catch (_) {
      setTimeout(function(){ el.remove(); }, 2500);
    }
  }
})();
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
  var container = document.querySelector('[data-endpoint]');
  if (!container) {
    return;
  }

  var endpoint = container.getAttribute('data-endpoint') || '';
  var saveUrl = container.getAttribute('data-save-endpoint') || '';
  var csrfName = container.getAttribute('data-csrf-name') || '';
  var csrfHash = container.getAttribute('data-csrf-value') || '';
  var semesterDefault = container.getAttribute('data-semester') || '';
  var schoolYearDefault = container.getAttribute('data-school-year') || '';
  var isCurrentYear = (container.getAttribute('data-is-current') || '1') === '1';

  var teachersGrid = document.getElementById('teachersGrid');
  var adminsGrid = document.getElementById('adminsGrid');
  var teacherMonthLabel = document.getElementById('teacherMonthLabel');
  var adminMonthLabel = document.getElementById('adminMonthLabel');

  if (!endpoint) {
    if (teachersGrid) {
      teachersGrid.innerHTML = '<div class="alert alert-danger mb-0">Endpoint not configured.</div>';
    }
    if (adminsGrid) {
      adminsGrid.innerHTML = '';
    }
    return;
  }

  fetch(endpoint, {
    headers: { 'Accept': 'application/json' },
    credentials: 'same-origin'
  })
    .then(function(response) {
      if (!response.ok) {
        throw new Error('Request failed with status ' + response.status);
      }
      return response.json();
    })
    .then(function(payload) {
      renderTeachers(payload);
      renderAdmins(payload);
      initializeSelects();
    })
    .catch(function(error) {
      console.error(error);
      if (teachersGrid) {
        teachersGrid.innerHTML = '<div class="alert alert-danger mb-0">Unable to load teacher attendance.</div>';
      }
      if (adminsGrid) {
        adminsGrid.innerHTML = '<div class="alert alert-danger mb-0">Unable to load admin attendance.</div>';
      }
      if (window.showToast) showToast('Failed to load attendance data', false);
    });

  function clearElement(el) {
    if (!el) {
      return;
    }
    while (el.firstChild) {
      el.removeChild(el.firstChild);
    }
  }

  function renderTeachers(payload) {
    if (!teachersGrid) {
      return;
    }
    clearElement(teachersGrid);

    var filters = payload && payload.filters ? payload.filters : {};
    var sections = payload && payload.sections ? payload.sections : [];
    var sundays = payload && payload.sundays ? payload.sundays : [];
    var noSchoolDays = payload && payload.noSchoolDays ? payload.noSchoolDays : [];
    var noSchoolSet = {};
    for (var i = 0; i < noSchoolDays.length; i++) { noSchoolSet[noSchoolDays[i]] = true; }

    var label = filters.range_label || filters.month_label || '';
    if (teacherMonthLabel && label) {
      teacherMonthLabel.textContent = label;
    }

    if (!sections.length) {
      var info = document.createElement('div');
      info.className = 'alert alert-info mb-0';
      info.textContent = 'No sections with assigned teachers found for this term.';
      teachersGrid.appendChild(info);
      return;
    }

    var table = document.createElement('table');
    table.className = 'table table-bordered table-striped month-grid align-middle';
    table.setAttribute('data-no-mgmt-sticky', '1');

    var thead = document.createElement('thead');
    var headerRow = document.createElement('tr');

    var thSection = document.createElement('th');
    thSection.className = 'sticky-col';
    thSection.style.minWidth = '180px';
    thSection.appendChild(document.createTextNode('Class / Section'));
    headerRow.appendChild(thSection);

    var thTeacher = document.createElement('th');
    thTeacher.className = 'sticky-col-2';
    thTeacher.style.minWidth = '280px';
    thTeacher.appendChild(document.createTextNode('Teacher'));
    headerRow.appendChild(thTeacher);

    var thRole = document.createElement('th');
    thRole.className = 'sticky-col-3 text-center';
    thRole.style.minWidth = '120px';
    thRole.appendChild(document.createTextNode('Role'));
    headerRow.appendChild(thRole);

    for (var i = 0; i < sundays.length; i++) {
      var day = sundays[i];
      var thDay = document.createElement('th');
      thDay.className = 'text-center';
      thDay.style.minWidth = '56px';
      if (noSchoolSet[day]) thDay.classList.add('no-school-day');
      // Show date as mm-dd-yyyy
      var yyyy = day.substring(0, 4);
      var mm = day.substring(5, 7);
      var dd = day.substring(8, 10);
      thDay.title = day; // full YYYY-MM-DD tooltip
      thDay.appendChild(document.createTextNode(mm + '-' + dd));
      headerRow.appendChild(thDay);
    }

    var totals = ['P', 'A', 'L'];
    for (var j = 0; j < totals.length; j++) {
      var thTotal = document.createElement('th');
      thTotal.className = 'text-center';
      thTotal.style.minWidth = '70px';
      thTotal.appendChild(document.createTextNode(totals[j]));
      headerRow.appendChild(thTotal);
    }

    thead.appendChild(headerRow);
    table.appendChild(thead);

    var tbody = document.createElement('tbody');
    var hasTeachers = false;

    for (var s = 0; s < sections.length; s++) {
      var section = sections[s];
      var teacherList = section && section.teachers ? section.teachers : [];
      if (!teacherList.length) {
        continue;
      }
      hasTeachers = true;
      var rowSpan = teacherList.length;

      for (var t = 0; t < teacherList.length; t++) {
        var teacher = teacherList[t];
        var row = document.createElement('tr');

        if (t === 0) {
          var tdSection = document.createElement('td');
          tdSection.className = 'sticky-col';
          tdSection.style.minWidth = '180px';
          tdSection.rowSpan = rowSpan;
          tdSection.appendChild(document.createTextNode(section.label || ('Section ' + section.section_code)));
          row.appendChild(tdSection);
        }

        var tdTeacher = document.createElement('td');
        tdTeacher.className = 'sticky-col-2';
        tdTeacher.appendChild(document.createTextNode(teacher.name || '—'));
        row.appendChild(tdTeacher);

        var tdRole = document.createElement('td');
        tdRole.className = 'sticky-col-3 text-center';
        var roleText = (teacher.position || '').toLowerCase() === 'main' ? 'Main' : 'Assistant';
        tdRole.appendChild(document.createTextNode(roleText));
        row.appendChild(tdRole);

        for (var d = 0; d < sundays.length; d++) {
          var dayKey = sundays[d];
          var cellData = teacher.cells && teacher.cells[dayKey] ? teacher.cells[dayKey] : null;
          var status = '';
          if (cellData && cellData.status) {
            var st = String(cellData.status).toLowerCase();
            if (st === 'present' || st === 'absent' || st === 'late') {
              status = st;
            }
          }

          var tdCell = document.createElement('td');
          tdCell.className = 'text-center';
          if (noSchoolSet[dayKey]) {
            tdCell.classList.add('no-school-day');
            var ns = document.createElement('span');
            ns.className = 'badge-cell bg-info text-dark';
            ns.textContent = 'NS';
            tdCell.appendChild(ns);
            row.appendChild(tdCell);
            continue;
          }

          var select = createAttendanceSelect(
            'teacher',
            section.section_code,
            teacher.user_id || teacher.teacher_id || section.section_code,
            dayKey,
            filters,
            roleText,
            status
          );
          tdCell.appendChild(select);
          row.appendChild(tdCell);
        }

        var totalsRow = teacher.totals || { p: 0, a: 0, l: 0 };
        var totalValues = [totalsRow.p || 0, totalsRow.a || 0, totalsRow.l || 0];
        for (var tv = 0; tv < totalValues.length; tv++) {
          var tdTotal = document.createElement('td');
          tdTotal.className = 'text-center';
          var strong = document.createElement('strong');
          strong.appendChild(document.createTextNode(String(totalValues[tv])));
          tdTotal.appendChild(strong);
          row.appendChild(tdTotal);
        }

        tbody.appendChild(row);
      }
    }

    if (!hasTeachers) {
      var emptyRow = document.createElement('tr');
      var emptyCell = document.createElement('td');
      emptyCell.colSpan = 3 + sundays.length + 3;
      emptyCell.className = 'text-center';
      emptyCell.appendChild(document.createTextNode('No teachers assigned.'));
      emptyRow.appendChild(emptyCell);
      tbody.appendChild(emptyRow);
    }

    table.appendChild(tbody);
    teachersGrid.appendChild(table);
  }

  function renderAdmins(payload) {
    if (!adminsGrid) {
      return;
    }
    clearElement(adminsGrid);

    var filters = payload && payload.filters ? payload.filters : {};
    var admins = payload && payload.admins ? payload.admins : [];
    var sundays = payload && payload.sundays ? payload.sundays : [];
    var noSchoolDays = payload && payload.noSchoolDays ? payload.noSchoolDays : [];
    var noSchoolSet = {};
    for (var i = 0; i < noSchoolDays.length; i++) { noSchoolSet[noSchoolDays[i]] = true; }

    var label = filters.range_label || filters.month_label || '';
    if (adminMonthLabel && label) {
      adminMonthLabel.textContent = label;
    }

    if (!admins.length) {
      var info = document.createElement('div');
      info.className = 'alert alert-info mb-0';
      info.textContent = 'No admin users found for this term.';
      adminsGrid.appendChild(info);
      return;
    }

    var table = document.createElement('table');
    table.className = 'table table-bordered table-striped month-grid align-middle';
    table.setAttribute('data-no-mgmt-sticky', '1');

    var thead = document.createElement('thead');
    var headerRow = document.createElement('tr');

    var thAdmin = document.createElement('th');
    thAdmin.className = 'sticky-col';
    thAdmin.style.minWidth = '180px';
    thAdmin.appendChild(document.createTextNode('Admin'));
    headerRow.appendChild(thAdmin);

    var thRole = document.createElement('th');
    thRole.className = 'sticky-col-2 text-center';
    thRole.style.minWidth = '240px';
    thRole.appendChild(document.createTextNode('Role'));
    headerRow.appendChild(thRole);

    for (var i = 0; i < sundays.length; i++) {
      var thDay = document.createElement('th');
      thDay.className = 'text-center';
      thDay.style.minWidth = '56px';
      if (noSchoolSet[sundays[i]]) thDay.classList.add('no-school-day');
      // Show date as mm-dd-yyyy
      var sday = sundays[i];
      var sdd = sday.substring(8, 10);
      var smm = sday.substring(5, 7);
      var syyyy = sday.substring(0, 4);
      thDay.title = sday; // full YYYY-MM-DD tooltip
      thDay.appendChild(document.createTextNode(smm + '-' + sdd));
      headerRow.appendChild(thDay);
    }

    var totals = ['P', 'A', 'L'];
    for (var j = 0; j < totals.length; j++) {
      var thTotal = document.createElement('th');
      thTotal.className = 'text-center';
      thTotal.style.minWidth = '70px';
      thTotal.appendChild(document.createTextNode(totals[j]));
      headerRow.appendChild(thTotal);
    }

    thead.appendChild(headerRow);
    table.appendChild(thead);

    var tbody = document.createElement('tbody');

    for (var a = 0; a < admins.length; a++) {
      var admin = admins[a];
      var row = document.createElement('tr');

      var tdName = document.createElement('td');
      tdName.className = 'sticky-col';
      tdName.appendChild(document.createTextNode(admin.name || '—'));
      row.appendChild(tdName);

      var tdRole = document.createElement('td');
      tdRole.className = 'sticky-col-2 text-center';
      tdRole.appendChild(document.createTextNode(admin.role || '—'));
      row.appendChild(tdRole);

      for (var d = 0; d < sundays.length; d++) {
        var dayKey = sundays[d];
        var cellData = admin.cells && admin.cells[dayKey] ? admin.cells[dayKey] : null;
        var status = '';
        if (cellData && cellData.status) {
          var st = String(cellData.status).toLowerCase();
          if (st === 'present' || st === 'absent' || st === 'late') {
            status = st;
          }
        }

        var tdCell = document.createElement('td');
        tdCell.className = 'text-center';
        if (noSchoolSet[dayKey]) {
          tdCell.classList.add('no-school-day');
          var ns = document.createElement('span');
          ns.className = 'badge-cell bg-info text-dark';
          ns.textContent = 'NS';
          tdCell.appendChild(ns);
          row.appendChild(tdCell);
          continue;
        }

        var select = createAttendanceSelect(
          'admin',
          null,
          admin.user_id,
          dayKey,
          filters,
          admin.role || 'Admin',
          status
        );
        tdCell.appendChild(select);
        row.appendChild(tdCell);
      }

      var totalsRow = admin.totals || { p: 0, a: 0, l: 0 };
      var totalValues = [totalsRow.p || 0, totalsRow.a || 0, totalsRow.l || 0];
      for (var tv = 0; tv < totalValues.length; tv++) {
        var tdTotal = document.createElement('td');
        tdTotal.className = 'text-center';
        var strong = document.createElement('strong');
        strong.appendChild(document.createTextNode(String(totalValues[tv])));
        tdTotal.appendChild(strong);
        row.appendChild(tdTotal);
      }

      tbody.appendChild(row);
    }

    table.appendChild(tbody);
    adminsGrid.appendChild(table);
  }

  function createAttendanceSelect(type, sectionCode, userId, date, filters, roleName, currentValue) {
    var select = document.createElement('select');
    select.className = 'form-select form-select-sm att-select';
    select.setAttribute('data-type', type);
    if (sectionCode !== null && sectionCode !== undefined) {
      select.setAttribute('data-section-id', sectionCode);
    }
    select.setAttribute('data-user-id', userId);
    select.setAttribute('data-date', date);
    // Derive semester for saves: if filter is whole-year (---), infer by date
    var semForSave = filters.semester || semesterDefault;
    if (semForSave === '---') {
      semForSave = inferSemesterByDate(date, (filters.school_year || schoolYearDefault));
    }
    select.setAttribute('data-semester', semForSave);
    select.setAttribute('data-school-year', filters.school_year || schoolYearDefault);
    if (roleName) {
      select.setAttribute('data-role-name', roleName);
    }

    var statuses = ['', 'present', 'absent', 'late'];
    var labels = ['—', 'P', 'A', 'L'];
    for (var i = 0; i < statuses.length; i++) {
      var option = document.createElement('option');
      option.value = statuses[i];
      option.appendChild(document.createTextNode(labels[i]));
      if (statuses[i] === currentValue) {
        option.selected = true;
      }
      select.appendChild(option);
    }

    if (!isCurrentYear) {
      select.disabled = true;
      select.title = 'Editing disabled for non-current year';
    }

    return select;
  }

  // Infer semester by date using fixed windows:
  // Fall:   Y1-09-21 to Y2-01-18
  // Spring: Y2-01-25 to Y2-05-30
  function inferSemesterByDate(dateStr, schoolYear) {
    try {
      if (!schoolYear || schoolYear.indexOf('-') < 0) return '';
      var parts = schoolYear.split('-');
      var y1 = parseInt(parts[0], 10);
      var y2 = parseInt(parts[1], 10);
      if (!y1 || !y2) return '';
      var fallStart = new Date(y1 + '-09-21T00:00:00Z');
      var fallEnd   = new Date(y2 + '-01-18T00:00:00Z');
      var spStart   = new Date(y2 + '-01-25T00:00:00Z');
      var spEnd     = new Date(y2 + '-05-30T00:00:00Z');
      var d         = new Date(dateStr + 'T00:00:00Z');
      if (d >= fallStart && d <= fallEnd) return 'Fall';
      if (d >= spStart && d <= spEnd) return 'Spring';
      // Fallback by month if out of bounds
      var m = d.getUTCMonth() + 1; // 1..12
      return (m >= 9 || m <= 1) ? 'Fall' : 'Spring';
    } catch (_) {
      return '';
    }
  }

  function initializeSelects() {
    var selects = document.querySelectorAll('.att-select');
    for (var i = 0; i < selects.length; i++) {
      applyAppearance(selects[i]);
    }
  }

  function applyAppearance(select) {
    if (!select) {
      return;
    }
    select.classList.remove('att-none', 'att-present', 'att-absent', 'att-late');
    var value = (select.value || '').toLowerCase();
    if (value === 'present') {
      select.classList.add('att-present');
    } else if (value === 'absent') {
      select.classList.add('att-absent');
    } else if (value === 'late') {
      select.classList.add('att-late');
    } else {
      select.classList.add('att-none');
    }
  }

  function recomputeRowTotals(row) {
    if (!row) {
      return;
    }
    var totals = { p: 0, a: 0, l: 0 };
    var selects = row.querySelectorAll('.att-select');
    for (var i = 0; i < selects.length; i++) {
      var value = selects[i].value;
      if (value === 'present') {
        totals.p++;
      } else if (value === 'absent') {
        totals.a++;
      } else if (value === 'late') {
        totals.l++;
      }
    }
    var cells = row.querySelectorAll('td');
    var len = cells.length;
    if (len >= 3) {
      cells[len - 3].innerHTML = '<strong>' + totals.p + '</strong>';
      cells[len - 2].innerHTML = '<strong>' + totals.a + '</strong>';
      cells[len - 1].innerHTML = '<strong>' + totals.l + '</strong>';
    }
  }

  function toFormData(obj) {
    var fd = new FormData();
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fd.append(key, obj[key]);
      }
    }
    return fd;
  }

  document.addEventListener('change', function(event) {
    var select = event.target;
    if (!select || !select.classList || !select.classList.contains('att-select')) {
      return;
    }
    if (!isCurrentYear) {
      event.preventDefault();
      if (window.showToast) showToast('Editing disabled for non-current year', false);
      return;
    }

    var payload = {};
    payload[csrfName] = csrfHash;
    payload.date = select.getAttribute('data-date') || '';
    payload.status = select.value || '';
    payload.user_id = select.getAttribute('data-user-id') || '';
    payload.semester = select.getAttribute('data-semester') || semesterDefault;
    payload.school_year = select.getAttribute('data-school-year') || schoolYearDefault;
    payload.role_name = select.getAttribute('data-role-name') || '';

    if (!payload.date || !payload.user_id || !payload.semester || !payload.school_year) {
      console.error('Missing required fields for save', payload);
      return;
    }

    select.disabled = true;

    fetch(saveUrl, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
        // Send CSRF in headers as well to satisfy strict CSRF setups
        'X-CSRF-TOKEN': csrfHash,
        'X-CSRF-Token': csrfHash
      },
      body: toFormData(payload),
      credentials: 'same-origin'
    })
      .then(function(response) {
        return response.json().catch(function() {
          return {};
        }).then(function(data) {
          return { ok: response.ok, data: data };
        });
      })
      .then(function(result) {
        if (!result) {
          throw new Error('Invalid response');
        }

        var data = result.data || {};

        if (data.csrf_token && data.csrf_hash) {
          csrfName = data.csrf_token;
          csrfHash = data.csrf_hash;
        } else {
          // Fallback: try refresh from cookie if server rotated token
          try {
            var c = document.cookie.split(';').map(function(v){return v.trim();}).find(function(v){
              return v.indexOf('<?= esc(config('Security')->csrfCookieName ?? (config('Security')->cookieName ?? 'csrf_cookie_name')) ?>=')===0;
            });
            if (c) {
              csrfHash = decodeURIComponent(c.split('=')[1] || '');
            }
          } catch (_) {}
        }

        if (!result.ok || data.ok === false) {
          console.error('Save failed', data);
          if (window.showToast) showToast('Save failed', false);
          return;
        }

        applyAppearance(select);
        recomputeRowTotals(select.closest('tr'));
        if (window.showToast) showToast('Saved');
      })
      .catch(function(error) {
        console.error('Network/save error', error);
        if (window.showToast) showToast('Network error while saving', false);
      })
      .finally(function() {
        select.disabled = false;
      });
  });
});
</script>
<?= $this->endSection() ?>
