<?php
declare(strict_types=1);

ini_set('display_errors', '0');

require_once __DIR__ . '/../../includes/console_shell.php';
require_login();

$pageLink = 'reports/attendance-report/monthly-log-book-summary.php';
$acl = require_acl('can_view', $pageLink);
$errors = [];

function mlb_stmt(mysqli $con, string $sql): mysqli_stmt
{
    $stmt = $con->prepare($sql);
    if (!$stmt) {
        throw new RuntimeException('Unable to prepare report query.');
    }
    return $stmt;
}

function mlb_run(mysqli_stmt $stmt): void
{
    if (!$stmt->execute()) {
        throw new RuntimeException('Unable to execute report query.');
    }
}

function mlb_options(mysqli $con, string $sql): array
{
    $rows = [];
    $stmt = mlb_stmt($con, $sql);
    mlb_run($stmt);
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        $rows[] = $row;
    }
    $stmt->close();
    return $rows;
}

function mlb_time_minutes(string $value): ?int
{
    $value = trim($value);
    if ($value === '' || $value === '0' || $value === '00:00:00') {
        return null;
    }
    $timestamp = strtotime($value);
    if ($timestamp === false) {
        return null;
    }
    return ((int)date('H', $timestamp) * 60) + (int)date('i', $timestamp);
}

function mlb_duration(?int $start, ?int $end): int
{
    if ($start === null || $end === null) {
        return 0;
    }
    if ($end < $start) {
        $end += 1440;
    }
    return max(0, $end - $start);
}

function mlb_hhmm(int $minutes): string
{
    $minutes = max(0, $minutes);
    return sprintf('%02d:%02d', intdiv($minutes, 60), $minutes % 60);
}

function mlb_display_time(string $value): string
{
    $timestamp = strtotime($value);
    return $timestamp === false ? '' : date('h:i A', $timestamp);
}

function mlb_dates(string $from, string $to): array
{
    $dates = [];
    $cursor = new DateTimeImmutable($from);
    $last = new DateTimeImmutable($to);
    while ($cursor <= $last) {
        $dates[] = $cursor->format('Y-m-d');
        $cursor = $cursor->modify('+1 day');
    }
    return $dates;
}

function mlb_int_list($value): array
{
    return array_values(array_unique(array_filter(array_map('intval', (array)$value), static fn(int $id): bool => $id > 0)));
}

$status = isset($_GET['status']) ? (int)$_GET['status'] : 1;
if (!in_array($status, [0, 1, 2], true)) {
    $status = 1;
}
$employeeIds = mlb_int_list($_GET['employees'] ?? []);
$month = max(0, min(12, (int)($_GET['month'] ?? 0)));
$year = max(0, (int)($_GET['year'] ?? 0));
$departmentId = max(0, (int)($_GET['department'] ?? 0));
$branchId = max(0, (int)($_GET['branch'] ?? 0));
$payrollId = max(0, (int)($_GET['payroll_location'] ?? 0));
$categoryId = max(0, (int)($_GET['category'] ?? 0));
$limit = (int)($_GET['limit'] ?? 40);
if (!in_array($limit, [20, 40, 50, 100, 200], true)) {
    $limit = 40;
}
$submitted = isset($_GET['month']) || isset($_GET['export']);
$primaryFiltersValid = $employeeIds && $month > 0 && $year >= 2000 && $year <= 2100 && $payrollId > 0;
$runReport = $submitted && $primaryFiltersValid;
if ($submitted && !$employeeIds) $errors[] = 'Employee Name is required.';
if ($submitted && $month === 0) $errors[] = 'Month is required.';
if ($submitted && ($year < 2000 || $year > 2100)) $errors[] = 'Year is required.';
if ($submitted && $payrollId === 0) $errors[] = 'Payroll Location is required.';

try {
    $employeesForFilter = mlb_options($con, 'SELECT id, name, status FROM jos_app_employee ORDER BY name ASC, id ASC');
    $departments = mlb_options($con, 'SELECT id, department AS name FROM jos_app_department ORDER BY department ASC, id ASC');
    $branches = mlb_options($con, 'SELECT id, name FROM jos_app_orglocation ORDER BY name ASC, id ASC');
    $payrollLocations = mlb_options($con, 'SELECT id, name FROM jos_app_payrolllocation WHERE status=1 ORDER BY name ASC, id ASC');
    $categories = mlb_options($con, 'SELECT id, designation_name AS name FROM jos_app_emp_category ORDER BY designation_name ASC, id ASC');
} catch (Throwable $e) {
    $employeesForFilter = $departments = $branches = $payrollLocations = $categories = [];
    $errors[] = 'Unable to load report filters.';
}

$dates = [];
$fromDate = $toDate = '';
$employees = [];
$reportRows = [];

if ($runReport && !$errors) {
    $fromDate = sprintf('%04d-%02d-01', $year, $month);
    $toDate = date('Y-m-t', strtotime($fromDate));
    $dates = mlb_dates($fromDate, $toDate);

    try {
        $where = ['e.status=?'];
        $types = 'i';
        $params = [$status];
        foreach ([['e.depat', $departmentId], ['e.branch_location', $branchId], ['e.payroll_location', $payrollId], ['e.category', $categoryId]] as [$column, $value]) {
            if ($value > 0) {
                $where[] = $column . '=?';
                $types .= 'i';
                $params[] = $value;
            }
        }
        if ($employeeIds) {
            $where[] = 'e.id IN (' . implode(',', array_fill(0, count($employeeIds), '?')) . ')';
            $types .= str_repeat('i', count($employeeIds));
            foreach ($employeeIds as $id) {
                $params[] = $id;
            }
        }
        $sql = 'SELECT e.id, e.name, e.photo, e.depat, e.branch_location, e.payroll_location, e.status, d.department, b.name AS branch_name, p.name AS payroll_name FROM jos_app_employee e LEFT JOIN jos_app_department d ON d.id=e.depat LEFT JOIN jos_app_orglocation b ON b.id=e.branch_location LEFT JOIN jos_app_payrolllocation p ON p.id=e.payroll_location WHERE ' . implode(' AND ', $where) . ' ORDER BY e.orderby=0, e.orderby ASC, e.name ASC LIMIT ?';
        $types .= 'i';
        $params[] = $limit;
        $stmt = mlb_stmt($con, $sql);
        $stmt->bind_param($types, ...$params);
        mlb_run($stmt);
        $result = $stmt->get_result();
        while ($row = $result->fetch_assoc()) {
            $employees[] = $row;
        }
        $stmt->close();

        $logStmt = mlb_stmt($con, 'SELECT id, entrydate, in_time, out_time, shiftid, orglocation FROM jos_app_attendance_log WHERE empid=? AND DATE(entrydate) BETWEEN ? AND ? ORDER BY entrydate ASC, id ASC');
        $shiftStmt = mlb_stmt($con, 'SELECT id, shortname, in_time, out_time, in_grace, max_grace, lm_show FROM jos_app_empshift WHERE id=? LIMIT 1');
        $locationStmt = mlb_stmt($con, 'SELECT gatepass FROM jos_app_orglocation WHERE id=? LIMIT 1');

        foreach ($employees as $employee) {
            $empId = (int)$employee['id'];
            $logStmt->bind_param('iss', $empId, $fromDate, $toDate);
            mlb_run($logStmt);
            $logsByDate = [];
            $logResult = $logStmt->get_result();
            while ($log = $logResult->fetch_assoc()) {
                $date = date('Y-m-d', strtotime((string)$log['entrydate']));
                $logsByDate[$date][] = $log;
            }

            $days = [];
            $summary = ['present' => 0, 'absent' => 0, 'worked' => 0, 'extra' => 0, 'loss' => 0, 'late' => 0];
            $shiftCache = [];
            $locationCache = [];
            foreach ($dates as $date) {
                $logs = $logsByDate[$date] ?? [];
                $punches = [];
                $worked = $gatepass = 0;
                $shift = null;
                foreach ($logs as $log) {
                    $shiftId = (int)($log['shiftid'] ?? 0);
                    if ($shiftId > 0 && !array_key_exists($shiftId, $shiftCache)) {
                        $shiftStmt->bind_param('i', $shiftId);
                        mlb_run($shiftStmt);
                        $shiftCache[$shiftId] = $shiftStmt->get_result()->fetch_assoc() ?: null;
                    }
                    if ($shift === null && $shiftId > 0) {
                        $shift = $shiftCache[$shiftId] ?? null;
                    }
                    $in = trim((string)($log['in_time'] ?? ''));
                    $out = trim((string)($log['out_time'] ?? ''));
                    if ($in !== '' && $in !== '0') $punches[] = mlb_display_time($in);
                    if ($out !== '' && $out !== '0') $punches[] = mlb_display_time($out);
                    $duration = mlb_duration(mlb_time_minutes($in), mlb_time_minutes($out));
                    $locationId = (int)($log['orglocation'] ?? 0);
                    if ($locationId > 0 && !array_key_exists($locationId, $locationCache)) {
                        $locationStmt->bind_param('i', $locationId);
                        mlb_run($locationStmt);
                        $locationCache[$locationId] = (int)($locationStmt->get_result()->fetch_assoc()['gatepass'] ?? 0);
                    }
                    if (($locationCache[$locationId] ?? 0) === 1) $gatepass += $duration; else $worked += $duration;
                }

                $scheduled = $shift ? mlb_duration(mlb_time_minutes((string)$shift['in_time']), mlb_time_minutes((string)$shift['out_time'])) : 0;
                $extra = $scheduled > 0 ? max(0, $worked - $scheduled) : 0;
                $loss = $scheduled > 0 ? max(0, $scheduled - $worked) : 0;
                $late = 0;
                if ($shift && $logs && (int)($shift['lm_show'] ?? 0) === 0) {
                    $firstIn = mlb_time_minutes((string)($logs[0]['in_time'] ?? ''));
                    $shiftIn = mlb_time_minutes((string)$shift['in_time']);
                    $graceParts = explode('-', (string)($shift['in_grace'] ?? '0-0'));
                    $grace = (int)end($graceParts);
                    if ($firstIn !== null && $shiftIn !== null) $late = max(0, $firstIn - $shiftIn - $grace);
                }
                $present = $worked > 0;
                $summary[$present ? 'present' : 'absent']++;
                $summary['worked'] += $worked;
                $summary['extra'] += $extra;
                $summary['loss'] += $loss;
                if ($late > 0) $summary['late']++;
                $days[$date] = ['shift' => (string)($shift['shortname'] ?? ''), 'status' => $present ? 'P' : 'A', 'punches' => $punches, 'gatepass' => $gatepass, 'worked' => $worked, 'extra' => $extra, 'loss' => $loss, 'late' => $late];
            }
            $reportRows[] = ['employee' => $employee, 'days' => $days, 'summary' => $summary];
        }
        $logStmt->close(); $shiftStmt->close(); $locationStmt->close();
    } catch (Throwable $e) {
        $errors[] = 'Unable to generate Monthly Log Book Summary.';
        $reportRows = [];
    }
}

$isExport = $runReport && in_array((string)($_GET['export'] ?? ''), ['xls', 'xlsx'], true);
if ($isExport && !$errors) {
    if (!class_exists('ZipArchive')) {
        http_response_code(500);
        exit('Excel export is temporarily unavailable.');
    }

    $xlsxText = static function (string $value): string {
        return htmlspecialchars($value, ENT_XML1 | ENT_QUOTES, 'UTF-8');
    };
    $xlsxColumn = static function (int $number): string {
        $column = '';
        while ($number > 0) {
            $number--;
            $column = chr(65 + ($number % 26)) . $column;
            $number = intdiv($number, 26);
        }
        return $column;
    };
    $sheetRows = [];
    $headers = ['Employee', 'Department', 'Branch'];
    foreach ($dates as $date) $headers[] = date('d-m-Y', strtotime($date));
    $headers = array_merge($headers, ['Present', 'Absent', 'Total Hours']);
    $exportRows = [$headers];
    foreach ($reportRows as $row) {
        $values = [
            (string)$row['employee']['name'],
            (string)($row['employee']['department'] ?? ''),
            (string)($row['employee']['branch_name'] ?? ''),
        ];
        foreach ($dates as $date) {
            $values[] = (string)$row['days'][$date]['status'] . ' ' . mlb_hhmm((int)$row['days'][$date]['worked']);
        }
        $values[] = (string)$row['summary']['present'];
        $values[] = (string)$row['summary']['absent'];
        $values[] = mlb_hhmm((int)$row['summary']['worked']);
        $exportRows[] = $values;
    }
    foreach ($exportRows as $rowNumber => $values) {
        $cells = [];
        foreach ($values as $columnNumber => $value) {
            $reference = $xlsxColumn($columnNumber + 1) . ($rowNumber + 1);
            $cells[] = '<c r="' . $reference . '" t="inlineStr"><is><t xml:space="preserve">' . $xlsxText((string)$value) . '</t></is></c>';
        }
        $sheetRows[] = '<row r="' . ($rowNumber + 1) . '">' . implode('', $cells) . '</row>';
    }

    $temporaryFile = tempnam(sys_get_temp_dir(), 'mlb-xlsx-');
    $zip = new ZipArchive();
    if ($temporaryFile === false || $zip->open($temporaryFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
        http_response_code(500);
        exit('Unable to create Excel export.');
    }
    $zip->addFromString('[Content_Types].xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/></Types>');
    $zip->addFromString('_rels/.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>');
    $zip->addFromString('xl/workbook.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Monthly Log Book" sheetId="1" r:id="rId1"/></sheets></workbook>');
    $zip->addFromString('xl/_rels/workbook.xml.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/></Relationships>');
    $zip->addFromString('xl/worksheets/sheet1.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>' . implode('', $sheetRows) . '</sheetData></worksheet>');
    $zip->close();

    $filename = 'monthly-log-book-summary-' . $year . '-' . sprintf('%02d', $month) . '.xlsx';
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Content-Length: ' . filesize($temporaryFile));
    header('Cache-Control: no-store, no-cache, must-revalidate');
    readfile($temporaryFile);
    unlink($temporaryFile);
    exit;
}

console_header('Monthly Log Book Summary', $pageLink);
$filterClass = 'mt-1 w-full rounded-lg border border-slate-200 bg-white px-2.5 py-2 text-sm text-slate-800 outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-100';
?>
<style>
@page { size: landscape; margin: 7mm; }
@media print {
  nav, header, footer, .no-print { display:none!important; }
  body, main { margin:0!important; padding:0!important; background:#fff!important; }
  .mb-6 { margin-bottom:8px!important; }
  .print-card { width:100%!important; border:0!important; box-shadow:none!important; overflow:visible!important; }
  .print-card > div { overflow:visible!important; }
  .mlb-grid { width:100%!important; min-width:0!important; table-layout:fixed!important; font-size:5.5px!important; }
  .mlb-grid .employee-col { position:static!important; width:68px!important; min-width:68px!important; }
  .mlb-grid .day-col { width:auto!important; min-width:0!important; padding:2px 0!important; }
  .mlb-grid th, .mlb-grid td { min-width:0!important; padding:2px 1px!important; line-height:1.15!important; overflow-wrap:anywhere!important; }
  .mlb-grid .sticky-col { position:static!important; }
  .mlb-grid tr { break-inside:avoid; page-break-inside:avoid; }
}
.mlb-grid th,.mlb-grid td{border:1px solid #cbd5e1;vertical-align:top}.mlb-grid .sticky-col{position:sticky;left:0;background:#fff;z-index:2}.mlb-grid thead .sticky-col{background:#f8fafc;z-index:3}
@media (min-width:1280px){
  .mlb-grid{width:100%;table-layout:fixed;font-size:9px!important}
  .mlb-grid .employee-col{width:150px;min-width:150px}
  .mlb-grid .day-col{width:auto;min-width:0;padding:6px 2px!important}
  .mlb-grid td{min-width:0;padding:5px 2px!important;line-height:1.25;overflow-wrap:anywhere}
}
</style>
<div class="mb-6"><div class="flex items-center gap-2 text-[12px] font-semibold text-slate-500 mb-2"><a href="/dashboard.php" class="hover:text-brand-600">Dashboard</a><i class="fa-solid fa-chevron-right text-[9px]"></i><span>Reports</span><i class="fa-solid fa-chevron-right text-[9px]"></i><span>Attendance Report</span><i class="fa-solid fa-chevron-right text-[9px]"></i><span class="text-brand-600">Monthly Log Book Summary</span></div><h1 class="text-2xl font-bold text-slate-900">Monthly Log Book Summary</h1><p class="mt-1 text-sm text-slate-500">Employee attendance, shift, punch, gate-pass and working-hour summary.</p></div>
<?php if ($errors): ?><div class="mb-6 rounded-xl border border-red-100 bg-red-50 px-5 py-4 text-sm font-semibold text-red-700"><?php foreach ($errors as $error): ?><div><?= h($error) ?></div><?php endforeach; ?></div><?php endif; ?>
<form method="get" id="report-filter-form" class="no-print mb-5 rounded-2xl border border-slate-100 bg-white p-4 shadow-sm"><div class="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
    <div class="relative text-sm font-semibold text-slate-700 employee-picker">Employee Name
        <button type="button" id="employee-picker-toggle" class="<?= $filterClass ?> flex min-h-[42px] items-center justify-between gap-3 text-left font-normal">
            <span id="employee-picker-summary" class="truncate"><?= $employeeIds ? h(count($employeeIds) . ' employee(s) selected') : 'Type or select employees' ?></span>
            <i class="fa-solid fa-chevron-down text-xs text-slate-400"></i>
        </button>
        <div id="employee-picker-panel" class="absolute left-0 right-0 top-full z-50 mt-1 hidden overflow-hidden rounded-xl border border-slate-200 bg-white shadow-xl">
            <div class="border-b border-slate-100 p-2">
                <input type="search" id="employee-picker-search" placeholder="Search employee..." autocomplete="off" class="w-full rounded-lg border border-slate-200 px-3 py-2 text-sm font-normal outline-none focus:border-brand-500">
            </div>
            <div id="employee-picker-options" class="max-h-56 overflow-y-auto p-2">
                <?php foreach ($employeesForFilter as $option): ?>
                    <label class="employee-option flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2 text-sm font-normal text-slate-700 hover:bg-brand-50" data-name="<?= h(mb_strtolower((string)$option['name'])) ?>">
                        <input type="checkbox" name="employees[]" value="<?= h((string)$option['id']) ?>" <?= in_array((int)$option['id'], $employeeIds, true) ? 'checked' : '' ?> class="rounded border-slate-300 text-brand-600">
                        <span><?= h((string)$option['name']) ?></span>
                    </label>
                <?php endforeach; ?>
                <div id="employee-picker-empty" class="hidden px-3 py-4 text-center text-xs font-medium text-slate-400">No employee found.</div>
            </div>
        </div>
    </div>
    <label class="text-sm font-semibold text-slate-700">Month<select name="month" required class="<?= $filterClass ?>"><option value="">Select Month</option><?php for ($m=1;$m<=12;$m++): ?><option value="<?= $m ?>" <?= $month===$m?'selected':'' ?>><?= h(date('F',mktime(0,0,0,$m,1))) ?></option><?php endfor; ?></select></label>
    <label class="text-sm font-semibold text-slate-700">Year<select name="year" required class="<?= $filterClass ?>"><option value="">Select Year</option><?php for ($y=(int)date('Y')+1;$y>=(int)date('Y')-4;$y--): ?><option value="<?= $y ?>" <?= $year===$y?'selected':'' ?>><?= $y ?></option><?php endfor; ?></select></label>
    <label class="text-sm font-semibold text-slate-700">Payroll Location<select name="payroll_location" required class="<?= $filterClass ?>"><option value="">Select Payroll Location</option><?php foreach ($payrollLocations as $option): ?><option value="<?= h((string)$option['id']) ?>" <?= $payrollId===(int)$option['id']?'selected':'' ?>><?= h((string)$option['name']) ?></option><?php endforeach; ?></select></label>
</div>
<div class="mt-4 flex flex-wrap items-center justify-between gap-3">
    <button type="button" id="additional-filter-toggle" aria-expanded="false" aria-controls="additional-filters" class="rounded-lg border border-slate-200 bg-white px-4 py-2.5 text-sm font-bold text-slate-700 hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700"><i class="fa-solid fa-sliders mr-2"></i><span>Use Additional Filters</span><i class="fa-solid fa-chevron-down ml-2 text-xs"></i></button>
    <div class="flex flex-wrap justify-end gap-2"><button class="rounded-lg bg-red-500 px-5 py-2.5 text-sm font-bold text-white hover:bg-red-600"><i class="fa-solid fa-filter mr-2"></i>Go</button><button type="button" id="print-report" class="rounded-lg bg-red-500 px-5 py-2.5 text-sm font-bold text-white hover:bg-red-600"><i class="fa-solid fa-print mr-2"></i>Print</button><button name="export" value="xlsx" class="rounded-lg bg-emerald-600 px-5 py-2.5 text-sm font-bold text-white hover:bg-emerald-700"><i class="fa-solid fa-file-excel mr-2"></i>Export to XLSX</button></div>
</div>
<div id="additional-filters" class="mt-4 hidden border-t border-slate-100 pt-4"><div class="grid gap-3 md:grid-cols-2 xl:grid-cols-5">
    <label class="text-sm font-semibold text-slate-700">Select Status<select name="status" class="<?= $filterClass ?>"><option value="1" <?= $status===1?'selected':'' ?>>Active</option><option value="0" <?= $status===0?'selected':'' ?>>Inactive</option><option value="2" <?= $status===2?'selected':'' ?>>Left From Company</option></select></label>
    <label class="text-sm font-semibold text-slate-700">Department<select name="department" class="<?= $filterClass ?>"><option value="0">Select All</option><?php foreach ($departments as $option): ?><option value="<?= h((string)$option['id']) ?>" <?= $departmentId===(int)$option['id']?'selected':'' ?>><?= h((string)$option['name']) ?></option><?php endforeach; ?></select></label>
    <label class="text-sm font-semibold text-slate-700">Branch Location<select name="branch" class="<?= $filterClass ?>"><option value="0">Select Branch</option><?php foreach ($branches as $option): ?><option value="<?= h((string)$option['id']) ?>" <?= $branchId===(int)$option['id']?'selected':'' ?>><?= h((string)$option['name']) ?></option><?php endforeach; ?></select></label>
    <label class="text-sm font-semibold text-slate-700">Category<select name="category" class="<?= $filterClass ?>"><option value="0">Select Category</option><?php foreach ($categories as $option): ?><option value="<?= h((string)$option['id']) ?>" <?= $categoryId===(int)$option['id']?'selected':'' ?>><?= h((string)$option['name']) ?></option><?php endforeach; ?></select></label>
    <label class="text-sm font-semibold text-slate-700">List Limit<select name="limit" class="<?= $filterClass ?>"><?php foreach ([20,40,50,100,200] as $option): ?><option value="<?= $option ?>" <?= $limit===$option?'selected':'' ?>>1-<?= $option ?></option><?php endforeach; ?></select></label>
</div></div></form>

<div class="print-card rounded-2xl border border-slate-100 bg-white shadow-sm overflow-hidden"><div class="border-b border-slate-100 px-6 py-5"><h2 class="text-lg font-bold text-slate-900">Employee Monthly Log Book Summary<?= $runReport ? ' — ' . h(date('F Y', strtotime($fromDate))) : '' ?></h2></div>
<?php if (!$runReport): ?><div class="px-6 py-16 text-center text-sm font-medium text-slate-500">Select a month and year, then click Go.</div><?php elseif (!$reportRows): ?><div class="px-6 py-16 text-center text-sm font-medium text-slate-500">No employees found for the selected filters.</div><?php else: ?><div class="overflow-x-auto"><table class="mlb-grid min-w-max xl:min-w-0 text-[11px] text-slate-700"><thead class="bg-slate-50"><tr><th class="sticky-col employee-col min-w-44 px-3 py-3 text-left">Employee / Detail</th><?php foreach ($dates as $date): ?><th class="day-col min-w-24 px-2 py-3 text-center"><?= h(date('D',strtotime($date))) ?><br><?= h(date('d-m',strtotime($date))) ?></th><?php endforeach; ?></tr></thead><tbody>
<?php foreach ($reportRows as $row): $emp=$row['employee']; $days=$row['days']; ?><tr><td class="sticky-col px-3 py-3 font-bold" rowspan="6">#<?= h((string)$emp['id']) ?><br><?= h((string)$emp['name']) ?><br><span class="font-medium text-slate-500"><?= h((string)($emp['department']??'')) ?><br><?= h((string)($emp['branch_name']??'')) ?></span></td><?php foreach ($dates as $date): ?><td class="px-2 py-2 text-center"><span class="font-bold"><?= h((string)$days[$date]['shift']) ?></span></td><?php endforeach; ?></tr>
<tr><?php foreach ($dates as $date): ?><td class="px-2 py-2 text-center font-bold <?= $days[$date]['status']==='P'?'text-emerald-600':'text-red-500' ?>"><?= h((string)$days[$date]['status']) ?></td><?php endforeach; ?></tr>
<tr><?php foreach ($dates as $date): ?><td class="px-2 py-2 text-center"><?= $days[$date]['punches'] ? h(implode(' / ',$days[$date]['punches'])) : '—' ?></td><?php endforeach; ?></tr>
<tr><?php foreach ($dates as $date): ?><td class="px-2 py-2 text-center"><b><?= h(mlb_hhmm((int)$days[$date]['worked'])) ?></b><?php if ($days[$date]['gatepass']>0): ?><br><span class="text-red-500">GP <?= h(mlb_hhmm((int)$days[$date]['gatepass'])) ?></span><?php endif; ?></td><?php endforeach; ?></tr>
<tr><?php foreach ($dates as $date): ?><td class="px-2 py-2 text-center"><?php if ($days[$date]['extra']>0): ?><span class="text-emerald-600">E +<?= h(mlb_hhmm((int)$days[$date]['extra'])) ?></span><?php endif; ?><?php if ($days[$date]['loss']>0): ?><br><span class="text-red-500">L -<?= h(mlb_hhmm((int)$days[$date]['loss'])) ?></span><?php endif; ?></td><?php endforeach; ?></tr>
<tr><?php foreach ($dates as $date): ?><td class="px-2 py-2 text-center"><?= $days[$date]['late']>0 ? 'Late '.h(mlb_hhmm((int)$days[$date]['late'])) : '—' ?></td><?php endforeach; ?></tr>
<tr class="bg-slate-50"><td class="sticky-col px-3 py-3 font-bold">Summary</td><td colspan="<?= h((string)count($dates)) ?>" class="px-4 py-3 font-semibold">Present: <?= h((string)$row['summary']['present']) ?> &nbsp; | &nbsp; Absent: <?= h((string)$row['summary']['absent']) ?> &nbsp; | &nbsp; Total Hrs: <?= h(mlb_hhmm((int)$row['summary']['worked'])) ?> &nbsp; | &nbsp; Extra: <?= h(mlb_hhmm((int)$row['summary']['extra'])) ?> &nbsp; | &nbsp; Loss: <?= h(mlb_hhmm((int)$row['summary']['loss'])) ?> &nbsp; | &nbsp; Late Marks: <?= h((string)$row['summary']['late']) ?></td></tr><?php endforeach; ?>
</tbody></table></div><?php endif; ?></div>
<script>
(() => {
    const filterForm = document.getElementById('report-filter-form');
    const additionalToggle = document.getElementById('additional-filter-toggle');
    const additionalFilters = document.getElementById('additional-filters');
    if (additionalToggle && additionalFilters) {
        additionalToggle.addEventListener('click', () => {
            const opening = additionalFilters.classList.contains('hidden');
            additionalFilters.classList.toggle('hidden');
            additionalToggle.setAttribute('aria-expanded', opening ? 'true' : 'false');
            additionalToggle.querySelector('span').textContent = opening ? 'Hide Additional Filters' : 'Use Additional Filters';
            additionalToggle.querySelector('.fa-chevron-down').classList.toggle('rotate-180', opening);
        });
    }

    const printButton = document.getElementById('print-report');
    if (printButton) {
        printButton.addEventListener('click', () => {
            const reportScroller = document.querySelector('.print-card .overflow-x-auto');
            if (reportScroller) reportScroller.scrollLeft = 0;
            window.print();
        });
    }

    const picker = document.querySelector('.employee-picker');
    const toggle = document.getElementById('employee-picker-toggle');
    const panel = document.getElementById('employee-picker-panel');
    const search = document.getElementById('employee-picker-search');
    const summary = document.getElementById('employee-picker-summary');
    const options = Array.from(document.querySelectorAll('.employee-option'));
    const empty = document.getElementById('employee-picker-empty');
    if (!picker || !toggle || !panel || !search || !summary) return;

    if (filterForm) {
        filterForm.addEventListener('submit', event => {
            if (!options.some(option => option.querySelector('input').checked)) {
                event.preventDefault();
                panel.classList.remove('hidden');
                toggle.focus();
                summary.textContent = 'Please select at least one employee';
                summary.classList.add('text-red-600');
            }
        });
    }

    const updateSummary = () => {
        const checked = options.filter(option => option.querySelector('input').checked);
        summary.classList.remove('text-red-600');
        if (checked.length === 0) summary.textContent = 'Type or select employees';
        else if (checked.length === 1) summary.textContent = checked[0].querySelector('span').textContent;
        else summary.textContent = checked.length + ' employees selected';
    };

    toggle.addEventListener('click', () => {
        panel.classList.toggle('hidden');
        if (!panel.classList.contains('hidden')) search.focus();
    });
    search.addEventListener('input', () => {
        const term = search.value.trim().toLowerCase();
        let visible = 0;
        options.forEach(option => {
            const show = option.dataset.name.includes(term);
            option.classList.toggle('hidden', !show);
            if (show) visible++;
        });
        empty.classList.toggle('hidden', visible !== 0);
    });
    options.forEach(option => option.querySelector('input').addEventListener('change', updateSummary));
    document.addEventListener('click', event => {
        if (!picker.contains(event.target)) panel.classList.add('hidden');
    });
    updateSummary();
})();
</script>
<?php console_footer(); ?>
