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

<div class="container-fluid">
  <div class="wrapper">
    <div class="content mb-3"></div>
    <h2 class="text-center mt-4 mb-3">Attendance Management</h2>
    <?= $this->include('partials/academic_filter') ?>

    <?= $this->section('styles') ?>
    <style>
      /* Use standard thead; do not hide DataTables' internal headers */

      /* Keep table header titles on a single line for alignment and ensure they layer above cells */
      .attendance-table thead th { white-space: nowrap; z-index: 6 !important; }
      .attendance-table thead th.school-id-col { z-index: 7 !important; }
      .attendance-table thead th.student-name-col { z-index: 6 !important; }
      /* Also apply nowrap to DataTables cloned headers */
      div.dataTables_wrapper .dataTables_scrollHead table thead th,
      table.fixedHeader-floating thead th { white-space: nowrap !important; }
      /* Student Name column respects the longest content */
      /* Student Name column */
      .attendance-table th.student-name-col { 
        white-space: nowrap;
        min-width: var(--name-min-ch, 12ch);
        text-align: left;
      }
      .attendance-table td.student-name-col {
        white-space: nowrap;
        min-width: var(--name-min-ch, 12ch);
        max-width: var(--name-min-ch, 12ch);
        overflow: hidden;
        text-overflow: ellipsis;
      }
      /* School ID column sized to fit content */
      /* School ID column */
      .attendance-table th.school-id-col {
        white-space: nowrap;
        min-width: var(--id-min-ch, 9ch);
        text-align: left;
      }
      .attendance-table td.school-id-col {
        white-space: nowrap;
        min-width: var(--id-min-ch, 9ch);
        max-width: var(--id-min-ch, 9ch);
        text-align: left;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      /* Date columns: uniform width and nowrap */
      .attendance-table th.date-col,
      .attendance-table td.date-col {
        white-space: nowrap;
        min-width: 160px;
        vertical-align: middle;
      }

      /* Make the first two columns sticky so names stay visible while scrolling */
      .attendance-table th.school-id-col,
      .attendance-table td.school-id-col {
        position: sticky;
        left: 0;
        z-index: 4; /* above other cells; below modals */
        background: #fff;
      }
      .attendance-table thead th.school-id-col { background: var(--mgmt-thead-bg, #f8f9fa) !important; }

      /* Keep Student Name non-sticky to avoid header misalignment on some laptops */
      .attendance-table th.student-name-col,
      .attendance-table td.student-name-col {
        position: static !important;
        left: auto !important;
        z-index: auto;
        background: transparent;
        box-shadow: none;
      }
      .attendance-table thead th.student-name-col { background: var(--mgmt-thead-bg, #f8f9fa) !important; }
      /* visual separation for sticky boundary of the first column */
      .attendance-table th.school-id-col, .attendance-table td.school-id-col { box-shadow: 1px 0 0 rgba(0,0,0,0.06) inset; }

      /* Compact the selects and badges so more fits on laptop screens */
      .attendance-table select.day-select.form-select-sm { font-size: 0.85rem; padding: .2rem .35rem; }
      .attendance-table .attendance-badge { font-size: .72rem; vertical-align: middle; }

      /* Reduce overall padding in content area on this page only */
      .wrapper .content { padding-left: 12px; padding-right: 12px; }

      /* Nav tabs wrap into multiple rows if needed */
      #attendanceTabs.nav-tabs { flex-wrap: wrap; row-gap: .25rem; }

      /* Responsiveness: tighten date column min-widths on narrower screens */
      @media (max-width: 1600px) {
        .attendance-table th.date-col,
        .attendance-table td.date-col { min-width: 140px; }
      }
      @media (max-width: 1440px) {
        .attendance-table th.date-col,
        .attendance-table td.date-col { min-width: 120px; }
      }
      @media (max-width: 1280px) {
        .attendance-table th.date-col,
        .attendance-table td.date-col { min-width: 110px; }
        .attendance-table select.day-select.form-select-sm { font-size: 0.8rem; padding: .18rem .3rem; }
      }
      @media (max-width: 1180px) {
        .attendance-table th.date-col,
        .attendance-table td.date-col { min-width: 100px; }
        .attendance-table .attendance-badge { display: none; }
      }
      /* Ensure horizontal scrolling always available */
      .table-responsive { overflow-x: auto; }

      /* Date navigator: mimic dynamic navbar round arrow */
      .date-nav-wrap { width: 100%; }
      .mgmt-round-arrow {
        width: 34px;
        height: 34px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border: none;
        border-radius: 9999px;
        background-color: var(--mgmt-primary);
        color: #fff;
        box-shadow: 0 2px 6px rgba(0,0,0,0.25);
        transition: background-color .2s ease, opacity .2s ease;
      }
      .mgmt-round-arrow:hover { background-color: var(--mgmt-primary-hover); }
      .mgmt-round-arrow:disabled { opacity: .5; cursor: not-allowed; }
      .date-range-label { min-width: 180px; text-align: center; color: var(--mgmt-muted); }
      .attendance-status-light {
        width: 12px;
        height: 12px;
        margin-right: .35rem;
        border-radius: 50%;
        border: 1px solid rgba(0, 0, 0, .25);
        display: inline-block;
        vertical-align: text-bottom;
      }
      .attendance-status-light.done {
        background-color: #198754;
        box-shadow: inset 0 0 0 1px rgba(25, 135, 84, .35);
      }
      .attendance-status-light.pending {
        background-color: #dc3545;
        box-shadow: inset 0 0 0 1px rgba(220, 53, 69, .35);
      }
    </style>
    <?= $this->endSection() ?>

    <!-- ===================== Global Student Search ===================== -->
    <div class="row g-2 justify-content-center mb-3">
      <div class="col-12 col-md-8 col-lg-6">
        <div class="input-group">
          <span class="input-group-text">Search Student</span>
          <input id="globalStudentSearch"
            class="form-control"
            type="text"
            placeholder="Type School ID or Student Name"
            list="studentSuggestions"
            autocomplete="off" />
          <!--button id="globalStudentSearchBtn" class="btn btn-primary" type="button">Find</button-->
          <button id="globalStudentSearchClear" class="btn btn-outline-secondary" type="button" title="Clear search">Clear</button>
        </div>
        <small class="text-muted">Searches all grades.</small>
      </div>
    </div>
    <?php
      $analysisUrl = site_url('administrator/daily_attendance/analysis');
      $queryParts = [];
      if (!empty($semester)) $queryParts[] = 'semester=' . urlencode((string)$semester);
      if (!empty($schoolYear)) $queryParts[] = 'school_year=' . urlencode((string)$schoolYear);
      if ($queryParts) $analysisUrl .= '?' . implode('&', $queryParts);
    ?>
    <div class="row justify-content-center mb-3">
      <div class="col-auto">
        <a class="btn btn-outline-primary" href="<?= esc($analysisUrl) ?>">
          Attendance Analysis
        </a>
      </div>
    </div>

    <?php
      // Exclude unwanted grade buckets globally (e.g., legacy Grade 10/11) unless the bucket is the Arabic program.
      $hiddenGrades = [10, 11];
      $hasArabic = static function (array $sections): bool {
        foreach ($sections as $section) {
          $name = strtolower((string)($section['class_section_name'] ?? ''));
          $code = strtolower((string)($section['class_section_id'] ?? ''));
          if (strpos($name, 'arabic') !== false || strpos($code, 'arabic') !== false) {
            return true;
          }
        }
        return false;
      };
      foreach ($hiddenGrades as $hid) {
        if (isset($grades[$hid]) && $hasArabic($grades[$hid])) {
          continue; // keep Arabic sections even if the class_id matches a hidden grade bucket
        }
        unset($grades[$hid]);
      }

      // Prune out sections with no students (extra safety so empty Arabic-2/3 never render)
      $filteredGrades = [];
      foreach ($grades as $cid => $sections) {
        $kept = [];
        foreach ($sections as $section) {
          $secKey = (string)($section['class_section_id'] ?? ($section['id'] ?? ''));
          if ($secKey !== '' && !empty($studentsBySection[$secKey])) {
            $kept[] = $section;
          }
        }
        if (!empty($kept)) {
          $filteredGrades[$cid] = $kept;
        }
      }
      $grades = $filteredGrades;
    ?>

    <datalist id="studentSuggestions">
      <?php
      // Output a single suggestion per student in the form: "SCHOOLID - First Last"
      // Use a set to prevent duplicates across sections/loops.
      $seen = [];

      foreach ($grades as $classId => $sections) {
        foreach ($sections as $section) {
          $secId = $section['class_section_id'] ?? null;
          if (!$secId || empty($studentsBySection[$secId])) continue;

          foreach ($studentsBySection[$secId] as $stu) {
            $sid   = (int)($stu['id'] ?? 0);
            $scid  = trim((string)($stu['school_id'] ?? ''));
            $fname = trim((string)($stu['firstname'] ?? ''));
            $lname = trim((string)($stu['lastname'] ?? ''));

            if (!$sid || $scid === '' || $fname === '' || $lname === '') continue;

            // De-dup by either student DB id or school_id
            if (isset($seen[$sid]) || isset($seen[$scid])) continue;
            $seen[$sid]  = true;
            $seen[$scid] = true;

            $className = (string)($section['class_section_name'] ?? '');
            $suffix    = $className !== '' ? (' (' . $className . ')') : '';
            $label     = $scid . ' - ' . $fname . ' ' . $lname . $suffix; // ASCII hyphen, then class section in parentheses
            echo '<option value="' . esc($label) . '"></option>';
          }
        }
      }
      ?>
    </datalist>


    <?php
    // =====================================================================
    // Helpers & Utilities
    // =====================================================================

    // ---- Build labels and a stable order: KG -> Grade 1..12 -> Youth ----
    $labelsByClassId   = [];
    $gradeNumberById   = [];
    $kgIds             = [];
    $arabicIds         = [];
    $youthIds          = [];

    foreach ($grades as $classId => $sections) {
      $cid = (int)$classId;
      $sampleName = '';
      $isArabicProgram = false;
      foreach ($sections as $s) {
        $sampleName = (string)($s['class_section_name'] ?? '');
        $lowName    = strtolower($sampleName);
        $lowCode    = strtolower((string)($s['class_section_id'] ?? ''));
        if (strpos($lowName, 'arabic') !== false || strpos($lowCode, 'arabic') !== false) {
          $isArabicProgram = true;
        }
        if ($sampleName !== '') break;
      }

      if ($isArabicProgram || $cid === 14) {
        // Arabic program: tab label is "Arabic" (sections show their own names e.g., Arabic-1)
        $labelsByClassId[$cid] = 'Arabic';
        $arabicIds[] = $cid;
      } elseif (preg_match('/\bKG\b/i', $sampleName)) {
        $labelsByClassId[$cid] = 'KG';
        $kgIds[] = $cid;
      } elseif (preg_match('/\bYouth\b/i', $sampleName)) {
        $labelsByClassId[$cid] = 'Youth';
        $youthIds[] = $cid;
      } elseif (preg_match('/Grade\s*(\d+)/i', $sampleName, $m)) {
        $labelsByClassId[$cid] = 'Grade ' . (int)$m[1];
        $gradeNumberById[$cid] = (int)$m[1];
      } else {
        if ($cid === 0) {
          $labelsByClassId[$cid] = 'KG';
          $kgIds[] = $cid;
        } elseif ($cid === 13) {
          $labelsByClassId[$cid] = 'Youth';
          $youthIds[] = $cid;
        } else {
          $labelsByClassId[$cid] = 'Grade ' . $cid;
          $gradeNumberById[$cid] = $cid;
        }
      }
    }

    $sortedClassIds = [];
    if ($kgIds) {
      sort($kgIds, SORT_NUMERIC);
      $sortedClassIds = array_merge($sortedClassIds, $kgIds);
    }
    if ($gradeNumberById) {
      asort($gradeNumberById, SORT_NUMERIC);
      $sortedClassIds = array_merge($sortedClassIds, array_keys($gradeNumberById));
    }
    if ($youthIds) {
      sort($youthIds, SORT_NUMERIC);
      $sortedClassIds = array_merge($sortedClassIds, $youthIds);
    }
    // Keep Arabic after Youth (if present) and before any unknown leftovers
    if ($arabicIds) {
      sort($arabicIds, SORT_NUMERIC);
      $sortedClassIds = array_merge($sortedClassIds, $arabicIds);
    }
    // Append any remaining class IDs (e.g., Arabic class) that didn’t fit standard buckets
    $presentIds = array_map('intval', array_keys($grades));
    $missingIds = array_values(array_diff($presentIds, $sortedClassIds));
    if (!empty($missingIds)) {
      $sortedClassIds = array_merge($sortedClassIds, $missingIds);
    }

    $labelFor = function (int $id) use ($labelsByClassId): string {
      return $labelsByClassId[$id] ?? ('Class ' . $id);
    };
    $slugFor  = function (int $id) use ($labelsByClassId, $gradeNumberById, $arabicIds): string {
      $lbl = $labelsByClassId[$id] ?? '';
      if ($lbl === 'KG') return 'kg';
      if ($lbl === 'Youth') return 'youth';
      if (in_array($id, $arabicIds, true) || strcasecmp($lbl, 'Arabic') === 0) return 'arabic';
      $n = $gradeNumberById[$id] ?? null;
      return $n !== null ? 'g' . $n : (string)$id;
    };

    // Distinct student counts per classId for tab badges
    $studentsCountByClassId = [];
    foreach ($grades as $classId => $sections) {
      $cid = (int)$classId;
      $uniq = [];
      foreach ($sections as $section) {
        $secId = $section['class_section_id'] ?? null;
        if ($secId && !empty($studentsBySection[$secId])) {
          foreach ($studentsBySection[$secId] as $stu) {
            if (!empty($stu['id'])) $uniq[(int)$stu['id']] = true;
          }
        }
      }
      $studentsCountByClassId[$cid] = count($uniq);
    }

    // Default active tab = first in sorted order (can still be overridden by ?class_id)
    $defaultId = $sortedClassIds[0] ?? null;

    // =====================================================================
    // NEW UTILITIES (dates pivot logic) — includes "today if Sunday, else next Sunday" column
    // =====================================================================
    $__datesBySection = (isset($datesBySection) && is_array($datesBySection)) ? $datesBySection : [];
    $__dateList       = (isset($dateList) && is_array($dateList)) ? array_values(array_filter(array_map('strval', $dateList))) : [];
    $__attendanceData = (isset($attendanceData) && is_array($attendanceData)) ? $attendanceData : [];
    $__noSchoolDays   = (isset($noSchoolDays) && is_array($noSchoolDays)) ? $noSchoolDays : [];

    try {
      $tzName = (string) (config('School')->attendance['timezone'] ?? user_timezone());
      $tzObj  = new DateTimeZone($tzName ?: 'UTC');
    } catch (\Throwable $e) {
      try {
        $tzObj = new DateTimeZone(user_timezone() ?: 'UTC');
      } catch (\Throwable $e2) {
        $tzObj = new DateTimeZone('UTC');
      }
    }

    try {
      $__nowDate = new DateTime('now', $tzObj);
    } catch (\Throwable $e) {
      $__nowDate = new DateTime('now');
    }

    $weekday = (int) $__nowDate->format('w');
    if ($weekday === 0) {
      $__anchorSunday = $__nowDate->format('Y-m-d');
    } else {
      $__anchorSunday = (clone $__nowDate)->modify('next sunday')->format('Y-m-d');
    }

    $buildDateCols = function ($sectionId) use ($__datesBySection, $__dateList, $__attendanceData, $__anchorSunday, $__nowDate, $__noSchoolDays) {
      $filterDates = function (array $items) use ($__noSchoolDays) {
        $map = [];
        foreach ($items as $item) {
          $d = (string)$item;
          if ($d === '' || !empty($__noSchoolDays[$d])) {
            continue;
          }
          $map[$d] = $d;
        }
        return array_values($map);
      };

      $candidates = [];
      if (!empty($__datesBySection[$sectionId]) && is_array($__datesBySection[$sectionId])) {
        $candidates = array_merge($candidates, $__datesBySection[$sectionId]);
      }
      if (!empty($__dateList) && is_array($__dateList)) {
        $candidates = array_merge($candidates, $__dateList);
      }

      $cols = $filterDates($candidates);
      if (!$cols && !empty($__attendanceData[$sectionId]) && is_array($__attendanceData[$sectionId])) {
        $set = [];
        foreach ($__attendanceData[$sectionId] as $sid => $entries) {
          if (!is_array($entries)) continue;
          foreach ($entries as $e) {
            $d = (string)($e['date'] ?? '');
            if ($d !== '') $set[$d] = $d;
          }
        }
        $cols = $filterDates(array_keys($set));
      }

      if (!$cols) {
        $nowRef = clone $__nowDate;
        $fallback = [
          (clone $nowRef)->modify('-7 days')->format('Y-m-d'),
          $nowRef->format('Y-m-d'),
        ];
        $cols = $filterDates($fallback);
      }

      if ($cols) {
        sort($cols, SORT_STRING);
      }

      if (!empty($__anchorSunday) && empty($__noSchoolDays[$__anchorSunday]) && !in_array($__anchorSunday, $cols, true)) {
        $cols[] = $__anchorSunday;
        sort($cols, SORT_STRING);
      }
      return $cols;
    };

    $formatDateLabel = function ($ymd) {
      $ymd = (string)$ymd;
      if ($ymd === '') return '';
      if (preg_match('/^(\\d{4})-(\\d{2})-(\\d{2})$/', $ymd, $m)) {
        return $m[2] . '-' . $m[3] . '-' . $m[1];
      }
      try {
        return local_date($ymd, 'm-d-Y');
      } catch (\Throwable $e) {
        return $ymd;
      }
    };

    $todayDate = $__nowDate->format('Y-m-d');
    $todayLabel = $todayDate ? $formatDateLabel($todayDate) : '';

    // Build {date => {status, is_reported}}
    $recAt = function (array $entries) {
      $map = [];
      foreach ($entries as $e) {
        $d = (string)($e['date'] ?? '');
        if ($d !== '') {
          $map[$d] = [
            'status'      => (string)($e['status'] ?? ''),
            'is_reported' => (string)($e['is_reported'] ?? 'no'),
          ];
        }
      }
      return $map;
    };

    // Dropdown options + badge meta (first is placeholder)
    $optionDefs = [
      'none'       => ['label' => 'Select attendance',    'status' => '',        'is_reported' => '',  'badge' => 'secondary',            'short' => '—'],
      'present'    => ['label' => 'Present',              'status' => 'present', 'is_reported' => 'no', 'badge' => 'success',              'short' => 'P'],
      'late_yes'   => ['label' => 'Late — Reported',      'status' => 'late',    'is_reported' => 'yes', 'badge' => 'warning text-dark',    'short' => 'LR'],
      'late_no'    => ['label' => 'Late — Not-reported',  'status' => 'late',    'is_reported' => 'no', 'badge' => 'warning text-dark',    'short' => 'LnR'],
      'absent_yes' => ['label' => 'Absent — Reported',    'status' => 'absent',  'is_reported' => 'yes', 'badge' => 'danger',               'short' => 'AR'],
      'absent_no'  => ['label' => 'Absent — Not-reported', 'status' => 'absent',  'is_reported' => 'no', 'badge' => 'danger',               'short' => 'AnR'],
    ];
    ?>

    <?php
      $anchorSunday = $__anchorSunday ?? '';
      $anchorSundayLabel = $anchorSunday ? $formatDateLabel($anchorSunday) : '';
      $sectionHasCompleteAttendance = function (string $sectionKey, string $targetDate) use ($__attendanceData, $studentsBySection): bool {
        if ($targetDate === '') {
          return false;
        }
        $sectionStudents = $studentsBySection[$sectionKey] ?? [];
        if (empty($sectionStudents)) {
          return false;
        }
        $entriesByStudent = $__attendanceData[$sectionKey] ?? [];
        foreach ($sectionStudents as $student) {
          $studentId = (int)($student['id'] ?? 0);
          if ($studentId <= 0) {
            return false;
          }
          $found = false;
          $entries = $entriesByStudent[$studentId] ?? [];
          if (is_array($entries)) {
            foreach ($entries as $entry) {
              if ((string)($entry['date'] ?? '') === $targetDate) {
                $found = true;
                break;
              }
            }
          }
          if (!$found) {
            return false;
          }
        }
        return true;
      };
      $classHasCompleteAttendance = function (array $sections, string $targetDate) use ($sectionHasCompleteAttendance): bool {
        if ($targetDate === '' || empty($sections)) {
          return false;
        }
        foreach ($sections as $section) {
          $secKey = (string)($section['class_section_id'] ?? ($section['id'] ?? ''));
          if ($secKey === '') {
            continue;
          }
          if (!$sectionHasCompleteAttendance($secKey, $targetDate)) {
            return false;
          }
        }
        return true;
      };
      $attendanceStatusByClass = [];
      $attendanceStatusDateByClass = [];
      foreach ($sortedClassIds as $cid) {
        $sections = $grades[$cid] ?? [];
        $statusDone = false;
        $statusDate = '';
        if ($todayDate !== '' && $classHasCompleteAttendance($sections, $todayDate)) {
          $statusDone = true;
          $statusDate = $todayDate;
        } elseif ($anchorSunday !== '' && $classHasCompleteAttendance($sections, $anchorSunday)) {
          $statusDone = true;
          $statusDate = $anchorSunday;
        }
        $attendanceStatusByClass[$cid] = $statusDone;
        $attendanceStatusDateByClass[$cid] = $statusDate;
      }
    ?>

    <!-- Tabs navigation -->
    <ul class="nav nav-tabs justify-content-center" id="attendanceTabs" role="tablist">
      <?php foreach ($sortedClassIds as $cid): ?>
        <?php
        $slug  = $slugFor($cid);
        $label = $labelFor($cid);
        $cnt   = (int)($studentsCountByClassId[$cid] ?? 0);
        $statusDone = !empty($attendanceStatusByClass[$cid]);
        $statusDate = $attendanceStatusDateByClass[$cid] ?? '';
        if ($statusDate !== '') {
          $statusLabel = $formatDateLabel($statusDate);
        } elseif ($anchorSundayLabel !== '') {
          $statusLabel = $anchorSundayLabel;
        } elseif ($todayLabel !== '') {
          $statusLabel = $todayLabel;
        } else {
          $statusLabel = '';
        }
        $statusTitle = $statusLabel
          ? ($statusDone ? 'Attendance recorded for ' : 'Attendance pending for ') . $statusLabel
          : ($statusDone ? 'Attendance recorded' : 'Attendance pending');
        ?>
        <li class="nav-item">
          <a class="nav-link <?= ($cid === $defaultId) ? 'active' : '' ?>"
            id="grade<?= esc($slug) ?>-tab"
            data-bs-toggle="tab"
            href="#grade<?= esc($slug) ?>"
            role="tab"
            aria-controls="grade<?= esc($slug) ?>"
            aria-selected="<?= ($cid === $defaultId) ? 'true' : 'false' ?>"
            data-class-id="<?= (int)$cid ?>">
            <span class="attendance-status-light <?= $statusDone ? 'done' : 'pending' ?>"
              title="<?= esc($statusTitle) ?>"
              aria-hidden="true"></span>
            <span class="visually-hidden"><?= esc($statusTitle) ?></span>
            <?= esc($label) ?>
            <span class="badge bg-secondary ms-1" title="Students in <?= esc($label) ?>"><?= $cnt ?></span>
          </a>
        </li>
      <?php endforeach; ?>
    </ul>

    <!-- Tabs content -->
    <div class="tab-content mt-3">
      <?php foreach ($sortedClassIds as $cid): ?>
        <?php
        $slug     = $slugFor($cid);
        $label    = $labelFor($cid);
        $sections = $grades[$cid] ?? [];
        ?>
        <div class="tab-pane fade <?= ($cid === $defaultId) ? 'show active' : '' ?>"
          id="grade<?= esc($slug) ?>"
          role="tabpanel"
          aria-labelledby="grade<?= esc($slug) ?>-tab">
          <?php /* Removed top-level grade header; show only per-section titles */ ?>

          <?php foreach ($sections as $section): ?>
            <?php
            $sectionKeyRaw = $section['class_section_id'] ?? ($section['id'] ?? '');
            $sectionKey = ($sectionKeyRaw !== '' && $sectionKeyRaw !== null) ? (string)$sectionKeyRaw : '';
            if ($sectionKey === '' || empty($studentsBySection[$sectionKey])) continue;
            $dateCols = $buildDateCols($sectionKey);
            // Prefer oldest incomplete attendance date for initial view
            $defaultDateYmd = '';
            if (!empty($dateCols)) {
              foreach ($dateCols as $d) {
                $d = (string)$d;
                if ($d !== '' && !$sectionHasCompleteAttendance($sectionKey, $d)) {
                  $defaultDateYmd = $d;
                  break;
                }
              }
              if ($defaultDateYmd === '') {
                $defaultDateYmd = (string)end($dateCols);
              }
              reset($dateCols);
            }
            $defaultDateLabel = $defaultDateYmd !== '' ? $formatDateLabel($defaultDateYmd) : '';
            // Compute longest student name length (characters) for this section
            $maxNameLen = 0;
            foreach ($studentsBySection[$sectionKey] as $s_) {
              $nm_ = trim(($s_['firstname'] ?? '') . ' ' . ($s_['lastname'] ?? ''));
              $len_ = function_exists('mb_strlen') ? mb_strlen($nm_, 'UTF-8') : strlen($nm_);
              if ($len_ > $maxNameLen) $maxNameLen = $len_;
            }
            $minNameCh = max(12, $maxNameLen + 2);
            // Compute longest school ID length (characters) for this section (ensure header fits: 9ch)
            $maxIdLen = 0;
            foreach ($studentsBySection[$sectionKey] as $s_) {
              $id_ = trim((string)($s_['school_id'] ?? ''));
              $len_ = function_exists('mb_strlen') ? mb_strlen($id_, 'UTF-8') : strlen($id_);
              if ($len_ > $maxIdLen) $maxIdLen = $len_;
            }
            $minIdCh = max(9, $maxIdLen);
            // Derive a human-friendly section label above the table
            $rawSecName = trim((string)($section['class_section_name'] ?? ''));
            // Base label from section name (fallback to tab label)
            $sectionLabel = ($rawSecName !== '') ? $rawSecName : $label;
            // Add "Grade " prefix unless already present, but NEVER for KG, Youth, or Arabic program
            if (preg_match('/^(KG(\b|-)|Youth(\b|-))/i', $sectionLabel)) {
              $headerText = $sectionLabel;
            } elseif (strcasecmp($label, 'Arabic') === 0 || stripos($sectionLabel, 'Arabic') === 0) {
              $headerText = $sectionLabel;
            } elseif (preg_match('/^\s*Grade\b/i', $sectionLabel)) {
              $headerText = $sectionLabel;
            } else {
              $headerText = 'Grade ' . $sectionLabel;
            }
            ?>
            <h4 class="mt-4 mb-2 text-center"><?= esc($headerText) ?></h4>
            <!-- Date navigation (shows 4 date columns at a time; arrows page left/right) -->
            <div class="date-nav-wrap d-flex justify-content-center align-items-center gap-2 mb-2" data-date-nav data-section-id="<?= esc($sectionKey) ?>">
              <button type="button" class="mgmt-round-arrow date-prev" title="Previous dates" aria-label="Previous dates">
                <i class="bi bi-chevron-left"></i>
              </button>
              <span class="px-2 small date-range-label">&nbsp;</span>
              <button type="button" class="mgmt-round-arrow date-next" title="Next dates" aria-label="Next dates">
                <i class="bi bi-chevron-right"></i>
              </button>
            </div>
            <div class="table-responsive">
              <table class="table table-bordered attendance-table attendance-grid w-100"
                data-section-id="<?= esc($sectionKey) ?>"
                data-default-date-label="<?= esc($defaultDateLabel) ?>">
                <thead>
                  <tr>
                    <th class="school-id-col" style="min-width: <?= (int)$minIdCh ?>ch;">School ID</th>
                    <th class="student-name-col" style="min-width: <?= (int)$minNameCh ?>ch;">Student Name</th>
                    <!-- (Class-Section hidden per request) -->
                    <?php foreach ($dateCols as $d): ?>
                      <?php $dLabel = $formatDateLabel($d); ?>
                      <th class="text-center date-col" style="min-width:160px;"><?= esc($dLabel) ?></th>
                    <?php endforeach; ?>
                    <th class="text-center">P</th>
                    <th class="text-center">L</th>
                    <th class="text-center">A</th>
                    <th class="text-center">T</th>
                  </tr>
                </thead>
                <tbody>
                  <?php
                    $uniqueStudents = [];
                    foreach ($studentsBySection[$sectionKey] as $student) {
                      $sid = (int)($student['id'] ?? 0);
                      if ($sid <= 0 || isset($uniqueStudents[$sid])) {
                        continue;
                      }
                      $uniqueStudents[$sid] = $student;
                    }
                  ?>
                  <?php foreach ($uniqueStudents as $student): ?>
                    <?php
                    $sid      = (int)$student['id'];
                    $entryMap = $recAt($__attendanceData[$sectionKey][$sid] ?? []);
                    
                    $summary = ($attendanceRecord[$sectionKey][$sid] ?? null);
                    $tPresent = $summary ? (int)($summary['total_presence'] ?? 0) : 0;
                    $tLate = $summary ? (int)($summary['total_late'] ?? 0) : 0;
                    $tAbsent = $summary ? (int)($summary['total_absence'] ?? 0) : 0;


                    $schoolId     = esc($student['school_id']);
                    $fullNameRaw  = trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? ''));
                    $fullName     = esc($fullNameRaw);
                    $fullNameAttr = esc(strtolower($fullNameRaw));
                    ?>
                    <tr
                      data-student-id="<?= (int)$sid ?>"
                      data-school-id="<?= $schoolId ?>"
                      data-student-name="<?= $fullNameAttr ?>"
                      data-student-name-display="<?= esc($fullNameRaw) ?>"
                      data-class-id="<?= (int)$cid ?>"
                      data-grade-label="<?= esc($headerText) ?>">
                      <td class="school-id-col" style="min-width: <?= (int)$minIdCh ?>ch;"><?= $schoolId ?></td>
                      <td class="student-name-col" style="min-width: <?= (int)$minNameCh ?>ch;">
                        <a
                          href="<?= site_url('family') . '?student_id=' . (int)$sid ?>"
                          class="text-decoration-none"
                          data-family-student-id="<?= (int)$sid ?>"
                          title="Open family card">
                          <?= $fullName ?>
                        </a>
                      </td>

                      <?php foreach ($dateCols as $dcol): ?>
                        <?php
                        $rec = $entryMap[$dcol] ?? null;
                        $val = 'none';
                        if ($rec) {
                          if ($rec['status'] === 'present')       $val = 'present';
                          elseif ($rec['status'] === 'late')      $val = ($rec['is_reported'] === 'yes') ? 'late_yes' : 'late_no';
                          elseif ($rec['status'] === 'absent')    $val = ($rec['is_reported'] === 'yes') ? 'absent_yes' : 'absent_no';
                        }
                        $isParentReport = $rec && (($rec['source'] ?? '') === 'parent_report');
                        $short     = $optionDefs[$val]['short'] ?? '—';
                        $badgePart = $optionDefs[$val]['badge'] ?? 'secondary'; // e.g. "warning text-dark"
                        $badgeFull = 'bg-' . $badgePart; // -> "bg-warning text-dark" or "bg-secondary"
                        $dLabel    = $formatDateLabel($dcol);
                        ?>
                        <td class="text-center date-col" style="min-width:160px;">
                          <select
                            class="form-select form-select-sm day-select"
                            data-class-id="<?= (int)$cid ?>"
                            data-class-section-id="<?= esc($sectionKey) ?>"
                            data-student-id="<?= (int)$sid ?>"
                            data-school-id="<?= esc($student['school_id']) ?>"
                            data-date="<?= esc($dcol) ?>"
                            aria-label="Attendance on <?= esc($dLabel) ?>">
                            <?php foreach ($optionDefs as $key => $def): ?>
                              <option value="<?= $key ?>" <?= $key === $val ? 'selected' : '' ?>>
                                <?= esc($def['label']) ?>
                              </option>
                            <?php endforeach; ?>
                          </select>
                          <span class="attendance-badge badge rounded-pill ms-1 <?= esc($badgeFull) ?>">
                            <?= esc($short) ?>
                          </span>
                          <?php if ($isParentReport): ?>
                            <div class="text-muted small mt-1">Parent report</div>
                          <?php endif; ?>
                        </td>
                      <?php endforeach; ?>

                      <td class="text-center total-present"><?= (int)$tPresent ?></td>
                      <td class="text-center total-late"><?= (int)$tLate ?></td>
                      <td class="text-center total-absent"><?= (int)$tAbsent ?></td>
                      <td class="text-center total-expected"><?= (int)($totalPassedDays ?? 0) ?></td>
                    </tr>
                  <?php endforeach; ?>
                </tbody>
              </table>
            </div>
          <?php endforeach; ?>
        </div>
      <?php endforeach; ?>
</div>
</div>
</div>

<!-- Late Slip Modal -->
<div class="modal fade" id="lateSlipModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Print Late Slip</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form id="lateSlipForm">
          <div class="row g-2">
            <div class="col-12">
              <label class="form-label">Student Name</label>
              <input type="text" class="form-control" name="student_name" readonly>
            </div>
            <div class="col-6">
              <label class="form-label">Date</label>
              <input type="text" class="form-control" name="date" readonly>
            </div>
            <div class="col-6">
              <label class="form-label">Time In</label>
              <input type="text" class="form-control" name="time_in" placeholder="hh:mm AM/PM">
            </div>
            <div class="col-12">
              <label class="form-label">Grade</label>
              <input type="text" class="form-control" name="grade" readonly>
            </div>
            <div class="col-12">
              <label class="form-label">Reason</label>
              <input type="text" class="form-control" name="reason" placeholder="Optional reason">
            </div>
            <div class="col-6">
              <label class="form-label">School Year</label>
              <input type="text" class="form-control" name="school_year" readonly>
            </div>
            <div class="col-6">
              <label class="form-label">Admin Name</label>
              <input type="text" class="form-control" name="admin_name" readonly>
            </div>
          </div>
        </form>
        <hr>
        <label class="form-label">Preview</label>
        <pre class="bg-light p-2" id="lateSlipPreview" style="white-space: pre-wrap; max-height: 240px; overflow:auto;">Loading...</pre>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary" id="lateSlipPrintBtn">Print Slip</button>
      </div>
    </div>
  </div>
  </div>

<?php
// ================== SAVE ENDPOINTS (route you said works) ==================
$savePath = 'attendance/update';
$attendanceSaveUrl       = '/' . $savePath;                 // same-origin relative URL
$attendanceSaveUrlIndex  = '/index.php/' . $savePath;       // index.php fallback (relative)
?>

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

<?= $this->section('scripts') ?>
<script>
  const ATTN_SAVE_URL = <?= json_encode($attendanceSaveUrl) ?>;
  const ATTN_SAVE_URL_INDEX = <?= json_encode($attendanceSaveUrlIndex) ?>;
  const SLIP_PREVIEW_URL = <?= json_encode('/slips/preview') ?>;
  const SLIP_PRINT_URL   = <?= json_encode('/slips/print') ?>;

  const TERM_SCHOOL_YEAR = <?= json_encode($schoolYear ?? '') ?>;
  const TERM_SEMESTER    = <?= json_encode($semester ?? '') ?>;
  <?php
    $___adminName = isset($currentAdminName) && $currentAdminName !== ''
      ? (string)$currentAdminName
      : trim((string)(session()->get('firstname') ?? '') . ' ' . (string)(session()->get('lastname') ?? ''));
  ?>
  const CURRENT_USER_NAME = <?= json_encode($___adminName) ?>;
</script>

<script>
  // ---- CSRF helpers (CI4) ----
  const CSRF_NAME        = <?= json_encode(csrf_token()) ?>;
  const CSRF_HEADER_NAME = <?= json_encode(csrf_header()) ?>;
  let CSRF_HASH          = <?= json_encode(csrf_hash()) ?>;

  function meta(name) {
    return document.querySelector(`meta[name="${name}"]`);
  }

  function getCsrfHeaderName() { return CSRF_HEADER_NAME || 'X-CSRF-TOKEN'; }

  function getCsrfFromMeta() { return ''; }

  function getCookie(n) {
    return document.cookie.split(';')
      .map(v => v.trim())
      .find(v => v.startsWith(n + '='))?.split('=')[1] || '';
  }

  // ✅ Use the right CI4 property for the CSRF cookie
  const CSRF_COOKIE_NAME = <?= json_encode(config('Security')->csrfCookieName ?? (config('Security')->cookieName ?? 'csrf_cookie_name')) ?>;

  function refreshCsrfFromPage() {
    // On first load meta has a fresh token; after any POST CI rotates and sets cookie
    const m = getCsrfFromMeta();
    if (m) {
      CSRF_HASH = m;
      return;
    }
    const c = decodeURIComponent(getCookie(CSRF_COOKIE_NAME));
    if (c) {
      CSRF_HASH = c;
    }
  }

  // --- URL-encoded posts (plays nicest with CI4) ---
  function toUrlEncoded(obj) {
    const p = new URLSearchParams();
    for (const [k, v] of Object.entries(obj)) p.append(k, v ?? '');
    // Always include CSRF field in body to satisfy strict CSRF setups
    if (CSRF_NAME && CSRF_HASH) {
      p.append(CSRF_NAME, CSRF_HASH);
    }
    return p;
  }

  // If the server sends a fresh token back in a header, capture it
  function captureCsrfFromResponse(res) {
    const hdrName = getCsrfHeaderName();
    const hdrVal = res.headers.get(hdrName);
    if (hdrVal) {
      CSRF_HASH = hdrVal;
      return;
    }
    // Fallback to cookie (token rotates after POST)
    const c = decodeURIComponent(getCookie(CSRF_COOKIE_NAME));
    if (c) CSRF_HASH = c;
  }

  async function doPost(url, bodyParams) {
    const res = await fetch(url, {
      method: 'POST',
      body: bodyParams,
      credentials: 'same-origin',
      headers: {
        'Accept': 'application/json, text/html, */*',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        [getCsrfHeaderName()]: CSRF_HASH,
        'X-Requested-With': 'XMLHttpRequest'
      }
    });
    const text = await res.text();
    let data = null;
    try {
      data = JSON.parse(text);
    } catch {}
    // ✅ Pick up new token (header first, then cookie, then JSON)
    if (data?.csrfHash) {
      CSRF_HASH = data.csrfHash;
    } else {
      captureCsrfFromResponse(res);
    }
    return {
      res,
      text,
      data
    };
  }

  // -------- Late slip helpers --------
  function formatDateMDY(iso) {
    if (!iso) return '';
    const d = new Date(iso + 'T00:00:00');
    if (isNaN(d.getTime())) return iso;
    const mm = (d.getMonth() + 1).toString().padStart(2, '0');
    const dd = d.getDate().toString().padStart(2, '0');
    const yyyy = d.getFullYear();
    return `${mm}-${dd}-${yyyy}`;
  }

  function currentTime12h(now = new Date()) {
    let h = now.getHours();
    const m = now.getMinutes();
    const ampm = h >= 12 ? 'PM' : 'AM';
    h = h % 12;
    if (h === 0) h = 12;
    return `${h.toString().padStart(1,'0')}:${m.toString().padStart(2,'0')} ${ampm}`;
  }

  function readSlipForm() {
    const f = document.getElementById('lateSlipForm');
    return {
      student_name: f.student_name.value || '',
      date:         f.date.value || '',
      time_in:      f.time_in.value || '',
      grade:        f.grade.value || '',
      reason:       f.reason.value || '',
      school_year:  f.school_year.value || TERM_SCHOOL_YEAR || '',
      admin_name:   f.admin_name.value || CURRENT_USER_NAME || ''
    };
  }

  async function refreshLateSlipPreview() {
    const vals = readSlipForm();
    const pre = document.getElementById('lateSlipPreview');
    pre.textContent = 'Loading...';
    try {
      const { res, data, text } = await doPost(SLIP_PREVIEW_URL, toUrlEncoded(vals));
      if (!res.ok || !data?.ok) {
        pre.textContent = `Preview failed (HTTP ${res.status}).\n` + (data?.error || text || '');
        return;
      }
      pre.textContent = data.text || '(Empty preview)';
    } catch (e) {
      pre.textContent = 'Preview error: ' + (e?.message || 'network');
    }
  }

  // Auto-update preview when the user types reason (and time)
  let __lateSlipPreviewDebounce;
  function scheduleLateSlipPreview() {
    if (__lateSlipPreviewDebounce) clearTimeout(__lateSlipPreviewDebounce);
    __lateSlipPreviewDebounce = setTimeout(refreshLateSlipPreview, 250);
  }

  let __lateSlipAutoHooked = false;
  function ensureLateSlipAutoPreview() {
    if (__lateSlipAutoHooked) return;
    const f = document.getElementById('lateSlipForm');
    if (!f) return;
    __lateSlipAutoHooked = true;
    f.addEventListener('input', function(e){
      const name = e.target && e.target.name;
      if (name === 'reason' || name === 'time_in') scheduleLateSlipPreview();
    });
    f.addEventListener('change', function(e){
      const name = e.target && e.target.name;
      if (name === 'reason' || name === 'time_in') scheduleLateSlipPreview();
    });
  }

  let __lateSlipModal;
  function openLateSlipModal(initVals) {
    const f = document.getElementById('lateSlipForm');
    f.student_name.value = initVals.student_name || '';
    f.date.value         = initVals.date || '';
    f.time_in.value      = initVals.time_in || currentTime12h();
    f.grade.value        = initVals.grade || '';
    f.reason.value       = initVals.reason || '';
    f.school_year.value  = initVals.school_year || TERM_SCHOOL_YEAR || '';
    f.admin_name.value   = initVals.admin_name || CURRENT_USER_NAME || '';

    if (!__lateSlipModal) {
      __lateSlipModal = new bootstrap.Modal(document.getElementById('lateSlipModal'));
    }
    __lateSlipModal.show();
    // Load preview after opening
    setTimeout(refreshLateSlipPreview, 50);
    // Hook auto-preview on input
    ensureLateSlipAutoPreview();
  }

  async function printLateSlip() {
    // Open a new tab that streams a PDF built from the form values
    const vals = readSlipForm();
    const p = new URLSearchParams(vals);
    // Use credit-card width; height is dynamic based on content
    p.set('paper', 'card');
    const url = SLIP_PRINT_URL + '?' + p.toString();
    window.open(url, '_blank', 'noopener');
    __lateSlipModal?.hide();
  }

  // Dropdown value → {status, is_reported}
  const OPTION_TO_PAYLOAD = {
    'none': {
      status: '',
      is_reported: ''
    },
    'present': {
      status: 'present',
      is_reported: 'no'
    },
    'late_yes': {
      status: 'late',
      is_reported: 'yes'
    },
    'late_no': {
      status: 'late',
      is_reported: 'no'
    },
    'absent_yes': {
      status: 'absent',
      is_reported: 'yes'
    },
    'absent_no': {
      status: 'absent',
      is_reported: 'no'
    },
  };

  async function postAttendanceChange(selEl) {
    const v = selEl.value;
    if (v === 'none') return {
      ok: true,
      skipped: true
    };

    const def = OPTION_TO_PAYLOAD[v] || OPTION_TO_PAYLOAD.present;

    // ✅ make sure we ALWAYS have class_id; clear error if missing
    const tr = selEl.closest('tr');
    const tabActive = document.querySelector('.nav-link.active');
    const classId =
      selEl.dataset.classId ||
      (tr && tr.dataset.classId) ||
      (tabActive && tabActive.getAttribute('data-class-id')) ||
      '';

    if (!classId) {
      return {
        ok: false,
        message: 'Missing class_id in dataset — cannot save attendance.'
      };
    }

    // required dataset fields
    const payload = {
      [CSRF_NAME]: CSRF_HASH,
      ajax: '1',
      class_id: classId,
      class_section_id: selEl.dataset.classSectionId || '',
      student_id: selEl.dataset.studentId || '',
      school_id: selEl.dataset.schoolId || '',
      date: selEl.dataset.date || '',
      semester: TERM_SEMESTER || '',
      school_year: TERM_SCHOOL_YEAR || '',
      status: def.status,
      is_reported: def.is_reported,
      reason: (def.status === 'late' || def.status === 'absent') ? '—' : ''
    };
    if (!payload.student_id || !payload.class_section_id || !payload.date) {
      return {
        ok: false,
        message: 'Missing student_id / class_section_id / date.'
      };
    }

    refreshCsrfFromPage();
    const body = toUrlEncoded(payload);

    try {
      selEl.disabled = true;

      // Try pretty URL then index.php fallback
      let {
        res,
        text,
        data
      } = await doPost(ATTN_SAVE_URL, body);
      if ((res.status === 404 || res.status === 405) && ATTN_SAVE_URL_INDEX !== ATTN_SAVE_URL) {
        ({
          res,
          text,
          data
        } = await doPost(ATTN_SAVE_URL_INDEX, body));
      }

      if (res.ok) return {
        ok: true
      };

      const msg = (data && data.message) ? data.message : `HTTP ${res.status}\n` + text.slice(0, 1200);
      return {
        ok: false,
        message: msg
      };

    } catch (e) {
      return {
        ok: false,
        message: e?.message || 'Network error'
      };
    } finally {
      selEl.disabled = false;
    }
  }

  function recomputeRowTotals(tr) {
    let p = 0,
      l = 0,
      a = 0;
    tr.querySelectorAll('select.day-select').forEach(sel => {
      const v = sel.value;
      if (v === 'present') p++;
      else if (v.startsWith('late_')) l++;
      else if (v.startsWith('absent_')) a++;
    });
    tr.querySelector('.total-present')?.replaceChildren(document.createTextNode(p));
    tr.querySelector('.total-late')?.replaceChildren(document.createTextNode(l));
    tr.querySelector('.total-absent')?.replaceChildren(document.createTextNode(a));
  }

  const OPTION_META = {
    'none': {
      badge: 'bg-secondary',
      short: '—'
    },
    'present': {
      badge: 'bg-success',
      short: 'P'
    },
    'late_yes': {
      badge: 'bg-warning text-dark',
      short: 'LR'
    },
    'late_no': {
      badge: 'bg-warning text-dark',
      short: 'LnR'
    },
    'absent_yes': {
      badge: 'bg-danger',
      short: 'AR'
    },
    'absent_no': {
      badge: 'bg-danger',
      short: 'AnR'
    }
  };

  function updateCellBadge(selectEl) {
    const meta = OPTION_META[selectEl.value] || OPTION_META.none;
    const badge = selectEl.parentElement.querySelector('.attendance-badge');
    if (!badge) return;
    badge.className = 'attendance-badge badge rounded-pill ms-1 ' + meta.badge;
    badge.textContent = meta.short;
  }

  document.addEventListener('change', async (e) => {
    const sel = e.target.closest('select.day-select');
    if (!sel) return;

    const tr = sel.closest('tr');
    const prev = sel.getAttribute('data-prev') || sel.value;
    sel.setAttribute('data-prev', sel.value);

    updateCellBadge(sel);
    recomputeRowTotals(tr);

    const result = await postAttendanceChange(sel);
    if (!result.ok && !result.skipped) {
      sel.value = prev;
      updateCellBadge(sel);
      recomputeRowTotals(tr);
      alert('Failed to save attendance.\n\n' + (result.message || 'Check Network tab for details.'));
      console.error('Save error details:', result.message);
      return;
    }

    // After a successful save, if marked as LATE, prompt to print a slip
    if (sel.value && sel.value.startsWith('late_')) {
      try {
        const isoDate = sel.getAttribute('data-date') || '';
        const row = sel.closest('tr');
        const nameDisp = (row?.getAttribute('data-student-name-display') || '').trim();
        const linkName = row?.querySelector('td:nth-child(2) a')?.textContent?.trim() || '';
        const studentName = nameDisp || linkName || '';
        const gradeLabel = (row?.getAttribute('data-grade-label') || '').trim();
        const initVals = {
          student_name: studentName,
          date: formatDateMDY(isoDate),
          time_in: currentTime12h(),
          grade: gradeLabel,
          reason: '',
          school_year: TERM_SCHOOL_YEAR,
          admin_name: CURRENT_USER_NAME,
        };
        openLateSlipModal(initVals);
      } catch (err) {
        console.warn('Failed to open slip modal:', err);
      }
    }
  });

  // Modal buttons
document.getElementById('lateSlipPrintBtn')?.addEventListener('click', printLateSlip);
</script>

<script>
  // ================== Global Search (sticky highlight) ==================
  let __tableApis = [];
  let __studentIndex = [];
  let __currentStickyRow = null;
  const __anchorSunday = <?= json_encode($__anchorSunday ?? '') ?>;

  function normalizeQuery(q) {
    return (q || '').toString().trim().toLowerCase().replace(/\s+/g, ' ');
  }
  function extractSchoolIdFromQuery(q) {
    const m = (q || '').match(/^\s*(\S+)\s*(?:—|-)?/);
    return m ? m[1] : '';
  }
  function activateTabById(tabId) {
    const link = document.querySelector(`a.nav-link[href="#${tabId}"]`);
    if (link) new bootstrap.Tab(link).show();
    return !!link;
  }
  function revealRowInDataTable(tableApi, tr) {
    try {
      const $rows = tableApi.rows({ search: 'none' }).nodes().to$();
      const idx = $rows.index(tr);
      if (idx >= 0) {
        const pageLen = tableApi.page.len();
        const targetPage = Math.floor(idx / pageLen);
        tableApi.page(targetPage).draw(false);
        tr.classList.add('row-sticky-highlight', 'row-highlight');
        void tr.offsetWidth;
        setTimeout(() => tr.classList.remove('row-highlight'), 1200);
        setTimeout(() => tr.scrollIntoView({ behavior: 'smooth', block: 'center' }), 80);
      }
    } catch (e) { console.warn(e); }
  }
  function clearStickyHighlight() {
    if (__currentStickyRow) {
      __currentStickyRow.classList.remove('row-sticky-highlight');
      __currentStickyRow = null;
    }
  }
  function findStudentAndReveal(queryRaw) {
    const q = normalizeQuery(queryRaw);
    if (!q) return;

    const qId = extractSchoolIdFromQuery(queryRaw).toLowerCase();
    let hit = __studentIndex.find(x => x.schoolId && x.schoolId.toLowerCase() === qId && qId !== '');
    if (!hit && qId) hit = __studentIndex.find(x => (x.schoolId || '').toLowerCase().includes(qId));
    if (!hit) hit = __studentIndex.find(x => (x.name || '').includes(q));
    if (!hit) {
      const parts = q.split(' ').filter(Boolean);
      hit = __studentIndex.find(x => parts.every(p => (x.name || '').includes(p)));
    }
    if (!hit) {
      alert('No matching student found.');
      return;
    }

    clearStickyHighlight();
    const ok = activateTabById(hit.tabId);
    if (!ok) {
      alert('Found the student but failed to open the tab.');
      return;
    }
    __currentStickyRow = hit.tr;
    setTimeout(() => revealRowInDataTable(hit.tableApi, hit.tr), 150);
  }

  document.addEventListener('DOMContentLoaded', function () {
    // Compute offset if a fixed/sticky top navbar exists to prevent header overlap
    function getFixedHeaderOffset() {
      let total = 0;
      const stack = [];
      const header = document.querySelector('header.navbar.sticky-top, header.navbar.fixed-top');
      if (header) stack.push(header);
      const mgmt = document.getElementById('navbarManagement');
      if (mgmt && (mgmt.classList.contains('sticky-top') || mgmt.classList.contains('fixed-top'))) stack.push(mgmt);
      document.querySelectorAll('.navbar.sticky-top, .navbar.fixed-top').forEach(function (el) { if (!stack.includes(el)) stack.push(el); });
      stack.forEach(function (el) { const h = el.offsetHeight || (el.getBoundingClientRect && el.getBoundingClientRect().height) || 0; total += Math.max(0, Math.round(h)); });
      return total;
    }

    // DataTables init
    document.querySelectorAll('.attendance-table').forEach(function (tbl) {
      const $tbl = $(tbl);
      const api = $.fn.dataTable.isDataTable(tbl) ? $tbl.DataTable() : $tbl.DataTable({
        stateSave: false,
        pageLength: 100,
        lengthMenu: [10, 25, 50, 100],
        order: [[1, 'asc']],
        fixedHeader: {
          header: true,
          headerOffset: getFixedHeaderOffset()
        }
      });
      __tableApis.push(api);
    });

    // Build index
    __studentIndex = [];
    document.querySelectorAll('.attendance-grid').forEach(tableEl => {
      const tabPane = tableEl.closest('.tab-pane');
      const tabId = tabPane ? tabPane.id : null;
      const api = __tableApis.find(a => a.table().node() === tableEl);
      tableEl.querySelectorAll('tbody tr[data-student-id]').forEach(tr => {
        const schoolId = (tr.getAttribute('data-school-id') || '').trim();
        const name = (tr.getAttribute('data-student-name') || '').trim();
        __studentIndex.push({ schoolId, name, tr, tableApi: api, tabId });
      });
    });

    // ---------- Search UI (auto-run when a datalist option is chosen) ----------
    const input = document.getElementById('globalStudentSearch');
    const btn   = document.getElementById('globalStudentSearchBtn');
    const clr   = document.getElementById('globalStudentSearchClear');
    const dlist = document.getElementById('studentSuggestions');

    // Cache all suggestion values for quick exact match
    const suggestionSet = new Set(
      Array.from(dlist?.options || []).map(o => (o.value || '').trim())
    );

    let lastAutoQuery = ''; // avoid duplicate firing on same value

    function go() { findStudentAndReveal(input.value); }

    // Enter key still works
    input?.addEventListener('keydown', e => {
      if (e.key === 'Enter') { e.preventDefault(); go(); }
    });

    // Clickable Find (kept for flexibility)
    btn?.addEventListener('click', go);

    // Clear button
    clr?.addEventListener('click', () => {
      if (input) input.value = '';
      clearStickyHighlight();
      input?.focus();
    });

    // Auto-run when the value matches a datalist option exactly
    function tryAutoRun() {
      const val = (input?.value || '').trim();
      if (!val) { clearStickyHighlight(); return; }
      if (suggestionSet.has(val) && val !== lastAutoQuery) {
        lastAutoQuery = val;
        go();
      }
    }

    // Some browsers fire 'change' after picking a datalist option; others only 'input'
    input?.addEventListener('change', tryAutoRun);
    input?.addEventListener('input', () => {
      // If user erased value, remove sticky highlight
      if (!input.value.trim()) clearStickyHighlight();
      // Debounce micro—still feels instant
      clearTimeout(input.__autoTimer);
      input.__autoTimer = setTimeout(tryAutoRun, 50);
    });

    // Adjust columns on tab switch
    $('a[data-bs-toggle="tab"]').on('shown.bs.tab', function () {
      $.fn.dataTable.tables({ visible: true, api: true }).columns.adjust().draw(false);
    });

    // Initial adjust
    $.fn.dataTable.tables({ visible: true, api: true }).columns.adjust().draw(false);

    // ====== Date column navigator (default to anchor Sunday + 3 prior Sundays) ======
    function getDateColsInfo(tableEl) {
      const ths = Array.from(tableEl.querySelectorAll('thead th'));
      const dateCols = [];
      const labels = [];
      ths.forEach((th, idx) => {
        if (th.classList.contains('date-col')) {
          dateCols.push(idx);
          labels.push((th.textContent || '').trim());
        }
      });
      return { dateCols, labels };
    }

    function initDateNavigatorForTable(tableEl) {
      const api = __tableApis.find(a => a.table().node() === tableEl);
      if (!api) return;
      const info = getDateColsInfo(tableEl);
      const dateCols = info.dateCols;
      const labels   = info.labels;
      const windowSize = 4;
      const anchorLabel = (__anchorSunday || '').trim();
      const defaultLabel = (tableEl.dataset.defaultDateLabel || '').trim();

      function resolveAnchorIndex() {
        if (!labels.length) return 0;
        const targetLabel = defaultLabel || anchorLabel;
        if (!targetLabel) return labels.length - 1;
        const exact = labels.indexOf(targetLabel);
        if (exact >= 0) return exact;
        for (let i = labels.length - 1; i >= 0; i--) {
          if (labels[i] <= targetLabel) return i;
        }
        return 0;
      }

      // Store on element for later
      tableEl.__dateCols = dateCols;
      tableEl.__dateLabels = labels;
      tableEl.dataset.windowSize = String(windowSize);
      tableEl.dataset.dateColsCount = String(dateCols.length);

      // Default window ends at oldest incomplete date (fallback to anchor Sunday)
      let start = Math.max(0, resolveAnchorIndex() - (windowSize - 1));
      tableEl.dataset.windowStart = String(start);

      // Apply visibility (anchor Sunday + previous 3 shown by default)
      dateCols.forEach((colIdx, i) => {
        const visible = i >= start && i < start + windowSize;
        api.column(colIdx).visible(visible, false);
      });
      api.columns.adjust().draw(false);

      // Wire up nav UI
      let nav = tableEl.closest('.tab-pane')?.querySelector(`[data-date-nav][data-section-id="${tableEl.getAttribute('data-section-id')}"]`);
      if (!nav) {
        // Fallback: inject above the table if placeholder not found
        const container = document.createElement('div');
        container.className = 'date-nav-wrap d-flex justify-content-center align-items-center gap-2 mb-2';
        container.setAttribute('data-date-nav', '');
        container.innerHTML = `
          <button type="button" class="mgmt-round-arrow date-prev" title="Previous dates" aria-label="Previous dates">
            <i class="bi bi-chevron-left"></i>
          </button>
          <span class="px-2 small date-range-label">&nbsp;</span>
          <button type="button" class="mgmt-round-arrow date-next" title="Next dates" aria-label="Next dates">
            <i class="bi bi-chevron-right"></i>
          </button>`;
        const resp = tableEl.closest('.table-responsive');
        if (resp && resp.parentNode) resp.parentNode.insertBefore(container, resp);
        nav = container;
      }

      function updateNav() {
        const s = parseInt(tableEl.dataset.windowStart || '0', 10);
        const n = parseInt(tableEl.dataset.dateColsCount || '0', 10);
        const size = parseInt(tableEl.dataset.windowSize || '4', 10);
        const prevBtn = nav.querySelector('.date-prev');
        const nextBtn = nav.querySelector('.date-next');
        const lbl = nav.querySelector('.date-range-label');
        const startIdx = Math.max(0, s);
        const endIdx = Math.min(n - 1, s + size - 1);
        const startDate = labels[startIdx] || '';
        const endDate = labels[endIdx] || '';
        lbl.textContent = n ? `${startDate} – ${endDate}` : 'No dates';
        prevBtn.disabled = startIdx <= 0;
        nextBtn.disabled = endIdx >= n - 1;
      }

      function setWindowStart(newStart) {
        const n = dateCols.length;
        const size = parseInt(tableEl.dataset.windowSize || '4', 10);
        const startClamped = Math.max(0, Math.min(newStart, Math.max(0, n - size)));
        if (String(startClamped) === tableEl.dataset.windowStart) return;
        tableEl.dataset.windowStart = String(startClamped);
        dateCols.forEach((colIdx, i) => {
          const vis = i >= startClamped && i < startClamped + size;
          api.column(colIdx).visible(vis, false);
        });
        api.columns.adjust().draw(false);
        updateNav();
      }

      nav.querySelector('.date-prev')?.addEventListener('click', () => {
        const s = parseInt(tableEl.dataset.windowStart || '0', 10);
        setWindowStart(s - 1);
      });
      nav.querySelector('.date-next')?.addEventListener('click', () => {
        const s = parseInt(tableEl.dataset.windowStart || '0', 10);
        setWindowStart(s + 1);
      });

      updateNav();
    }

    document.querySelectorAll('.attendance-grid').forEach(tbl => {
      initDateNavigatorForTable(tbl);
    });
  });
</script>


<style>
  /* highlight classes */
  @keyframes flashHighlight {
    0% {
      background-color: #fff3cd;
    }

    50% {
      background-color: #ffe8a1;
    }

    100% {
      background-color: #fff3cd;
    }
  }

  tr.row-highlight {
    animation: flashHighlight 1.2s ease-in-out 1;
  }

  tr.row-sticky-highlight {
    background-color: #fff3cd !important;
  }
</style>

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