<?php
declare(strict_types=1);

// modules/jadwal_orientasi_staf_baru.php
// Versi simple: Penjadwalan Perawat manual + link publik share ke staf.

error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/app.php';

checkAuth();
$conn = function_exists('getAppConnection') ? getAppConnection() : getConnection();

if (!function_exists('e')) {
    function e($v): string
    {
        return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
    }
}

if (!$conn instanceof mysqli) {
    echo "<div class='bg-red-50 border-l-4 border-red-500 p-4 rounded'><p class='text-red-700'>Koneksi database gagal.</p></div>";
    return;
}

$module = 'jadwal_orientasi_staf_baru';
$action = trim((string)($_GET['action'] ?? $_POST['action'] ?? 'list'));
$id = max(0, (int)($_GET['id'] ?? $_POST['id'] ?? 0));
$error = '';
$success = '';

$monthNames = [
    1 => 'Januari', 2 => 'Februari', 3 => 'Maret', 4 => 'April', 5 => 'Mei', 6 => 'Juni',
    7 => 'Juli', 8 => 'Agustus', 9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Desember'
];

function nurseScheduleEnsureTables(mysqli $conn): void
{
    $conn->query("CREATE TABLE IF NOT EXISTS nurse_schedule_periods (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        title VARCHAR(180) NOT NULL,
        unit_name VARCHAR(150) DEFAULT NULL,
        schedule_month TINYINT UNSIGNED NOT NULL,
        schedule_year SMALLINT UNSIGNED NOT NULL,
        token VARCHAR(80) NOT NULL,
        is_public TINYINT(1) NOT NULL DEFAULT 1,
        unit_code_legend TEXT DEFAULT NULL,
        notes TEXT DEFAULT NULL,
        created_by BIGINT UNSIGNED DEFAULT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY uk_nurse_schedule_token (token),
        KEY idx_nurse_schedule_period (schedule_year, schedule_month)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

    $conn->query("CREATE TABLE IF NOT EXISTS nurse_schedule_rows (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        period_id BIGINT UNSIGNED NOT NULL,
        nurse_name VARCHAR(180) NOT NULL,
        position_title VARCHAR(120) DEFAULT NULL,
        sort_order INT UNSIGNED NOT NULL DEFAULT 0,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY idx_nurse_schedule_rows_period (period_id),
        CONSTRAINT fk_nurse_schedule_rows_period FOREIGN KEY (period_id) REFERENCES nurse_schedule_periods(id) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

    $conn->query("CREATE TABLE IF NOT EXISTS nurse_schedule_cells (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        row_id BIGINT UNSIGNED NOT NULL,
        schedule_date DATE NOT NULL,
        shift_code VARCHAR(30) DEFAULT NULL,
        notes VARCHAR(255) DEFAULT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY uk_nurse_schedule_cell (row_id, schedule_date),
        KEY idx_nurse_schedule_cells_date (schedule_date),
        CONSTRAINT fk_nurse_schedule_cells_row FOREIGN KEY (row_id) REFERENCES nurse_schedule_rows(id) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

    nurseScheduleEnsureColumn($conn, 'nurse_schedule_periods', 'unit_code_legend', 'TEXT DEFAULT NULL AFTER is_public');
}

function nurseScheduleToken(): string
{
    try {
        return bin2hex(random_bytes(16));
    } catch (Throwable $e) {
        return sha1(uniqid('jadwal-perawat-', true));
    }
}

function nurseScheduleDefaultUnitLegend(): string
{
    return implode("\n", [
        '1=IGD',
        '2=Canigara',
        '3=Cempaka',
        '4=Cendana',
        '5=Ruang Bayi',
        '6=NICU',
        '7=ICU',
        '8=Kamar Bersalin/VK',
        '9=HD',
        '10=OK/Kamar Operasi',
        '11=Poliklinik',
    ]);
}

function nurseScheduleParseUnitLegend(string $legend): array
{
    $items = [];
    foreach (preg_split('/\r\n|\r|\n/', $legend) as $line) {
        $line = trim((string)$line);
        if ($line === '') {
            continue;
        }
        $parts = preg_split('/\s*=\s*/', $line, 2);
        if (count($parts) === 2) {
            $items[] = ['code' => trim($parts[0]), 'unit' => trim($parts[1])];
        } else {
            $items[] = ['code' => '', 'unit' => $line];
        }
    }
    return $items;
}

function nurseScheduleEnsureColumn(mysqli $conn, string $table, string $column, string $definition): void
{
    $tableSafe = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
    $columnSafe = preg_replace('/[^a-zA-Z0-9_]/', '', $column);
    $res = $conn->query("SHOW COLUMNS FROM `{$tableSafe}` LIKE '{$columnSafe}'");
    if ($res && $res->num_rows > 0) {
        return;
    }
    $conn->query("ALTER TABLE `{$tableSafe}` ADD COLUMN `{$columnSafe}` {$definition}");
}

function nurseScheduleCurrentUserId(mysqli $conn): ?int
{
    $direct = (int)($_SESSION['user_id'] ?? ($_SESSION['user']['id'] ?? 0));
    if ($direct > 0) {
        return $direct;
    }

    $employeeId = (int)($_SESSION['user']['employee_id'] ?? $_SESSION['employee_id'] ?? 0);
    if ($employeeId > 0) {
        $stmt = $conn->prepare('SELECT id FROM users WHERE employee_id = ? LIMIT 1');
        if ($stmt) {
            $stmt->bind_param('i', $employeeId);
            $stmt->execute();
            $res = $stmt->get_result();
            $row = $res ? $res->fetch_assoc() : null;
            $stmt->close();
            if ($row && (int)$row['id'] > 0) {
                return (int)$row['id'];
            }
        }
    }
    return null;
}

function nurseSchedulePublicUrl(string $token): string
{
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (($_SERVER['SERVER_PORT'] ?? '') === '443');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    return $scheme . '://' . $host . '/jadwal_perawat_public.php?t=' . urlencode($token);
}

function nurseScheduleGetPeriod(mysqli $conn, int $id): ?array
{
    $stmt = $conn->prepare('SELECT * FROM nurse_schedule_periods WHERE id = ? LIMIT 1');
    if (!$stmt) {
        return null;
    }
    $stmt->bind_param('i', $id);
    $stmt->execute();
    $res = $stmt->get_result();
    $row = $res ? $res->fetch_assoc() : null;
    $stmt->close();
    return $row ?: null;
}

function nurseScheduleLoadRows(mysqli $conn, int $periodId): array
{
    $rows = [];
    $stmt = $conn->prepare('SELECT * FROM nurse_schedule_rows WHERE period_id = ? ORDER BY sort_order ASC, id ASC');
    if ($stmt) {
        $stmt->bind_param('i', $periodId);
        $stmt->execute();
        $res = $stmt->get_result();
        while ($res && ($row = $res->fetch_assoc())) {
            $row['cells'] = [];
            $rows[(int)$row['id']] = $row;
        }
        $stmt->close();
    }

    if ($rows) {
        $ids = implode(',', array_map('intval', array_keys($rows)));
        $res = $conn->query("SELECT * FROM nurse_schedule_cells WHERE row_id IN ({$ids}) ORDER BY schedule_date ASC");
        while ($res && ($cell = $res->fetch_assoc())) {
            $day = (int)date('j', strtotime((string)$cell['schedule_date']));
            $rows[(int)$cell['row_id']]['cells'][$day] = $cell;
        }
    }

    return array_values($rows);
}

nurseScheduleEnsureTables($conn);

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'save') {
    $title = trim((string)($_POST['title'] ?? ''));
    $unitName = trim((string)($_POST['unit_name'] ?? ''));
    $month = max(1, min(12, (int)($_POST['schedule_month'] ?? date('n'))));
    $year = max(2024, min(2100, (int)($_POST['schedule_year'] ?? date('Y'))));
    $unitCodeLegend = trim((string)($_POST['unit_code_legend'] ?? ''));
    if ($unitCodeLegend === '') {
        $unitCodeLegend = nurseScheduleDefaultUnitLegend();
    }
    $notes = trim((string)($_POST['notes'] ?? ''));
    $isPublic = isset($_POST['is_public']) ? 1 : 0;
    $nurseNames = $_POST['nurse_name'] ?? [];
    $positions = $_POST['position_title'] ?? [];
    $cells = $_POST['cells'] ?? [];
    $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

    if ($title === '') {
        $title = 'Jadwal Dinas Perawat ' . ($monthNames[$month] ?? '') . ' ' . $year;
    }

    $validNames = [];
    foreach ((array)$nurseNames as $idx => $name) {
        $name = trim((string)$name);
        if ($name !== '') {
            $validNames[(int)$idx] = $name;
        }
    }

    if (!$validNames) {
        $error = 'Minimal isi 1 nama perawat/bidan.';
    } else {
        try {
            $conn->begin_transaction();
            $createdBy = nurseScheduleCurrentUserId($conn);

            $shouldInsertNewPeriod = true;
            $periodId = 0;

            if ($id > 0) {
                $period = nurseScheduleGetPeriod($conn, $id);
                if (!$period) {
                    throw new RuntimeException('Periode jadwal tidak ditemukan.');
                }

                // Penting: kalau bulan/tahun diganti dari jadwal lama, jangan UPDATE jadwal lama.
                // Contoh edit Mei lalu pindah ke Juni => Mei harus tetap ada, Juni dibuat sebagai jadwal baru.
                $oldMonth = (int)($period['schedule_month'] ?? 0);
                $oldYear = (int)($period['schedule_year'] ?? 0);
                $samePeriod = ($oldMonth === $month && $oldYear === $year);

                if ($samePeriod) {
                    $stmt = $conn->prepare('UPDATE nurse_schedule_periods SET title=?, unit_name=?, schedule_month=?, schedule_year=?, is_public=?, unit_code_legend=?, notes=? WHERE id=?');
                    if (!$stmt) {
                        throw new RuntimeException('Prepare update periode gagal: ' . $conn->error);
                    }
                    $stmt->bind_param('ssiiissi', $title, $unitName, $month, $year, $isPublic, $unitCodeLegend, $notes, $id);
                    $stmt->execute();
                    $stmt->close();

                    // Hanya hapus/rebuild baris untuk periode yang memang sedang diedit.
                    $stmtDel = $conn->prepare('DELETE FROM nurse_schedule_rows WHERE period_id = ?');
                    if (!$stmtDel) {
                        throw new RuntimeException('Prepare hapus baris gagal: ' . $conn->error);
                    }
                    $stmtDel->bind_param('i', $id);
                    $stmtDel->execute();
                    $stmtDel->close();

                    $periodId = $id;
                    $shouldInsertNewPeriod = false;
                }
            }

            if ($shouldInsertNewPeriod) {
                $token = nurseScheduleToken();
                if ($createdBy !== null) {
                    $stmt = $conn->prepare('INSERT INTO nurse_schedule_periods (title, unit_name, schedule_month, schedule_year, token, is_public, unit_code_legend, notes, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
                    if (!$stmt) {
                        throw new RuntimeException('Prepare insert periode gagal: ' . $conn->error);
                    }
                    $stmt->bind_param('ssiisissi', $title, $unitName, $month, $year, $token, $isPublic, $unitCodeLegend, $notes, $createdBy);
                } else {
                    $stmt = $conn->prepare('INSERT INTO nurse_schedule_periods (title, unit_name, schedule_month, schedule_year, token, is_public, unit_code_legend, notes, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)');
                    if (!$stmt) {
                        throw new RuntimeException('Prepare insert periode gagal: ' . $conn->error);
                    }
                    $stmt->bind_param('ssiisiss', $title, $unitName, $month, $year, $token, $isPublic, $unitCodeLegend, $notes);
                }
                $stmt->execute();
                $periodId = (int)$conn->insert_id;
                $stmt->close();
            }

            $stmtRow = $conn->prepare('INSERT INTO nurse_schedule_rows (period_id, nurse_name, position_title, sort_order) VALUES (?, ?, ?, ?)');
            $stmtCell = $conn->prepare('INSERT INTO nurse_schedule_cells (row_id, schedule_date, shift_code, notes) VALUES (?, ?, ?, ?)');
            if (!$stmtRow || !$stmtCell) {
                throw new RuntimeException('Prepare simpan baris/sel gagal: ' . $conn->error);
            }

            $order = 1;
            foreach ($validNames as $idx => $name) {
                $position = trim((string)($positions[$idx] ?? ''));
                $stmtRow->bind_param('issi', $periodId, $name, $position, $order);
                $stmtRow->execute();
                $rowId = (int)$conn->insert_id;

                for ($day = 1; $day <= $daysInMonth; $day++) {
                    $shift = strtoupper(trim((string)($cells[$idx][$day]['shift'] ?? '')));
                    $cellNote = trim((string)($cells[$idx][$day]['notes'] ?? ''));
                    if ($shift === '' && $cellNote === '') {
                        continue;
                    }
                    $scheduleDate = sprintf('%04d-%02d-%02d', $year, $month, $day);
                    $stmtCell->bind_param('isss', $rowId, $scheduleDate, $shift, $cellNote);
                    $stmtCell->execute();
                }
                $order++;
            }
            $stmtRow->close();
            $stmtCell->close();

            $conn->commit();
            $success = $shouldInsertNewPeriod && $id > 0 ? 'Jadwal bulan baru berhasil dibuat. Jadwal bulan lama tetap tersimpan.' : 'Jadwal berhasil disimpan.';
            $action = 'edit';
            $id = $periodId;
        } catch (Throwable $e) {
            $conn->rollback();
            $error = 'Gagal menyimpan jadwal: ' . $e->getMessage();
        }
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'delete' && $id > 0) {
    try {
        $stmt = $conn->prepare('DELETE FROM nurse_schedule_periods WHERE id = ?');
        if (!$stmt) {
            throw new RuntimeException($conn->error);
        }
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $stmt->close();
        echo "<script>alert('Jadwal berhasil dihapus.'); window.location.href='?module={$module}';</script>";
        exit;
    } catch (Throwable $e) {
        $error = 'Gagal menghapus jadwal: ' . $e->getMessage();
    }
}

if ($action === 'toggle_public' && $id > 0) {
    $stmt = $conn->prepare('UPDATE nurse_schedule_periods SET is_public = IF(is_public=1,0,1) WHERE id = ?');
    if ($stmt) {
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $stmt->close();
    }
    echo "<script>window.location.href='?module={$module}';</script>";
    exit;
}

$period = null;
$rows = [];
$month = (int)date('n');
$year = (int)date('Y');
$daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

if (in_array($action, ['create', 'edit'], true)) {
    if ($id > 0) {
        $period = nurseScheduleGetPeriod($conn, $id);
        if ($period) {
            $month = (int)$period['schedule_month'];
            $year = (int)$period['schedule_year'];
            $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
            $rows = nurseScheduleLoadRows($conn, $id);
        } else {
            $error = 'Data jadwal tidak ditemukan.';
            $action = 'list';
        }
    } else {
        $month = max(1, min(12, (int)($_GET['month'] ?? date('n'))));
        $year = max(2024, min(2100, (int)($_GET['year'] ?? date('Y'))));
        $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
        $rows = [];
    }
}

$periods = [];
$res = $conn->query('SELECT * FROM nurse_schedule_periods ORDER BY schedule_year DESC, schedule_month DESC, id DESC');
while ($res && ($row = $res->fetch_assoc())) {
    $periods[] = $row;
}

$defaultRowCount = max(8, count($rows) + 2);
?>
<div class="max-w-7xl mx-auto space-y-6">
    <div class="rounded-3xl overflow-hidden shadow-lg bg-gradient-to-r from-blue-700 via-indigo-700 to-cyan-600 text-white">
        <div class="p-6 md:p-8 flex flex-col lg:flex-row lg:items-center lg:justify-between gap-5">
            <div>
                <p class="uppercase tracking-[.25em] text-blue-100 text-xs font-semibold">RS BaliMéd Denpasar</p>
                <h1 class="text-2xl md:text-4xl font-extrabold mt-2">Penjadwalan Perawat Simple</h1>
                <p class="mt-2 text-blue-100">Input nama manual, isi kode jaga langsung di tanggal, lalu bagikan link publik ke staf.</p>
            </div>
            <div class="flex flex-wrap gap-3">
                <a href="?module=<?= e($module) ?>" class="px-4 py-3 rounded-2xl bg-white/15 hover:bg-white/25 border border-white/20 font-semibold">Daftar Jadwal</a>
                <a href="?module=<?= e($module) ?>&action=create" class="px-4 py-3 rounded-2xl bg-white text-blue-700 hover:bg-blue-50 font-semibold shadow">+ Buat Jadwal</a>
            </div>
        </div>
    </div>

    <?php if ($error !== ''): ?>
        <div class="rounded-2xl border border-red-200 bg-red-50 px-5 py-4 text-red-700 font-medium"><?= e($error) ?></div>
    <?php endif; ?>
    <?php if ($success !== ''): ?>
        <div class="rounded-2xl border border-green-200 bg-green-50 px-5 py-4 text-green-700 font-medium"><?= e($success) ?></div>
    <?php endif; ?>

    <?php if ($action === 'list'): ?>
        <div class="bg-white rounded-3xl shadow border border-gray-100 overflow-hidden">
            <div class="p-5 md:p-6 border-b border-gray-100 flex flex-col md:flex-row md:items-center md:justify-between gap-3">
                <div>
                    <h2 class="text-xl font-bold text-gray-800">Tabel Jadwal Orientasi/Perawat yang Pernah Dibuat</h2>
                    <p class="text-sm text-gray-500 mt-1">Semua jadwal yang sudah dibuat muncul di sini, bisa dibuka ulang, diedit, atau link publiknya dishare ke staf.</p>
                </div>
                <a href="?module=<?= e($module) ?>&action=create" class="inline-flex items-center justify-center px-5 py-3 rounded-xl bg-blue-600 text-white hover:bg-blue-700 font-semibold">Buat Jadwal Baru</a>
            </div>
            <div class="overflow-auto">
                <table class="w-full min-w-[1000px] text-sm">
                    <thead class="bg-slate-900 text-white">
                        <tr>
                            <th class="p-3 text-left">Judul</th>
                            <th class="p-3 text-left">Unit</th>
                            <th class="p-3 text-center">Bulan</th>
                            <th class="p-3 text-center">Publik</th>
                            <th class="p-3 text-left">Link Share</th>
                            <th class="p-3 text-center">Aksi</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php if (!$periods): ?>
                            <tr><td colspan="6" class="p-8 text-center text-gray-500">Belum ada jadwal. Klik <strong>Buat Jadwal Baru</strong>.</td></tr>
                        <?php endif; ?>
                        <?php foreach ($periods as $p): ?>
                            <?php $url = nurseSchedulePublicUrl((string)$p['token']); ?>
                            <tr class="border-b border-gray-100 hover:bg-blue-50/40">
                                <td class="p-3 font-semibold text-gray-800"><?= e($p['title']) ?></td>
                                <td class="p-3"><?= e($p['unit_name'] ?: '-') ?></td>
                                <td class="p-3 text-center"><?= e(($monthNames[(int)$p['schedule_month']] ?? '-') . ' ' . $p['schedule_year']) ?></td>
                                <td class="p-3 text-center">
                                    <span class="inline-flex px-3 py-1 rounded-full text-xs font-bold <?= (int)$p['is_public'] === 1 ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700' ?>"><?= (int)$p['is_public'] === 1 ? 'Aktif' : 'Nonaktif' ?></span>
                                </td>
                                <td class="p-3">
                                    <div class="flex gap-2 items-center">
                                        <input readonly value="<?= e($url) ?>" class="public-url w-full rounded-xl border-gray-300 bg-gray-50 text-xs">
                                        <button type="button" onclick="copyText(this)" class="px-3 py-2 rounded-xl bg-slate-800 text-white text-xs font-semibold">Copy</button>
                                    </div>
                                </td>
                                <td class="p-3">
                                    <div class="flex flex-wrap justify-center gap-2">
                                        <a href="?module=<?= e($module) ?>&action=edit&id=<?= (int)$p['id'] ?>" class="px-3 py-2 rounded-xl bg-blue-600 text-white text-xs font-semibold">Edit</a>
                                        <a target="_blank" href="<?= e($url) ?>" class="px-3 py-2 rounded-xl bg-indigo-600 text-white text-xs font-semibold">Lihat Publik</a>
                                        <a href="?module=<?= e($module) ?>&action=toggle_public&id=<?= (int)$p['id'] ?>" class="px-3 py-2 rounded-xl border border-gray-300 text-gray-700 text-xs font-semibold">On/Off</a>
                                        <form method="post" action="?module=<?= e($module) ?>&action=delete&id=<?= (int)$p['id'] ?>" onsubmit="return confirm('Hapus jadwal ini?')" class="inline">
                                            <button class="px-3 py-2 rounded-xl bg-red-600 text-white text-xs font-semibold">Hapus</button>
                                        </form>
                                    </div>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        </div>
    <?php else: ?>
        <?php if ($periods): ?>
            <div class="bg-white rounded-3xl shadow border border-gray-100 overflow-hidden">
                <div class="p-5 border-b border-gray-100 flex flex-col md:flex-row md:items-center md:justify-between gap-3">
                    <div>
                        <h2 class="text-lg font-bold text-gray-800">Jadwal Orientasi/Perawat yang Pernah Dibuat</h2>
                        <p class="text-sm text-gray-500 mt-1">Klik edit untuk membuka jadwal lama tanpa membuat ulang dari awal.</p>
                    </div>
                    <a href="?module=<?= e($module) ?>" class="px-4 py-2 rounded-xl border border-gray-300 text-gray-700 font-semibold hover:bg-gray-50">Lihat Semua</a>
                </div>
                <div class="overflow-auto">
                    <table class="w-full min-w-[820px] text-sm">
                        <thead class="bg-gray-50 text-gray-700">
                            <tr>
                                <th class="p-3 text-left">Judul</th>
                                <th class="p-3 text-center">Bulan</th>
                                <th class="p-3 text-left">Unit</th>
                                <th class="p-3 text-center">Publik</th>
                                <th class="p-3 text-center">Aksi</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach (array_slice($periods, 0, 5) as $p): ?>
                                <tr class="border-b border-gray-100 hover:bg-blue-50/40 <?= (int)$p['id'] === (int)$id ? 'bg-blue-50' : '' ?>">
                                    <td class="p-3 font-semibold text-gray-800"><?= e($p['title']) ?></td>
                                    <td class="p-3 text-center"><?= e(($monthNames[(int)$p['schedule_month']] ?? '-') . ' ' . $p['schedule_year']) ?></td>
                                    <td class="p-3"><?= e($p['unit_name'] ?: '-') ?></td>
                                    <td class="p-3 text-center"><?= (int)$p['is_public'] === 1 ? '<span class="text-green-700 font-bold">Aktif</span>' : '<span class="text-red-700 font-bold">Nonaktif</span>' ?></td>
                                    <td class="p-3 text-center">
                                        <a href="?module=<?= e($module) ?>&action=edit&id=<?= (int)$p['id'] ?>" class="px-3 py-2 rounded-xl bg-blue-600 text-white text-xs font-semibold">Edit</a>
                                    </td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        <?php endif; ?>
        <form method="post" action="?module=<?= e($module) ?>&action=save<?= $id > 0 ? '&id=' . (int)$id : '' ?>" class="space-y-6" id="scheduleForm">
            <input type="hidden" name="id" value="<?= (int)$id ?>">
            <div class="bg-white rounded-3xl shadow border border-gray-100 p-5 md:p-6">
                <h2 class="text-xl font-bold text-gray-800 mb-4"><?= $id > 0 ? 'Edit Jadwal' : 'Buat Jadwal Baru' ?></h2>
                <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4">
                    <div class="lg:col-span-2">
                        <label class="block text-sm font-semibold text-gray-700 mb-1">Judul Jadwal</label>
                        <input name="title" value="<?= e($period['title'] ?? ('Jadwal Dinas Perawat ' . $monthNames[$month] . ' ' . $year)) ?>" class="w-full rounded-xl border-gray-300 focus:ring-blue-500 focus:border-blue-500" required>
                    </div>
                    <div>
                        <label class="block text-sm font-semibold text-gray-700 mb-1">Unit/Ruangan</label>
                        <input name="unit_name" value="<?= e($period['unit_name'] ?? '') ?>" placeholder="Contoh: IGD / Rawat Inap" class="w-full rounded-xl border-gray-300 focus:ring-blue-500 focus:border-blue-500">
                    </div>
                    <div>
                        <label class="block text-sm font-semibold text-gray-700 mb-1">Bulan</label>
                        <select name="schedule_month" id="scheduleMonth" class="w-full rounded-xl border-gray-300 focus:ring-blue-500 focus:border-blue-500">
                            <?php foreach ($monthNames as $num => $label): ?>
                                <option value="<?= $num ?>" <?= $month === $num ? 'selected' : '' ?>><?= e($label) ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div>
                        <label class="block text-sm font-semibold text-gray-700 mb-1">Tahun</label>
                        <input type="number" name="schedule_year" id="scheduleYear" value="<?= (int)$year ?>" min="2024" max="2100" class="w-full rounded-xl border-gray-300 focus:ring-blue-500 focus:border-blue-500">
                    </div>
                </div>
                <div class="mt-3 rounded-2xl bg-amber-50 border border-amber-100 px-4 py-3 text-sm text-amber-800">
                    Saat bulan/tahun diganti, <strong>nama perawat tetap</strong>, sedangkan <strong>kolom tanggal otomatis berubah</strong> mengikuti jumlah hari pada bulan tersebut. Kode jaga bulan baru akan kosong agar tidak salah jadwal.
                </div>
                <div class="mt-4 grid grid-cols-1 lg:grid-cols-3 gap-4">
                    <div>
                        <label class="block text-sm font-semibold text-gray-700 mb-1">Catatan Umum</label>
                        <input name="notes" value="<?= e($period['notes'] ?? '') ?>" placeholder="Contoh: Jadwal dapat berubah sewaktu-waktu" class="w-full rounded-xl border-gray-300 focus:ring-blue-500 focus:border-blue-500">
                    </div>
                    <div>
                        <label class="block text-sm font-semibold text-gray-700 mb-1">Keterangan Kode Unit</label>
                        <textarea name="unit_code_legend" rows="5" placeholder="1=IGD&#10;2=Canigara" class="w-full rounded-xl border-gray-300 focus:ring-blue-500 focus:border-blue-500 text-sm"><?= e($period['unit_code_legend'] ?? nurseScheduleDefaultUnitLegend()) ?></textarea>
                        <p class="text-xs text-gray-500 mt-1">Format satu baris satu kode. Contoh: <strong>1=IGD</strong>. Maka <strong>P1</strong> dibaca Pagi IGD.</p>
                    </div>
                    <label class="flex items-center gap-3 rounded-2xl border border-gray-200 px-4 py-3 bg-gray-50 mt-0 lg:mt-6 self-start">
                        <input type="checkbox" name="is_public" value="1" <?= !isset($period) || (int)($period['is_public'] ?? 1) === 1 ? 'checked' : '' ?> class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
                        <span class="font-semibold text-gray-700">Link publik aktif</span>
                    </label>
                </div>
                <div class="mt-4 rounded-2xl bg-indigo-50 border border-indigo-100 p-4">
                    <div class="text-sm font-bold text-indigo-800 mb-2">Cara membaca kode jadwal</div>
                    <div class="grid grid-cols-1 md:grid-cols-3 gap-2 text-sm text-indigo-900">
                        <div><strong>P1</strong> = Pagi IGD</div>
                        <div><strong>S2</strong> = Sore Canigara</div>
                        <div><strong>M7</strong> = Malam ICU</div>
                    </div>
                </div>
                <?php if ($period): ?>
                    <div class="mt-4 rounded-2xl bg-blue-50 border border-blue-100 p-4">
                        <div class="text-sm font-semibold text-blue-800 mb-2">Link publik untuk dibagikan ke staf</div>
                        <div class="flex gap-2">
                            <input readonly value="<?= e(nurseSchedulePublicUrl((string)$period['token'])) ?>" class="public-url w-full rounded-xl border-blue-200 bg-white text-sm">
                            <button type="button" onclick="copyText(this)" class="px-4 py-2 rounded-xl bg-blue-700 text-white font-semibold">Copy</button>
                            <a target="_blank" href="<?= e(nurseSchedulePublicUrl((string)$period['token'])) ?>" class="px-4 py-2 rounded-xl bg-slate-900 text-white font-semibold whitespace-nowrap">Buka</a>
                        </div>
                    </div>
                <?php endif; ?>
            </div>

            <div class="bg-white rounded-3xl shadow border border-gray-100 overflow-hidden">
                <div class="p-5 border-b border-gray-100 flex flex-col lg:flex-row lg:items-center lg:justify-between gap-3">
                    <div>
                        <h3 class="text-lg font-bold text-gray-800">Grid Jadwal Manual</h3>
                        <p class="text-sm text-gray-500">Nama perawat diisi manual. Kode jaga bebas, misalnya <strong>P1</strong> = pagi unit kode 1, <strong>S2</strong> = sore unit kode 2, <strong>M7</strong> = malam unit kode 7, <strong>L</strong>, <strong>OFF</strong>, <strong>CT</strong>. Kolom kecil di bawah kode bersifat catatan opsional.</p>
                    </div>
                    <div class="flex flex-wrap gap-2">
                        <button type="button" onclick="addScheduleRow()" class="px-4 py-2 rounded-xl border border-blue-600 text-blue-700 font-semibold hover:bg-blue-50">+ Tambah Baris</button>
                        <button type="submit" class="px-5 py-2 rounded-xl bg-green-600 text-white font-semibold hover:bg-green-700">Simpan Jadwal</button>
                    </div>
                </div>
                <div class="overflow-auto">
                    <table class="min-w-[2200px] w-full text-xs md:text-sm border-collapse" id="scheduleTable">
                        <thead class="bg-slate-900 text-white sticky top-0">
                            <tr>
                                <th class="border border-slate-700 px-3 py-3 text-left sticky left-0 bg-slate-900 z-20 min-w-[260px]">Nama Perawat/Bidan</th>
                                <th class="border border-slate-700 px-3 py-3 text-left min-w-[150px]">Keterangan/Jabatan</th>
                                <?php for ($day = 1; $day <= $daysInMonth; $day++): ?>
                                    <th class="border border-slate-700 px-2 py-3 text-center min-w-[76px]"><?= $day ?></th>
                                <?php endfor; ?>
                                <th class="border border-slate-700 px-2 py-3 text-center min-w-[80px]">Aksi</th>
                            </tr>
                        </thead>
                        <tbody id="scheduleBody">
                            <?php for ($r = 0; $r < $defaultRowCount; $r++): ?>
                                <?php $row = $rows[$r] ?? ['nurse_name' => '', 'position_title' => '', 'cells' => []]; ?>
                                <tr class="schedule-row odd:bg-white even:bg-gray-50">
                                    <td class="border border-gray-200 p-2 sticky left-0 bg-inherit z-10">
                                        <input name="nurse_name[<?= $r ?>]" value="<?= e($row['nurse_name'] ?? '') ?>" placeholder="Nama perawat/bidan" class="w-full rounded-lg border-gray-300 text-sm font-semibold">
                                    </td>
                                    <td class="border border-gray-200 p-2">
                                        <input name="position_title[<?= $r ?>]" value="<?= e($row['position_title'] ?? '') ?>" placeholder="Opsional" class="w-full rounded-lg border-gray-300 text-xs">
                                    </td>
                                    <?php for ($day = 1; $day <= $daysInMonth; $day++): ?>
                                        <?php $cell = $row['cells'][$day] ?? ['shift_code' => '', 'notes' => '']; ?>
                                        <td class="border border-gray-200 p-1 align-top">
                                            <input name="cells[<?= $r ?>][<?= $day ?>][shift]" value="<?= e($cell['shift_code'] ?? '') ?>" placeholder="-" class="w-full rounded-md border-gray-300 text-center text-xs font-bold uppercase">
                                            <input name="cells[<?= $r ?>][<?= $day ?>][notes]" value="<?= e($cell['notes'] ?? '') ?>" placeholder="ctt" class="mt-1 w-full rounded-md border-gray-200 text-[10px] text-center">
                                        </td>
                                    <?php endfor; ?>
                                    <td class="border border-gray-200 p-2 text-center">
                                        <button type="button" onclick="removeScheduleRow(this)" class="px-3 py-2 rounded-lg bg-red-50 text-red-700 text-xs font-semibold">Hapus</button>
                                    </td>
                                </tr>
                            <?php endfor; ?>
                        </tbody>
                    </table>
                </div>
                <div class="p-5 border-t border-gray-100 flex flex-col md:flex-row md:items-center md:justify-between gap-3">
                    <div class="text-sm text-gray-500">Tips: biarkan nama kosong jika baris tidak dipakai. Saat simpan, baris kosong otomatis diabaikan.</div>
                    <button type="submit" class="px-6 py-3 rounded-xl bg-green-600 text-white font-semibold hover:bg-green-700 shadow">Simpan Jadwal</button>
                </div>
            </div>
        </form>
    <?php endif; ?>
</div>

<script>
function copyText(btn) {
    const wrap = btn.closest('div');
    const input = wrap ? wrap.querySelector('.public-url') : null;
    if (!input) return;
    input.select();
    input.setSelectionRange(0, 99999);
    navigator.clipboard?.writeText(input.value).then(function () {
        btn.textContent = 'Copied';
        setTimeout(function(){ btn.textContent = 'Copy'; }, 1200);
    }).catch(function(){
        document.execCommand('copy');
        btn.textContent = 'Copied';
        setTimeout(function(){ btn.textContent = 'Copy'; }, 1200);
    });
}

const scheduleMonthNames = <?= json_encode($monthNames, JSON_UNESCAPED_UNICODE) ?>;
let activeScheduleKey = String(document.getElementById('scheduleYear')?.value || '<?= (int)$year ?>') + '-' + String(document.getElementById('scheduleMonth')?.value || '<?= (int)$month ?>').padStart(2, '0');
const scheduleCache = {};
let titleAutoMode = true;

function daysInMonth(month, year) {
    return new Date(parseInt(year, 10), parseInt(month, 10), 0).getDate();
}

function getScheduleKey() {
    const m = String(document.getElementById('scheduleMonth')?.value || '<?= (int)$month ?>').padStart(2, '0');
    const y = String(document.getElementById('scheduleYear')?.value || '<?= (int)$year ?>');
    return y + '-' + m;
}

function getRowIndex(row) {
    const nameInput = row.querySelector('input[name^="nurse_name["]');
    const match = nameInput ? nameInput.name.match(/nurse_name\[(\d+)\]/) : null;
    return match ? parseInt(match[1], 10) : 0;
}

function captureCurrentScheduleCells() {
    const body = document.getElementById('scheduleBody');
    if (!body) return;
    const data = {};
    body.querySelectorAll('tr.schedule-row').forEach(function(row){
        const idx = getRowIndex(row);
        data[idx] = {};
        row.querySelectorAll('input[name^="cells["]').forEach(function(input){
            const match = input.name.match(/cells\[(\d+)\]\[(\d+)\]\[(shift|notes)\]/);
            if (!match) return;
            const day = parseInt(match[2], 10);
            const field = match[3];
            if (!data[idx][day]) data[idx][day] = {shift: '', notes: ''};
            data[idx][day][field] = input.value;
        });
    });
    scheduleCache[activeScheduleKey] = data;
}

function createDayHeader(day) {
    const th = document.createElement('th');
    th.className = 'border border-slate-700 px-2 py-3 text-center min-w-[76px]';
    th.textContent = day;
    return th;
}

function createDayCell(rowIdx, day, value) {
    const td = document.createElement('td');
    td.className = 'border border-gray-200 p-1 align-top';
    const shift = document.createElement('input');
    shift.name = 'cells[' + rowIdx + '][' + day + '][shift]';
    shift.value = (value && value.shift) ? value.shift : '';
    shift.placeholder = '-';
    shift.className = 'w-full rounded-md border-gray-300 text-center text-xs font-bold uppercase';
    const notes = document.createElement('input');
    notes.name = 'cells[' + rowIdx + '][' + day + '][notes]';
    notes.value = (value && value.notes) ? value.notes : '';
    notes.placeholder = 'ctt';
    notes.className = 'mt-1 w-full rounded-md border-gray-200 text-[10px] text-center';
    td.appendChild(shift);
    td.appendChild(notes);
    return td;
}

function rebuildScheduleDays() {
    const table = document.getElementById('scheduleTable');
    const body = document.getElementById('scheduleBody');
    const monthEl = document.getElementById('scheduleMonth');
    const yearEl = document.getElementById('scheduleYear');
    if (!table || !body || !monthEl || !yearEl) return;

    captureCurrentScheduleCells();
    const month = parseInt(monthEl.value, 10);
    const year = parseInt(yearEl.value, 10);
    const newKey = getScheduleKey();
    const dayCount = daysInMonth(month, year);
    const cached = scheduleCache[newKey] || {};

    const headerRow = table.querySelector('thead tr');
    while (headerRow.children.length > 3) {
        headerRow.removeChild(headerRow.children[2]);
    }
    const actionHeader = headerRow.lastElementChild;
    for (let day = 1; day <= dayCount; day++) {
        headerRow.insertBefore(createDayHeader(day), actionHeader);
    }

    body.querySelectorAll('tr.schedule-row').forEach(function(row){
        const idx = getRowIndex(row);
        while (row.children.length > 3) {
            row.removeChild(row.children[2]);
        }
        const actionCell = row.lastElementChild;
        for (let day = 1; day <= dayCount; day++) {
            row.insertBefore(createDayCell(idx, day, cached[idx] ? cached[idx][day] : null), actionCell);
        }
    });

    activeScheduleKey = newKey;
    updateTitleForMonthYear(month, year);
}

function updateTitleForMonthYear(month, year) {
    const titleInput = document.querySelector('input[name="title"]');
    if (!titleInput || !titleAutoMode) return;
    titleInput.value = 'Jadwal Dinas Perawat ' + (scheduleMonthNames[month] || '') + ' ' + year;
}

function nextRowIndex() {
    let max = -1;
    document.querySelectorAll('#scheduleBody input[name^="nurse_name["]').forEach(function(input){
        const m = input.name.match(/nurse_name\[(\d+)\]/);
        if (m) max = Math.max(max, parseInt(m[1], 10));
    });
    return max + 1;
}

function addScheduleRow() {
    const body = document.getElementById('scheduleBody');
    const first = body ? body.querySelector('tr.schedule-row') : null;
    if (!body || !first) return;
    captureCurrentScheduleCells();
    const idx = nextRowIndex();
    const clone = first.cloneNode(true);
    clone.querySelectorAll('input').forEach(function(input){
        input.value = '';
        input.name = input.name
            .replace(/nurse_name\[\d+\]/, 'nurse_name[' + idx + ']')
            .replace(/position_title\[\d+\]/, 'position_title[' + idx + ']')
            .replace(/cells\[\d+\]/, 'cells[' + idx + ']');
    });
    body.appendChild(clone);
}

function removeScheduleRow(btn) {
    const row = btn.closest('tr');
    const body = document.getElementById('scheduleBody');
    if (!row || !body) return;
    if (body.querySelectorAll('tr.schedule-row').length <= 1) {
        row.querySelectorAll('input').forEach(function(input){ input.value = ''; });
        return;
    }
    row.remove();
}

(function initScheduleMonthSwitcher(){
    const monthEl = document.getElementById('scheduleMonth');
    const yearEl = document.getElementById('scheduleYear');
    const titleInput = document.querySelector('input[name="title"]');
    if (titleInput) {
        titleInput.addEventListener('input', function(){ titleAutoMode = false; });
    }
    if (monthEl) monthEl.addEventListener('change', rebuildScheduleDays);
    if (yearEl) yearEl.addEventListener('change', rebuildScheduleDays);
})();
</script>
