<?php
declare(strict_types=1);

ini_set('display_errors', '0');

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

$pageLink = 'masters/employee-shifts.php';
$acl = require_acl('can_view', $pageLink);
$errors = [];
$flash = $_SESSION['flash_employee_shifts'] ?? null;
unset($_SESSION['flash_employee_shifts']);

$mode = (string)($_GET['mode'] ?? '');
$editId = max(0, (int)($_GET['edit'] ?? 0));
$isFormView = $mode === 'add' || $editId > 0;
$search = trim((string)($_GET['q'] ?? ''));
$editItem = null;

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

function shift_run(mysqli_stmt $stmt): void
{
    if (!$stmt->execute()) {
        throw new RuntimeException('Unable to complete database operation.');
    }
}

function shift_text(string $value, int $max = 255): string
{
    $value = trim((string)(preg_replace('/\s+/u', ' ', $value) ?? $value));
    return mb_substr($value, 0, $max);
}

function shift_flag($value): int
{
    return (string)$value === '1' ? 1 : 0;
}

function shift_time_valid(string $value): bool
{
    $date = DateTimeImmutable::createFromFormat('!H:i', $value);
    return $date !== false && $date->format('H:i') === $value;
}

function shift_hhmm_valid(string $value): bool
{
    return $value === '' || preg_match('/^(?:\d{1,3}):[0-5]\d$/', $value) === 1;
}

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

function shift_input_time(mixed $value): string
{
    $value = trim((string)$value);
    return $value === '' || $value === '0' ? '' : date('H:i', strtotime($value));
}

function shift_total_hours(string $in, string $out): string
{
    $start = DateTimeImmutable::createFromFormat('!H:i', $in);
    $end = DateTimeImmutable::createFromFormat('!H:i', $out);
    if (!$start || !$end) {
        return '';
    }
    if ($end < $start) {
        $end = $end->modify('+1 day');
    }
    $minutes = (int)(($end->getTimestamp() - $start->getTimestamp()) / 60);
    return intdiv($minutes, 60) . ' hrs, ' . ($minutes % 60) . 'min';
}

function shift_locations(mysqli $con, int $shiftId): array
{
    $items = [];
    $stmt = shift_stmt($con, 'SELECT l.orglocation, l.status, o.name FROM jos_app_empshift_locationlog l INNER JOIN jos_app_orglocation o ON o.id=l.orglocation WHERE l.shiftid=? ORDER BY o.name ASC, l.id ASC');
    $stmt->bind_param('i', $shiftId);
    shift_run($stmt);
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        $items[] = $row;
    }
    $stmt->close();
    return $items;
}

function shift_selected_locations(mysqli $con, int $shiftId): array
{
    return array_map(static fn(array $row): int => (int)$row['orglocation'], shift_locations($con, $shiftId));
}

function shift_post_data(): array
{
    $locations = array_values(array_unique(array_filter(
        array_map('intval', (array)($_POST['orglocation'] ?? [])),
        static fn(int $id): bool => $id > 0
    )));
    return [
        'id' => max(0, (int)($_POST['id'] ?? 0)),
        'shift' => max(0, (int)($_POST['shift'] ?? 0)),
        'shift_type' => shift_text((string)($_POST['shift_type'] ?? '')),
        'shortname' => shift_text((string)($_POST['shortname'] ?? ''), 50),
        'in_time' => trim((string)($_POST['in_time'] ?? '')),
        'in_grace' => trim((string)($_POST['in_grace'] ?? '')),
        'max_grace' => trim((string)($_POST['max_grace'] ?? '')),
        'out_time' => trim((string)($_POST['out_time'] ?? '')),
        'max_out' => trim((string)($_POST['max_out'] ?? '')),
        'lunch_applicable' => shift_flag($_POST['lunch_applicable'] ?? 0),
        'lunch_time' => trim((string)($_POST['lunch_time'] ?? '')),
        'notapplay_time' => trim((string)($_POST['notapplay_time'] ?? '')),
        'lunch_minusinshift' => shift_flag($_POST['lunch_minusinshift'] ?? 0),
        'lunch_minusinwork' => shift_flag($_POST['lunch_minusinwork'] ?? 0),
        'unused_lunch' => (int)($_POST['unused_lunch'] ?? 0),
        'minlt_time' => trim((string)($_POST['minlt_time'] ?? '')),
        'lunch_in' => trim((string)($_POST['lunch_in'] ?? '')),
        'cameraonof' => shift_flag($_POST['cameraonof'] ?? 0),
        'indisplaybefore' => trim((string)($_POST['indisplaybefore'] ?? '')),
        'indisplayafter' => trim((string)($_POST['indisplayafter'] ?? '')),
        'outdisplaybefore' => trim((string)($_POST['outdisplaybefore'] ?? '')),
        'outdisplayafter' => trim((string)($_POST['outdisplayafter'] ?? '')),
        'ot_category' => (int)($_POST['ot_category'] ?? 0),
        'lm_show' => shift_flag($_POST['lm_show'] ?? 0),
        'night_category' => (int)($_POST['night_category'] ?? 0),
        'night_shift' => shift_flag($_POST['night_shift'] ?? 0),
        'night_onwff' => shift_flag($_POST['night_onwff'] ?? 0),
        'night_otcount' => shift_flag($_POST['night_otcount'] ?? 0),
        'night_ot' => shift_flag($_POST['night_ot'] ?? 0),
        'night_shiftcount' => shift_flag($_POST['night_shiftcount'] ?? 0),
        'shiftcount_onwff' => shift_flag($_POST['shiftcount_onwff'] ?? 0),
        'minwork_short' => trim((string)($_POST['minwork_short'] ?? '')),
        'min_worktime' => trim((string)($_POST['min_worktime'] ?? '')),
        'max_worktime' => trim((string)($_POST['max_worktime'] ?? '')),
        'early_logouttime' => trim((string)($_POST['early_logouttime'] ?? '')),
        'locations' => $locations,
    ];
}

if (mb_strlen($search) > 100) {
    $errors[] = 'Search must be 100 characters or fewer.';
    $search = '';
}

$cameraFeatureEnabled = false;
try {
    $stmt = shift_stmt($con, 'SELECT cameraonof FROM jos_app_usersetting LIMIT 1');
    shift_run($stmt);
    $cameraFeatureEnabled = (int)($stmt->get_result()->fetch_assoc()['cameraonof'] ?? 0) === 1;
    $stmt->close();
} catch (Throwable $e) {
    $cameraFeatureEnabled = false;
}

$posted = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = (string)($_POST['action'] ?? '');
    if (!verify_csrf($_POST['_csrf'] ?? null)) {
        $errors[] = 'Security token expired. Please refresh and try again.';
    } elseif ($action !== 'save') {
        $errors[] = 'Invalid request.';
    } else {
        $posted = shift_post_data();
        $id = $posted['id'];
        if ($id > 0 && empty($acl['can_edit'])) {
            $errors[] = 'You do not have permission to edit employee shifts.';
        }
        if ($id === 0 && empty($acl['can_add'])) {
            $errors[] = 'You do not have permission to add employee shifts.';
        }
        if ($posted['shift'] <= 0) $errors[] = 'Shift Type is required.';
        if ($posted['shift_type'] === '') $errors[] = 'Shift Name is required.';
        if ($posted['shortname'] === '') $errors[] = 'Shift Short Name is required.';
        if (!shift_time_valid($posted['in_time'])) $errors[] = 'A valid In Time is required.';
        if (!shift_time_valid($posted['out_time'])) $errors[] = 'A valid Out Time is required.';
        if ($posted['in_grace'] === '' || !ctype_digit($posted['in_grace'])) $errors[] = 'LM Grace must contain minutes only.';
        if ($posted['max_grace'] !== '' && !ctype_digit($posted['max_grace'])) $errors[] = 'Max LM Grace must contain minutes only.';
        if (!$posted['locations']) $errors[] = 'Select at least one Terminal Location.';
        if (!in_array($posted['ot_category'], [0, 1, 2], true)) $errors[] = 'Invalid OT Category.';
        if (!in_array($posted['unused_lunch'], [0, 1, 2], true)) $errors[] = 'Invalid unused lunch option.';
        if (!in_array($posted['night_category'], [0, 1, 2], true)) $errors[] = 'Invalid night calculation option.';

        $isMidnightShift = false;
        if (!$cameraFeatureEnabled || !$posted['cameraonof']) {
            $posted['cameraonof'] = 0;
            foreach (['indisplaybefore', 'indisplayafter', 'outdisplaybefore', 'outdisplayafter'] as $field) $posted[$field] = '';
        } else {
            foreach (['indisplaybefore', 'indisplayafter', 'outdisplaybefore', 'outdisplayafter'] as $field) {
                if ($posted[$field] !== '' && !shift_time_valid($posted[$field])) $errors[] = 'Camera display times must use a valid time.';
            }
        }
        if (!$posted['lunch_applicable']) {
            foreach (['lunch_time', 'notapplay_time', 'minlt_time', 'lunch_in'] as $field) $posted[$field] = '';
            $posted['lunch_minusinshift'] = $posted['lunch_minusinwork'] = $posted['unused_lunch'] = 0;
        } else {
            if ($posted['lunch_time'] !== '' && !ctype_digit($posted['lunch_time'])) $errors[] = 'Lunch Hours must contain minutes only.';
            if (!shift_hhmm_valid($posted['notapplay_time'])) $errors[] = 'Don’t Apply Lunch time must use HH:MM.';
            if (!shift_hhmm_valid($posted['minlt_time'])) $errors[] = 'Minimum Hours to Apply Lunch must use HH:MM.';
            if ($posted['lunch_in'] !== '' && !shift_time_valid($posted['lunch_in'])) $errors[] = 'Lunch Start Time is invalid.';
            if ($posted['minlt_time'] !== '' && $posted['lunch_in'] !== '') $errors[] = 'Enter either Minimum Hours to Apply Lunch or Lunch Start Time, not both.';
        }
        if ($posted['ot_category'] !== 2) {
            $posted['night_category'] = $posted['night_shift'] = $posted['night_onwff'] = 0;
            $posted['night_otcount'] = $posted['night_ot'] = $posted['night_shiftcount'] = $posted['shiftcount_onwff'] = 0;
        }
        foreach (['minwork_short', 'min_worktime', 'max_worktime'] as $field) {
            if (!shift_hhmm_valid($posted[$field])) $errors[] = 'Shift configuration times must use HH:MM.';
        }
        if ($posted['early_logouttime'] !== '' && !ctype_digit($posted['early_logouttime'])) $errors[] = 'Early Logout must contain minutes only.';

        if (!$errors) {
            try {
                $stmt = shift_stmt($con, 'SELECT id, name FROM jos_app_empshiftgroup WHERE id=? AND active_status=1 LIMIT 1');
                $stmt->bind_param('i', $posted['shift']);
                shift_run($stmt);
                $groupRow = $stmt->get_result()->fetch_assoc();
                if (!$groupRow) {
                    $errors[] = 'Selected Shift Type is not active.';
                } else {
                    $isMidnightShift = stripos((string)$groupRow['name'], 'midnight') !== false;
                }
                $stmt->close();

                if (!$isMidnightShift) {
                    $posted['max_out'] = '';
                } elseif ($posted['max_out'] !== '' && !shift_time_valid($posted['max_out'])) {
                    $errors[] = 'Max Out must be a valid time.';
                }

                $stmt = shift_stmt($con, 'SELECT id FROM jos_app_empshift WHERE (shift_type=? OR shortname=?) AND id<>? LIMIT 1');
                $stmt->bind_param('ssi', $posted['shift_type'], $posted['shortname'], $id);
                shift_run($stmt);
                if ($stmt->get_result()->fetch_assoc()) $errors[] = 'Shift Name or Shift Short Name already exists.';
                $stmt->close();

                $stmt = shift_stmt($con, 'SELECT id FROM jos_app_orglocation WHERE id=? LIMIT 1');
                foreach ($posted['locations'] as $locationId) {
                    $stmt->bind_param('i', $locationId);
                    shift_run($stmt);
                    if (!$stmt->get_result()->fetch_assoc()) $errors[] = 'One or more terminal locations are invalid.';
                }
                $stmt->close();
            } catch (Throwable $e) {
                $errors[] = 'Unable to validate shift data. Please try again.';
            }
        }

        if (!$errors) {
            $con->begin_transaction();
            try {
                $inDb = shift_db_time($posted['in_time']);
                $outDb = shift_db_time($posted['out_time']);
                $maxOutDb = shift_db_time($posted['max_out']);
                $lunchInDb = shift_db_time($posted['lunch_in']);
                $inGraceDb = '0-' . (int)$posted['in_grace'];
                $shiftHours = shift_total_hours($posted['in_time'], $posted['out_time']);
                $camInBefore = shift_db_time($posted['indisplaybefore']);
                $camInAfter = shift_db_time($posted['indisplayafter']);
                $camOutBefore = shift_db_time($posted['outdisplaybefore']);
                $camOutAfter = shift_db_time($posted['outdisplayafter']);

                $values = [$posted['shift'], $posted['shift_type'], $posted['shortname'], $inDb, $inGraceDb, $posted['max_grace'], $outDb, $maxOutDb, $shiftHours,
                    $posted['lunch_applicable'], $posted['lunch_time'], $posted['notapplay_time'], $posted['lunch_minusinshift'], $posted['lunch_minusinwork'], $posted['unused_lunch'], $posted['minlt_time'], $lunchInDb,
                    $posted['cameraonof'], $camInBefore, $camInAfter, $camOutBefore, $camOutAfter, $posted['ot_category'], $posted['lm_show'], $posted['night_category'], $posted['night_shift'], $posted['night_onwff'], $posted['night_otcount'], $posted['night_ot'], $posted['night_shiftcount'], $posted['shiftcount_onwff']];
                $types = 'issssssssissiiississssiiiiiiiii';
                $columns = 'shift=?, shift_type=?, shortname=?, in_time=?, in_grace=?, max_grace=?, out_time=?, max_out=?, shifthrs=?, lunch_applicable=?, lunch_time=?, notapplay_time=?, lunch_minusinshift=?, lunch_minusinwork=?, unused_lunch=?, minlt_time=?, lunch_in=?, cameraonof=?, indisplaybefore=?, indisplayafter=?, outdisplaybefore=?, outdisplayafter=?, ot_category=?, lm_show=?, night_category=?, night_shift=?, night_onwff=?, night_otcount=?, night_ot=?, night_shiftcount=?, shiftcount_onwff=?';
                if ($id > 0) {
                    $stmt = shift_stmt($con, 'UPDATE jos_app_empshift SET ' . $columns . ', update_status=0, user_status=0 WHERE id=?');
                    $values[] = $id;
                    $stmt->bind_param($types . 'i', ...$values);
                } else {
                    $stmt = shift_stmt($con, 'INSERT INTO jos_app_empshift SET ' . $columns);
                    $stmt->bind_param($types, ...$values);
                }
                shift_run($stmt);
                $shiftId = $id > 0 ? $id : (int)$con->insert_id;
                $stmt->close();

                $stmt = shift_stmt($con, 'DELETE FROM jos_app_empshift_locationlog WHERE shiftid=?');
                $stmt->bind_param('i', $shiftId); shift_run($stmt); $stmt->close();
                $status = 0;
                $stmt = shift_stmt($con, 'INSERT INTO jos_app_empshift_locationlog (shiftid, orglocation, status) VALUES (?, ?, ?)');
                foreach ($posted['locations'] as $locationId) {
                    $stmt->bind_param('iii', $shiftId, $locationId, $status); shift_run($stmt);
                }
                $stmt->close();

                $stmt = shift_stmt($con, 'DELETE FROM jos_app_halfday_config WHERE shiftid=?');
                $stmt->bind_param('i', $shiftId); shift_run($stmt); $stmt->close();
                $stmt = shift_stmt($con, 'INSERT INTO jos_app_halfday_config (shiftid, min_worktimeshorthr, min_worktimehr, max_worktimehr, early_logouttimemin) VALUES (?, ?, ?, ?, ?)');
                $stmt->bind_param('issss', $shiftId, $posted['minwork_short'], $posted['min_worktime'], $posted['max_worktime'], $posted['early_logouttime']);
                shift_run($stmt); $stmt->close();

                // This is the legacy shift-history business table, not the console audit helper.
                $locationCsv = implode(',', $posted['locations']);
                $modifiedBy = (int)(current_user()['id'] ?? 0);
                $stmt = shift_stmt($con, 'INSERT INTO jos_app_employee_shift_edit_log (`date`, shift, shift_id, shiftname, shift_type, shortname, in_time, in_grace, max_grace, out_time, out_grace, lunch_time, lunch_in, lunch_in_grace, lunch_out, lunch_out_grace, adminingrace, adminlunchoutgrace, update_status, user_status, indipslaybefore, indisplayafter, outdisplaybefore, outdisplayafter, lindisplaybefore, lindisplayafter, loutdisplaybefore, loutdisplayafter, orglocation, modify_by, workhrs, ot_category, min_worktimeshorthr, min_worktimehr, max_worktimehr, early_logouttimemin, lunch_minusinshift, lunch_minusinwork, night_category, night_onwff, night_otcount, night_ot, night_shiftcount) SELECT NOW(), e.shift, e.id, e.shiftname, e.shift_type, e.shortname, e.in_time, e.in_grace, e.max_grace, e.out_time, e.out_grace, e.lunch_time, e.lunch_in, e.lunch_in_grace, e.lunch_out, e.lunch_out_grace, e.adminingrace, e.adminlunchoutgrace, e.update_status, e.user_status, e.indisplaybefore, e.indisplayafter, e.outdisplaybefore, e.outdisplayafter, e.lindisplaybefore, e.lindisplayafter, e.loutdisplaybefore, e.loutdisplayafter, ?, ?, e.workhrs, e.ot_category, h.min_worktimeshorthr, h.min_worktimehr, h.max_worktimehr, h.early_logouttimemin, e.lunch_minusinshift, e.lunch_minusinwork, e.night_category, e.night_onwff, e.night_otcount, e.night_ot, e.night_shiftcount FROM jos_app_empshift e LEFT JOIN jos_app_halfday_config h ON h.shiftid=e.id WHERE e.id=? LIMIT 1');
                $stmt->bind_param('sii', $locationCsv, $modifiedBy, $shiftId);
                shift_run($stmt); $stmt->close();

                $con->commit();
                $_SESSION['flash_employee_shifts'] = $id > 0 ? 'Employee Shift updated successfully.' : 'Employee Shift saved successfully.';
                redirect('/masters/employee-shifts.php');
            } catch (Throwable $e) {
                $con->rollback();
                $errors[] = 'Unable to save Employee Shift. Please try again.';
            }
        }
        $isFormView = true;
        $editId = $id;
    }
}

$shiftTypes = [];
$stmt = shift_stmt($con, 'SELECT id, name FROM jos_app_empshiftgroup WHERE active_status=1 ORDER BY id ASC');
shift_run($stmt); $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) $shiftTypes[] = $row;
$stmt->close();

$terminalOptions = [];
$stmt = shift_stmt($con, 'SELECT id, name FROM jos_app_orglocation ORDER BY name ASC, id ASC');
shift_run($stmt); $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) $terminalOptions[] = $row;
$stmt->close();

if ($editId > 0) {
    try {
        $stmt = shift_stmt($con, 'SELECT e.*, h.min_worktimeshorthr, h.min_worktimehr, h.max_worktimehr, h.early_logouttimemin FROM jos_app_empshift e LEFT JOIN jos_app_halfday_config h ON h.shiftid=e.id WHERE e.id=? LIMIT 1');
        $stmt->bind_param('i', $editId); shift_run($stmt);
        $editItem = $stmt->get_result()->fetch_assoc() ?: null; $stmt->close();
        if (!$editItem && !$errors) {
            $_SESSION['flash_employee_shifts'] = 'Employee Shift record was not found.';
            redirect('/masters/employee-shifts.php');
        }
    } catch (Throwable $e) {
        $errors[] = 'Unable to load Employee Shift.';
    }
}

$shifts = [];
if (!$isFormView) {
    try {
        if ($search !== '') {
            $like = '%' . $search . '%';
            $stmt = shift_stmt($con, 'SELECT e.*, g.name AS group_name, h.min_worktimeshorthr, h.min_worktimehr, h.max_worktimehr, h.early_logouttimemin FROM jos_app_empshift e LEFT JOIN jos_app_empshiftgroup g ON g.id=e.shift LEFT JOIN jos_app_halfday_config h ON h.shiftid=e.id WHERE e.shift_type LIKE ? OR e.shortname LIKE ? ORDER BY e.id ASC');
            $stmt->bind_param('ss', $like, $like);
        } else {
            $stmt = shift_stmt($con, 'SELECT e.*, g.name AS group_name, h.min_worktimeshorthr, h.min_worktimehr, h.max_worktimehr, h.early_logouttimemin FROM jos_app_empshift e LEFT JOIN jos_app_empshiftgroup g ON g.id=e.shift LEFT JOIN jos_app_halfday_config h ON h.shiftid=e.id ORDER BY e.id ASC');
        }
        shift_run($stmt); $result = $stmt->get_result();
        while ($row = $result->fetch_assoc()) {
            $row['locations'] = shift_locations($con, (int)$row['id']);
            $shifts[] = $row;
        }
        $stmt->close();
    } catch (Throwable $e) {
        $errors[] = 'Unable to load Employee Shifts.';
    }
}

$form = $posted ?? ($editItem ?: [
    'id' => 0, 'shift' => 0, 'shift_type' => '', 'shortname' => '', 'in_time' => '', 'in_grace' => '', 'max_grace' => '', 'out_time' => '', 'max_out' => '',
    'lunch_applicable' => 0, 'lunch_time' => '', 'notapplay_time' => '', 'lunch_minusinshift' => 0, 'lunch_minusinwork' => 0, 'unused_lunch' => 0, 'minlt_time' => '', 'lunch_in' => '',
    'cameraonof' => 0, 'indisplaybefore' => '', 'indisplayafter' => '', 'outdisplaybefore' => '', 'outdisplayafter' => '', 'ot_category' => 0, 'lm_show' => 0,
    'night_category' => 0, 'night_shift' => 0, 'night_onwff' => 0, 'night_otcount' => 0, 'night_ot' => 0, 'night_shiftcount' => 0, 'shiftcount_onwff' => 0,
    'minwork_short' => '', 'min_worktime' => '', 'max_worktime' => '', 'early_logouttime' => '', 'locations' => []
]);
if (!$posted && $editItem) {
    $form['in_time'] = shift_input_time($editItem['in_time'] ?? '');
    $form['out_time'] = shift_input_time($editItem['out_time'] ?? '');
    $form['max_out'] = shift_input_time($editItem['max_out'] ?? '');
    $form['lunch_in'] = shift_input_time($editItem['lunch_in'] ?? '');
    foreach (['indisplaybefore', 'indisplayafter', 'outdisplaybefore', 'outdisplayafter'] as $field) $form[$field] = shift_input_time($editItem[$field] ?? '');
    $storedInGrace = (string)($editItem['in_grace'] ?? '');
    $form['in_grace'] = strpos($storedInGrace, '0-') === 0 ? substr($storedInGrace, 2) : $storedInGrace;
    $form['minwork_short'] = (string)($editItem['min_worktimeshorthr'] ?? '');
    $form['min_worktime'] = (string)($editItem['min_worktimehr'] ?? '');
    $form['max_worktime'] = (string)($editItem['max_worktimehr'] ?? '');
    $form['early_logouttime'] = (string)($editItem['early_logouttimemin'] ?? '');
    $form['locations'] = shift_selected_locations($con, (int)$editItem['id']);
}
$formLocations = array_map('intval', (array)($form['locations'] ?? []));
$isEditing = (int)($form['id'] ?? $editId) > 0;

console_header('Employee Shifts', $pageLink);
?>
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 gap-4">
    <div>
        <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>Masters</span><i class="fa-solid fa-chevron-right text-[9px]"></i><span class="text-brand-600">Employee Shifts</span></div>
        <h1 class="text-2xl font-bold text-slate-900">Employee Shift Master</h1>
        <p class="text-sm text-slate-500 mt-1">Manage attendance timing, lunch, OT, terminal and half-day rules.</p>
    </div>
</div>

<?php if ($flash): ?><div class="mb-6 rounded-xl border border-emerald-100 bg-emerald-50 px-5 py-4 text-sm font-semibold text-emerald-700"><?= h((string)$flash) ?></div><?php endif; ?>
<?php if ($errors): ?><div class="mb-6 rounded-xl border border-red-100 bg-red-50 px-5 py-4 text-red-700"><h2 class="font-bold">Please fix the following</h2><ul class="mt-2 list-disc list-inside text-sm"><?php foreach ($errors as $error): ?><li><?= h($error) ?></li><?php endforeach; ?></ul></div><?php endif; ?>

<?php if ($isFormView): ?>
<div class="mb-4">
    <a href="/masters/employee-shifts.php" class="inline-flex items-center gap-2 text-sm font-bold text-brand-600 hover:text-brand-700"><i class="fa-solid fa-arrow-left"></i>Back to List</a>
</div>
<form method="post" class="space-y-6" id="shift-form" novalidate>
    <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>"><input type="hidden" name="action" value="save"><input type="hidden" name="id" value="<?= h((string)($form['id'] ?? $editId)) ?>">
    <?php $inputClass = 'mt-1 w-full rounded-xl border border-slate-200 bg-white px-3 py-2.5 text-sm text-slate-800 outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-100'; ?>
    <section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm"><h2 class="font-bold text-slate-900">Shift Details</h2><div class="mt-5 grid gap-5 md:grid-cols-2 lg:grid-cols-4">
        <label class="text-sm font-semibold text-slate-700">Shift Type *<select name="shift" id="shift-type" required class="<?= $inputClass ?>"><option value="">Select</option><?php foreach ($shiftTypes as $type): ?><option value="<?= h((string)$type['id']) ?>" data-midnight="<?= stripos((string)$type['name'], 'midnight') !== false ? '1' : '0' ?>" <?= (int)$form['shift']===(int)$type['id']?'selected':'' ?>><?= h($type['name']) ?></option><?php endforeach; ?></select></label>
        <label class="text-sm font-semibold text-slate-700">Shift Name *<input name="shift_type" required maxlength="255" value="<?= h((string)$form['shift_type']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Shift Short Name *<input name="shortname" required maxlength="50" value="<?= h((string)$form['shortname']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Total Shift Hours<input id="total-hours" readonly value="<?= h(shift_total_hours((string)$form['in_time'], (string)$form['out_time'])) ?>" class="<?= $inputClass ?> bg-slate-50"></label>
    </div><div class="mt-5"><div class="text-sm font-semibold text-slate-700 mb-2">Terminal Location *</div><div class="grid gap-2 md:grid-cols-2 lg:grid-cols-3"><?php foreach ($terminalOptions as $terminal): ?><label class="flex items-center gap-3 rounded-xl border border-slate-200 px-4 py-3 text-sm"><input type="checkbox" name="orglocation[]" value="<?= h((string)$terminal['id']) ?>" <?= in_array((int)$terminal['id'],$formLocations,true)?'checked':'' ?> class="rounded border-slate-300 text-brand-600"><span><?= h($terminal['name']) ?></span></label><?php endforeach; ?></div></div></section>

    <section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm"><h2 class="font-bold text-slate-900">Attendance Timing</h2><div class="mt-5 grid gap-5 md:grid-cols-2 lg:grid-cols-5">
        <label class="text-sm font-semibold text-slate-700">In Time *<input type="time" name="in_time" id="in-time" required value="<?= h((string)$form['in_time']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">LM Grace (MM) *<input inputmode="numeric" name="in_grace" required value="<?= h((string)$form['in_grace']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Max LM Grace (MM)<input inputmode="numeric" name="max_grace" value="<?= h((string)$form['max_grace']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Out Time *<input type="time" name="out_time" id="out-time" required value="<?= h((string)$form['out_time']) ?>" class="<?= $inputClass ?>"></label>
        <label id="max-out-wrap" class="text-sm font-semibold text-slate-700">Max Out<input type="time" name="max_out" value="<?= h((string)$form['max_out']) ?>" class="<?= $inputClass ?>"></label>
    </div></section>

    <?php if ($cameraFeatureEnabled): ?><section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm"><div class="flex items-center justify-between gap-4"><h2 class="font-bold text-slate-900">Camera Display Windows</h2><label class="text-sm font-semibold">Enable <select name="cameraonof" id="camera-toggle" class="ml-2 rounded-lg border border-slate-200 px-3 py-2"><option value="0" <?= empty($form['cameraonof'])?'selected':'' ?>>No</option><option value="1" <?= !empty($form['cameraonof'])?'selected':'' ?>>Yes</option></select></label></div><div id="camera-fields" class="mt-5 grid gap-5 md:grid-cols-2 lg:grid-cols-4"><?php foreach (['indisplaybefore'=>'In Display Before','indisplayafter'=>'In Display After','outdisplaybefore'=>'Out Display Before','outdisplayafter'=>'Out Display After'] as $field=>$label): ?><label class="text-sm font-semibold text-slate-700"><?= h($label) ?><input type="time" name="<?= h($field) ?>" value="<?= h((string)$form[$field]) ?>" class="<?= $inputClass ?>"></label><?php endforeach; ?></div></section><?php endif; ?>

    <section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm"><div class="flex items-center justify-between"><h2 class="font-bold text-slate-900">Lunch Configuration</h2><label class="text-sm font-semibold">Applicable <select name="lunch_applicable" id="lunch-toggle" class="ml-2 rounded-lg border border-slate-200 px-3 py-2"><option value="0" <?= empty($form['lunch_applicable'])?'selected':'' ?>>No</option><option value="1" <?= !empty($form['lunch_applicable'])?'selected':'' ?>>Yes</option></select></label></div><div id="lunch-fields" class="mt-5 grid gap-5 md:grid-cols-2 lg:grid-cols-4">
        <label class="text-sm font-semibold text-slate-700">Lunch Time (MM)<input inputmode="numeric" name="lunch_time" value="<?= h((string)$form['lunch_time']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Don’t Apply After (HH:MM)<input name="notapplay_time" placeholder="HH:MM" value="<?= h((string)$form['notapplay_time']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Minus From Shift Hours<select name="lunch_minusinshift" class="<?= $inputClass ?>"><option value="0" <?= empty($form['lunch_minusinshift'])?'selected':'' ?>>Yes</option><option value="1" <?= !empty($form['lunch_minusinshift'])?'selected':'' ?>>No</option></select></label>
        <label class="text-sm font-semibold text-slate-700">Minus From Working Hours<select name="lunch_minusinwork" class="<?= $inputClass ?>"><option value="0" <?= empty($form['lunch_minusinwork'])?'selected':'' ?>>Yes</option><option value="1" <?= !empty($form['lunch_minusinwork'])?'selected':'' ?>>No</option></select></label>
        <label class="text-sm font-semibold text-slate-700">Unused Lunch Rule<select name="unused_lunch" class="<?= $inputClass ?>"><option value="0" <?= (int)$form['unused_lunch']===0?'selected':'' ?>>No</option><option value="1" <?= (int)$form['unused_lunch']===1?'selected':'' ?>>Add to Total Hours</option><option value="2" <?= (int)$form['unused_lunch']===2?'selected':'' ?>>Minus From In/Out Pair</option></select></label>
        <label class="text-sm font-semibold text-slate-700">Minimum Hours to Apply Lunch<input id="min-lunch" name="minlt_time" placeholder="HH:MM" value="<?= h((string)$form['minlt_time']) ?>" class="<?= $inputClass ?>"></label>
        <label class="text-sm font-semibold text-slate-700">Lunch Start Time<input id="lunch-start" type="time" name="lunch_in" value="<?= h((string)$form['lunch_in']) ?>" class="<?= $inputClass ?>"></label>
    </div></section>

    <section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm"><h2 class="font-bold text-slate-900">OT and Late Mark</h2><div class="mt-5 grid gap-5 md:grid-cols-2 lg:grid-cols-3"><label class="text-sm font-semibold text-slate-700">OT Category<select name="ot_category" id="ot-category" class="<?= $inputClass ?>"><option value="0" <?= (int)$form['ot_category']===0?'selected':'' ?>>None</option><option value="1" <?= (int)$form['ot_category']===1?'selected':'' ?>>Day OT</option><option value="2" <?= (int)$form['ot_category']===2?'selected':'' ?>>Night OT</option></select></label><label class="text-sm font-semibold text-slate-700">LM Show<select name="lm_show" class="<?= $inputClass ?>"><option value="0" <?= empty($form['lm_show'])?'selected':'' ?>>Yes</option><option value="1" <?= !empty($form['lm_show'])?'selected':'' ?>>No</option></select></label></div>
    <div id="night-fields" class="mt-5 rounded-xl bg-slate-50 p-5"><label class="block max-w-xs text-sm font-semibold text-slate-700">Calculate Night On<select name="night_category" class="<?= $inputClass ?>"><option value="0" <?= (int)$form['night_category']===0?'selected':'' ?>>With All Shifts</option><option value="1" <?= (int)$form['night_category']===1?'selected':'' ?>>Only 1st Shift</option><option value="2" <?= (int)$form['night_category']===2?'selected':'' ?>>Only 2nd Shift</option></select></label><div class="mt-4 grid gap-3 md:grid-cols-2 lg:grid-cols-3"><?php foreach (['night_shift'=>'Consider total hours as Night OT','night_onwff'=>'Night OT on Weekly Off','night_otcount'=>'Calculate Night OT Count','night_ot'=>'Calculate Night OT Hours','night_shiftcount'=>'Calculate Night Shift Count','shiftcount_onwff'=>'Shift Count on Weekly Off'] as $field=>$label): ?><label class="flex items-center gap-3 text-sm font-semibold text-slate-700"><input type="checkbox" name="<?= h($field) ?>" value="1" <?= !empty($form[$field])?'checked':'' ?> class="rounded border-slate-300 text-brand-600"><?= h($label) ?></label><?php endforeach; ?></div></div></section>

    <section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm"><h2 class="font-bold text-slate-900">Shift Configuration</h2><div class="mt-5 grid gap-5 md:grid-cols-2 lg:grid-cols-4"><?php foreach (['minwork_short'=>'Min Work for Short Day','min_worktime'=>'Min Work for Half Day','max_worktime'=>'Max Work for Half Day'] as $field=>$label): ?><label class="text-sm font-semibold text-slate-700"><?= h($label) ?><input name="<?= h($field) ?>" placeholder="HH:MM" value="<?= h((string)$form[$field]) ?>" class="<?= $inputClass ?>"></label><?php endforeach; ?><label class="text-sm font-semibold text-slate-700">Early Logout (Minutes)<input inputmode="numeric" name="early_logouttime" value="<?= h((string)$form['early_logouttime']) ?>" class="<?= $inputClass ?>"></label></div></section>
    <div class="flex justify-end gap-3"><a href="/masters/employee-shifts.php" class="rounded-xl border border-slate-200 bg-white px-5 py-3 text-sm font-bold text-slate-600">Cancel</a><button class="rounded-xl bg-brand-600 px-6 py-3 text-sm font-bold text-white hover:bg-brand-700"><?= $isEditing?'Update':'Save' ?> Employee Shift</button></div>
</form>
<?php else: ?>
<div class="rounded-2xl border border-slate-100 bg-white shadow-sm overflow-hidden">
    <div class="border-b border-slate-100 p-5 flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
        <div><h2 class="text-lg font-bold text-slate-900">Employee Shift List</h2><p class="mt-1 text-xs font-medium text-slate-500">Search and maintain configured employee shifts.</p></div>
        <?php if (!empty($acl['can_add'])): ?><a href="/masters/employee-shifts-progressive.php?mode=add" class="inline-flex items-center justify-center gap-2 rounded-xl bg-brand-600 px-5 py-2.5 text-sm font-bold text-white shadow-sm hover:bg-brand-700"><i class="fa-solid fa-plus"></i>Add</a><?php endif; ?>
    </div>
    <div class="border-b border-slate-100 p-5"><form method="get" class="flex flex-col sm:flex-row gap-3"><input name="q" value="<?= h($search) ?>" placeholder="Search shift name or short name" class="w-full max-w-md rounded-xl border border-slate-200 px-4 py-2.5 text-sm"><button class="rounded-xl bg-slate-900 px-5 py-2.5 text-sm font-bold text-white">Search</button><?php if ($search!==''): ?><a href="/masters/employee-shifts.php" class="rounded-xl border border-slate-200 px-4 py-2.5 text-center text-sm font-bold">Clear</a><?php endif; ?></form></div>
    <div class="overflow-x-auto"><table class="min-w-full text-left text-sm"><thead class="bg-slate-50 text-xs uppercase tracking-wide text-slate-500"><tr><th class="px-5 py-4">Shift</th><th class="px-5 py-4">Timing</th><th class="px-5 py-4">Rules</th><th class="px-5 py-4">Terminals</th><th class="px-5 py-4 text-right">Action</th></tr></thead><tbody class="divide-y divide-slate-100"><?php if (!$shifts): ?><tr><td colspan="5" class="px-5 py-12 text-center text-slate-500">No employee shifts found.</td></tr><?php endif; ?><?php foreach ($shifts as $row): ?><tr class="align-top"><td class="px-5 py-4"><div class="font-bold text-slate-900"><?= h((string)$row['shift_type']) ?></div><div class="mt-1 text-xs text-slate-500"><?= h((string)($row['group_name']??'')) ?> · <?= h((string)$row['shortname']) ?></div><div class="mt-1 text-xs text-brand-600"><?= h((string)($row['shifthrs']??'')) ?></div></td><td class="px-5 py-4 text-slate-700"><div><?= h((string)$row['in_time']) ?> — <?= h((string)$row['out_time']) ?></div><div class="mt-1 text-xs text-slate-500">Grace <?= h((string)$row['in_grace']) ?> min</div></td><td class="px-5 py-4 text-xs text-slate-600"><div>Lunch: <?= !empty($row['lunch_applicable'])?'Yes':'No' ?></div><div>OT: <?= (int)$row['ot_category']===2?'Night OT':((int)$row['ot_category']===1?'Day OT':'None') ?></div><div>Half day: <?= h((string)($row['min_worktimehr']??'—')) ?></div></td><td class="px-5 py-4"><div class="space-y-1"><?php foreach ($row['locations'] as $location): ?><div class="flex items-center gap-2 text-xs"><span class="h-2 w-2 rounded-full <?= (int)$location['status']===1?'bg-emerald-500':'bg-red-400' ?>"></span><?= h((string)$location['name']) ?></div><?php endforeach; ?></div></td><td class="px-5 py-4 text-right"><?php if (!empty($acl['can_edit'])): ?><a href="/masters/employee-shifts-progressive.php?edit=<?= h((string)$row['id']) ?>" class="inline-flex h-9 w-9 items-center justify-center rounded-lg border border-slate-200 text-brand-600 hover:bg-brand-50" title="Edit"><i class="fa-solid fa-pen"></i></a><?php endif; ?></td></tr><?php endforeach; ?></tbody></table></div>
</div>
<?php endif; ?>

<script>
(() => {
  const byId = id => document.getElementById(id);
  const show = (id, visible) => { const el=byId(id); if (el) el.style.display=visible?'':'none'; };
  const refresh = () => {
    show('max-out-wrap', byId('shift-type')?.selectedOptions?.[0]?.dataset?.midnight === '1');
    show('lunch-fields', byId('lunch-toggle')?.value === '1');
    show('camera-fields', byId('camera-toggle')?.value === '1');
    show('night-fields', byId('ot-category')?.value === '2');
  };
  ['shift-type','lunch-toggle','camera-toggle','ot-category'].forEach(id => byId(id)?.addEventListener('change', refresh));
  const total = () => {
    const a=byId('in-time')?.value, b=byId('out-time')?.value, target=byId('total-hours');
    if (!a || !b || !target) return;
    let [ah,am]=a.split(':').map(Number), [bh,bm]=b.split(':').map(Number), mins=(bh*60+bm)-(ah*60+am);
    if (mins<0) mins+=1440;
    target.value=Math.floor(mins/60)+' hrs, '+(mins%60)+'min';
  };
  byId('in-time')?.addEventListener('change', total); byId('out-time')?.addEventListener('change', total);
  byId('min-lunch')?.addEventListener('input', e => { if(e.target.value && byId('lunch-start')) byId('lunch-start').value=''; });
  byId('lunch-start')?.addEventListener('input', e => { if(e.target.value && byId('min-lunch')) byId('min-lunch').value=''; });
  refresh(); total();
})();
</script>
<?php console_footer(); ?>

