<?php
session_start();
date_default_timezone_set('Africa/Lagos');
require __DIR__ . '/../config.php';
require __DIR__ . '/includes/auth_init.php';
require __DIR__ . '/includes/PayrollEngine.php';
require __DIR__ . '/includes/approval_notify.php';

if (!$isAdmin) {
    $_SESSION['flash_error'] = "You don't have permission to manage payroll cycles.";
    header("Location: dashboard.php");
    exit;
}

// Release the session lock on plain page views; the POST branches below still
// need to write flash data, so they keep the session open for themselves.
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    session_write_close();
}

$isSuperAdmin = strtolower(trim($role)) === 'superadmin';

// -----------------------------------------------------------------------------
// FETCH DEFAULT PAYROLL RUN DATES
// -----------------------------------------------------------------------------
$runDateConfig   = $conn->query("SELECT * FROM payroll_run_date ORDER BY id DESC LIMIT 1")->fetch_assoc();
$defaultStartDay = $runDateConfig['start_day'] ?? 1;
$defaultEndDay   = $runDateConfig['end_day'] ?? 0; // 0 indicates last day of month fallback

// Helper function to derive start and end dates based on configured run dates
function calculateCycleDates($month, $year, $startDay, $endDay) {
    if ($endDay <= 0) {
        // Full month calculation
        $start = sprintf('%04d-%02d-%02d', $year, $month, 1);
        $lastDay = date('t', strtotime($start));
        $end   = sprintf('%04d-%02d-%02d', $year, $month, $lastDay);
    } elseif ($startDay > $endDay) {
        // Crosses month boundary (e.g., 26th of previous month to 25th of current month)
        $prevTimestamp = strtotime("-1 month", mktime(0, 0, 0, $month, 1, $year));
        $prevMonth = date('n', $prevTimestamp);
        $prevYear  = date('Y', $prevTimestamp);

        $maxPrevDays = date('t', $prevTimestamp);
        $actualStartDay = min($startDay, $maxPrevDays);
        $start = sprintf('%04d-%02d-%02d', $prevYear, $prevMonth, $actualStartDay);

        $maxCurrDays = date('t', mktime(0, 0, 0, $month, 1, $year));
        $actualEndDay = min($endDay, $maxCurrDays);
        $end = sprintf('%04d-%02d-%02d', $year, $month, $actualEndDay);
    } else {
        // Standard within same month
        $maxDays = date('t', mktime(0, 0, 0, $month, 1, $year));
        $actualStartDay = min($startDay, $maxDays);
        $actualEndDay   = min($endDay, $maxDays);
        $start = sprintf('%04d-%02d-%02d', $year, $month, $actualStartDay);
        $end   = sprintf('%04d-%02d-%02d', $year, $month, $actualEndDay);
    }
    return [$start, $end];
}

// -----------------------------------------------------------------------------
// DELETE A CYCLE (Superadmin only)
// -----------------------------------------------------------------------------
if (isset($_GET['delete_cycle'])) {
    if (!$isSuperAdmin) {
        $_SESSION['flash_error'] = "Only a superadmin can delete a payroll cycle.";
        header("Location: cycles.php");
        exit;
    }
    $cycleId   = (int) $_GET['delete_cycle'];
    $cycleName = $conn->query("SELECT name FROM payroll_cycles WHERE id = $cycleId")->fetch_assoc()['name'] ?? null;
    if ($cycleName) {
        $stmt = $conn->prepare("DELETE FROM payroll_cycles WHERE id = ?");
        $stmt->bind_param('i', $cycleId);
        $stmt->execute();
        $stmt->close();
        $_SESSION['flash_success'] = "Payroll cycle '$cycleName' and all associated data permanently deleted.";
    } else {
        $_SESSION['flash_error'] = "Cycle not found.";
    }
    header("Location: cycles.php");
    exit;
}

// -----------------------------------------------------------------------------
// UPDATE AN EXISTING CYCLE
// -----------------------------------------------------------------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_cycle'])) {
    $cycleId   = (int) $_POST['cycle_id'];
    $name      = trim($_POST['name']);
    $month     = (int) $_POST['payroll_month'];
    $year      = (int) $_POST['payroll_year'];
    $startDate = $_POST['start_date'];
    $endDate   = $_POST['end_date'];

    $stmt = $conn->prepare("UPDATE payroll_cycles SET name = ?, payroll_month = ?, payroll_year = ?, start_date = ?, end_date = ? WHERE id = ?");
    $stmt->bind_param('siissi', $name, $month, $year, $startDate, $endDate, $cycleId);

    try {
        $stmt->execute();
        $_SESSION['flash_success'] = "Payroll cycle '$name' updated.";
    } catch (mysqli_sql_exception $e) {
        if ($e->getCode() === 1062) {
            $monthName = date('F', mktime(0, 0, 0, $month, 1));
            $_SESSION['flash_error'] = "A payroll cycle for $monthName $year already exists.";
        } else {
            $_SESSION['flash_error'] = "Could not update cycle: " . $e->getMessage();
        }
    }
    $stmt->close();
    header("Location: cycles.php");
    exit;
}

// -----------------------------------------------------------------------------
// CREATE A NEW CYCLE
// -----------------------------------------------------------------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_cycle'])) {
    $name       = trim($_POST['name']);
    $month      = (int) $_POST['payroll_month'];
    $year       = (int) $_POST['payroll_year'];
    $startDate  = $_POST['start_date'];
    $endDate    = $_POST['end_date'];
    $workflowId = 1;

    $stmt = $conn->prepare("INSERT INTO payroll_cycles (name, payroll_month, payroll_year, start_date, end_date, workflow_id, created_by, status, current_stage_order) VALUES (?, ?, ?, ?, ?, ?, ?, 'draft', 0)");
    $stmt->bind_param('siissii', $name, $month, $year, $startDate, $endDate, $workflowId, $_SESSION['user_id']);

    try {
        $stmt->execute();
        $_SESSION['flash_success'] = "Payroll cycle '$name' created.";
    } catch (mysqli_sql_exception $e) {
        if ($e->getCode() === 1062) {
            $monthName = date('F', mktime(0, 0, 0, $month, 1));
            $_SESSION['flash_error'] = "A payroll cycle for $monthName $year already exists. Edit or use the existing one instead.";
        } else {
            $_SESSION['flash_error'] = "Could not create cycle: " . $e->getMessage();
        }
    }
    $stmt->close();
    header("Location: cycles.php");
    exit;
}

// -----------------------------------------------------------------------------
// REQUEST APPROVAL -- explicit action, replaces the old auto-send-on-run
// behavior. Initializes the approval trail and emails the first-stage
// approver(s) a secure link to cycle_approve.php. Also doubles as the
// manual "resend" fallback if an earlier notification email failed to send
// or land -- see PayrollEngine::requestApproval()'s isResend handling.
// -----------------------------------------------------------------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['request_approval'])) {
    $cycleId = (int) $_POST['cycle_id'];
    $engine = new PayrollEngine($conn);
    $result = $engine->requestApproval($cycleId);

    if (!$result['success']) {
        $_SESSION['flash_error'] = $result['error'];
        header("Location: cycles.php");
        exit;
    }

    $cycleRow = $conn->query("SELECT * FROM payroll_cycles WHERE id = " . $cycleId)->fetch_assoc();
    $stage = $result['stage'];
    $notifyResult = notifyStageApprovers($conn, $cycleRow, $stage);

    $actionVerb = $result['isResend'] ? 'Reminder sent' : 'Approval requested';
    $actionVerbFail = $result['isResend'] ? 'A reminder was triggered' : 'Approval was requested';

    if ($notifyResult['error']) {
        $_SESSION['flash_error'] = "$actionVerbFail, but the notification email could not be sent (" . $notifyResult['error'] . "). The approver can still act on it from Approvals directly.";
    } elseif ($notifyResult['sent'] > 0) {
        $_SESSION['flash_success'] = "$actionVerb for '{$cycleRow['name']}'. Notified {$notifyResult['sent']} approver(s) at the {$stage['stage_name']} stage.";
    } elseif ($notifyResult['skippedNoEmail'] > 0) {
        $_SESSION['flash_error'] = "$actionVerbFail, but the {$stage['stage_name']} approver(s) have no email on file, so nobody was notified. They can still act on it from Approvals directly.";
    } else {
        $_SESSION['flash_error'] = "$actionVerbFail, but no user matches the {$stage['stage_name']} stage's assigned approver, so nobody was notified.";
    }
    header("Location: cycles.php");
    exit;
}


// Check if editing a specific cycle
$editingCycle = null;
if (isset($_GET['edit_id'])) {
    $editId = (int) $_GET['edit_id'];
    $editingCycle = $conn->query("SELECT * FROM payroll_cycles WHERE id = $editId")->fetch_assoc();
}

// Fetch all cycles for table listing
$cycles = $conn->query("SELECT * FROM payroll_cycles ORDER BY payroll_year DESC, payroll_month DESC");

// Determine initial defaults for creation form
$currentMonth = (int) date('n');
$currentYear  = (int) date('Y');
list($defaultStartDate, $defaultEndDate) = calculateCycleDates($currentMonth, $currentYear, $defaultStartDay, $defaultEndDay);

$pageTitle = 'Payroll Cycles';
$pageSubtitle = 'Payroll Module';
require __DIR__ . '/includes/layout_header.php';
?>

<?php if ($editingCycle): ?>
<!-- EDIT CYCLE FORM -->
<div class="bg-amber-50/50 border border-amber-200 rounded-xl p-4 shadow-xs mb-6">
    <div class="flex items-center justify-between mb-4">
        <h3 class="text-xs font-black text-amber-900 uppercase tracking-tight">Edit Payroll Cycle #<?= $editingCycle['id']; ?></h3>
        <a href="cycles.php" class="text-xs font-bold text-slate-500 hover:text-slate-800 underline">Cancel Edit</a>
    </div>
    
    <form method="POST" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 items-end">
        <input type="hidden" name="cycle_id" value="<?= $editingCycle['id']; ?>">
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Cycle Name</label>
            <input type="text" name="name" required value="<?= h($editingCycle['name']); ?>"
                   class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3 bg-white focus:ring-2 focus:ring-amber-500 focus:outline-none">
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Month</label>
            <select name="payroll_month" class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3 bg-white">
                <?php for ($m = 1; $m <= 12; $m++): ?>
                    <option value="<?= $m; ?>" <?= ((int)$editingCycle['payroll_month'] === $m) ? 'selected' : ''; ?>><?= date('F', mktime(0,0,0,$m,1)); ?></option>
                <?php endfor; ?>
            </select>
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Year</label>
            <input type="number" name="payroll_year" value="<?= h($editingCycle['payroll_year']); ?>" required
                   class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3 bg-white">
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Start Date</label>
            <input type="date" name="start_date" value="<?= h($editingCycle['start_date']); ?>" required class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3 bg-white">
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">End Date</label>
            <input type="date" name="end_date" value="<?= h($editingCycle['end_date']); ?>" required class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3 bg-white">
        </div>
        <div class="lg:col-span-5 flex items-center gap-3">
            <button type="submit" name="update_cycle" class="bg-amber-600 hover:bg-amber-700 text-white text-xs font-black uppercase tracking-wider px-5 py-2.5 rounded-lg transition active:scale-95 border border-amber-700">
                Save Cycle Changes
            </button>
            <a href="cycles.php" class="bg-slate-200 hover:bg-slate-300 text-slate-700 text-xs font-bold uppercase tracking-wider px-4 py-2.5 rounded-lg transition">
                Cancel
            </a>
        </div>
    </form>
</div>
<?php else: ?>
<!-- CREATE CYCLE FORM -->
<div class="bg-white border border-slate-200/80 rounded-xl p-4 shadow-xs mb-6">
    <div class="flex items-center justify-between mb-4">
        <h3 class="text-xs font-black text-slate-900 uppercase tracking-tight">Create New Payroll Cycle</h3>
        <span class="text-[11px] font-semibold text-slate-500 bg-slate-100 px-2.5 py-1 rounded-full border border-slate-200/60">
            Cycle Defaults: Day <?= h($defaultStartDay); ?> to Day <?= h($defaultEndDay ?: 'End'); ?>
        </span>
    </div>
    
    <form method="POST" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 items-end">
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Cycle Name</label>
            <input type="text" id="cycle_name" name="name" required value="<?= date('F Y'); ?>" placeholder="e.g. January 2026"
                   class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3 focus:ring-2 focus:ring-indigo-500 focus:outline-none">
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Month</label>
            <select id="payroll_month" name="payroll_month" class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3">
                <?php for ($m = 1; $m <= 12; $m++): ?>
                    <option value="<?= $m; ?>" <?= ($currentMonth === $m) ? 'selected' : ''; ?>><?= date('F', mktime(0,0,0,$m,1)); ?></option>
                <?php endfor; ?>
            </select>
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Year</label>
            <input type="number" id="payroll_year" name="payroll_year" value="<?= $currentYear; ?>" required
                   class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3">
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">Start Date</label>
            <input type="date" id="start_date" name="start_date" value="<?= $defaultStartDate; ?>" required class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3">
        </div>
        <div>
            <label class="text-[10px] font-black text-slate-400 uppercase tracking-wider">End Date</label>
            <input type="date" id="end_date" name="end_date" value="<?= $defaultEndDate; ?>" required class="mt-1 w-full text-sm border border-slate-200 rounded-lg p-3">
        </div>
        <div class="lg:col-span-5">
            <button type="submit" name="create_cycle" class="bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-black uppercase tracking-wider px-5 py-2.5 rounded-lg transition active:scale-95 border border-indigo-700">
                + Create Cycle
            </button>
        </div>
    </form>
</div>
<?php endif; ?>

<!-- ALL CYCLES LIST TABLE -->
<div class="bg-white border border-slate-200 rounded-xl shadow-xs overflow-hidden">
    <div class="p-4 border-b border-slate-100">
        <h3 class="text-xs font-black text-slate-900 uppercase tracking-tight">All Cycles</h3>
    </div>
    <div class="overflow-x-auto">
        <table class="w-full text-sm">
            <thead class="bg-slate-50 text-slate-400 uppercase text-[9px] font-black tracking-wider">
                <tr>
                    <th class="text-left p-3">Cycle</th>
                    <th class="text-left p-3">Period</th>
                    <th class="text-left p-3">Status</th>
                    <th class="text-left p-3">Actions</th>
                </tr>
            </thead>
            <tbody class="divide-y divide-slate-100">
                <?php while ($c = $cycles->fetch_assoc()):
                    $statusColors = [
                        'draft'            => 'bg-slate-50 text-slate-500 border-slate-100',
                        'processing'       => 'bg-amber-50 text-amber-700 border-amber-100',
                        'pending_approval' => 'bg-amber-50 text-amber-700 border-amber-100',
                        'approved'         => 'bg-emerald-50 text-emerald-700 border-emerald-100',
                        'rejected'         => 'bg-rose-50 text-rose-700 border-rose-100',
                        'paid'             => 'bg-indigo-50 text-indigo-700 border-indigo-100',
                    ];
                    $badge = $statusColors[$c['status']] ?? 'bg-slate-50 text-slate-500 border-slate-100';
                ?>
                <tr class="hover:bg-slate-50/50 transition">
                    <td class="p-3 font-bold text-slate-900"><?= h($c['name']); ?></td>
                    <td class="p-3 text-slate-600"><?= date('d M Y', strtotime($c['start_date'])); ?> &ndash; <?= date('d M Y', strtotime($c['end_date'])); ?></td>
                    <td class="p-3"><span class="px-2 py-0.5 text-[10px] font-bold border rounded <?= $badge; ?>"><?= str_replace('_', ' ', $c['status']); ?></span></td>
                    <td class="p-3 space-x-2">
                        <a href="run_cycle.php?cycle_id=<?= $c['id']; ?>" class="text-indigo-600 font-bold text-xs hover:underline active:scale-95 transition inline-block">Process</a>
                        <?php
                        $isCurrentMonthRow = (int)$c['payroll_month'] === $currentMonth && (int)$c['payroll_year'] === $currentYear;
                        $canRequestApproval = in_array($c['status'], ['processing', 'rejected'], true);
                        // A cycle already sitting at pending_approval still gets an
                        // action here -- if it reached that status under the old
                        // auto-send behavior, or the first email just didn't land,
                        // this resends the reminder to whichever stage is currently
                        // waiting rather than leaving no way to notify them at all.
                        $canResendApproval = $c['status'] === 'pending_approval';
                        ?>
                        <?php if ($isCurrentMonthRow && $canRequestApproval): ?>
                        <form method="POST" class="inline-block" onsubmit="return confirm('Send this cycle for approval? This emails the first-stage approver(s) a secure link to review it.');">
                            <input type="hidden" name="cycle_id" value="<?= $c['id']; ?>">
                            <button type="submit" name="request_approval" value="1" class="text-violet-600 font-bold text-xs hover:underline active:scale-95 transition inline-block bg-transparent border-0 p-0 cursor-pointer">Request Approval</button>
                        </form>
                        <?php elseif ($isCurrentMonthRow && $canResendApproval): ?>
                        <form method="POST" class="inline-block" onsubmit="return confirm('Resend the approval reminder for this cycle? This emails whichever approver the trail is currently waiting on.');">
                            <input type="hidden" name="cycle_id" value="<?= $c['id']; ?>">
                            <button type="submit" name="request_approval" value="1" class="text-violet-600 font-bold text-xs hover:underline active:scale-95 transition inline-block bg-transparent border-0 p-0 cursor-pointer">Resend Reminder</button>
                        </form>
                        <?php endif; ?>
                        <a href="cycle_approve.php?cycle_id=<?= $c['id']; ?>" class="text-amber-600 font-bold text-xs hover:underline active:scale-95 transition inline-block">Approvals</a>
                        <a href="reports.php?cycle_id=<?= $c['id']; ?>" class="text-slate-600 font-bold text-xs hover:underline active:scale-95 transition inline-block">Reports</a>
                        <a href="send_payslips.php?cycle_id=<?= $c['id']; ?>" class="text-emerald-600 font-bold text-xs hover:underline active:scale-95 transition inline-block">Send Payslips</a>
                        <a href="?edit_id=<?= $c['id']; ?>" class="text-blue-600 font-bold text-xs hover:underline active:scale-95 transition inline-block">Edit</a>
                        <?php if ($isSuperAdmin):
                            $warning = $c['status'] === 'paid'
                                ? "This cycle has already had payslips SENT to employees. Deleting it will permanently erase every payslip, approval record, and send log for '" . addslashes($c['name']) . "' -- employees will keep the emails they already received, but you will lose all record of it in this system. This cannot be undone. Delete anyway?"
                                : "Permanently delete '" . addslashes($c['name']) . "' and every payslip, approval record, and send log tied to it? This cannot be undone.";
                        ?>
                        <a href="?delete_cycle=<?= $c['id']; ?>" onclick="return confirm('<?= h($warning); ?>')" class="text-rose-600 font-bold text-xs hover:underline active:scale-95 transition inline-block">Delete</a>
                        <?php endif; ?>
                    </td>
                </tr>
                <?php endwhile; ?>
            </tbody>
        </table>
    </div>
</div>

<?php if (!$editingCycle): ?>
<script>
// Run immediately rather than waiting for DOMContentLoaded -- this script
// tag only ever executes once the surrounding markup already exists, whether
// that's on a normal page load or after an AJAX navigation swap
// (DOMContentLoaded only ever fires once per real browser page load).
(function() {
    const monthSelect = document.getElementById('payroll_month');
    const yearInput   = document.getElementById('payroll_year');
    const nameInput   = document.getElementById('cycle_name');
    const startDate   = document.getElementById('start_date');
    const endDate     = document.getElementById('end_date');

    const configStartDay = <?= json_encode((int)$defaultStartDay); ?>;
    const configEndDay   = <?= json_encode((int)$defaultEndDay); ?>;

    const monthNames = ["January", "February", "March", "April", "May", "June", 
                        "July", "August", "September", "October", "November", "December"];

    function updateDates() {
        const m = parseInt(monthSelect.value);
        const y = parseInt(yearInput.value);

        if (!m || !y) return;

        nameInput.value = monthNames[m - 1] + ' ' + y;

        let startStr = '', endStr = '';

        if (configEndDay <= 0) {
            const lastDay = new Date(y, m, 0).getDate();
            startStr = `${y}-${String(m).padStart(2, '0')}-01`;
            endStr   = `${y}-${String(m).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
        } else if (configStartDay > configEndDay) {
            let prevM = m - 1;
            let prevY = y;
            if (prevM === 0) { prevM = 12; prevY--; }

            const maxPrevDays = new Date(prevY, prevM, 0).getDate();
            const actualStartDay = Math.min(configStartDay, maxPrevDays);

            const maxCurrDays = new Date(y, m, 0).getDate();
            const actualEndDay = Math.min(configEndDay, maxCurrDays);

            startStr = `${prevY}-${String(prevM).padStart(2, '0')}-${String(actualStartDay).padStart(2, '0')}`;
            endStr   = `${y}-${String(m).padStart(2, '0')}-${String(actualEndDay).padStart(2, '0')}`;
        } else {
            const maxDays = new Date(y, m, 0).getDate();
            const actualStartDay = Math.min(configStartDay, maxDays);
            const actualEndDay   = Math.min(configEndDay, maxDays);

            startStr = `${y}-${String(m).padStart(2, '0')}-${String(actualStartDay).padStart(2, '0')}`;
            endStr   = `${y}-${String(m).padStart(2, '0')}-${String(actualEndDay).padStart(2, '0')}`;
        }

        startDate.value = startStr;
        endDate.value   = endStr;
    }

    monthSelect.addEventListener('change', updateDates);
    yearInput.addEventListener('input', updateDates);
})();
</script>
<?php endif; ?>

<?php require __DIR__ . '/includes/layout_footer.php'; ?>