{% extends 'base.html' %}
{% load static %}

{% block title %}Payroll Dashboard | Fox Fitt{% endblock %}

{% block content %}
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>

<div class="container py-4">

    {# === PAGE HEADER === #}
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h1 class="h3 mb-0" style="font-family: 'Poppins', sans-serif;">Payroll Dashboard</h1>
        <div class="d-flex gap-2">
            <button type="button" class="btn btn-outline-info shadow-sm" id="workerLookupBtn">
                <i class="fas fa-id-card fa-sm me-1"></i> Worker Lookup
            </button>
            <button type="button" class="btn btn-primary shadow-sm" id="batchPayBtn" title="Pay all workers with a configured pay schedule for their current pay period">
                <i class="fas fa-users fa-sm me-1"></i> Batch Pay
            </button>
            <button type="button" class="btn btn-accent shadow-sm" data-bs-toggle="modal" data-bs-target="#addAdjustmentModal">
                <i class="fas fa-plus fa-sm me-1"></i> Add Adjustment
            </button>
            <button type="button" class="btn btn-outline-warning shadow-sm" data-bs-toggle="modal" data-bs-target="#priceOvertimeModal">
                <i class="fas fa-clock fa-sm me-1"></i> Price Overtime
            </button>
        </div>
    </div>

    {# === ANALYTICS CARDS === #}
    {# Left side: 3 single-value stat cards (2 on top + 1 below)         #}
    {# Right side: Project breakdown card spanning full height — no scroll #}
    <div class="row g-3 mb-4">

        {# --- Left column: stat cards --- #}
        <div class="col-xl-7">
            <div class="row g-3 h-100">
                {# Outstanding Total — with breakdown of wages vs adjustments #}
                <div class="col-sm-6">
                    <div class="card stat-card h-100 py-2">
                        <div class="card-body">
                            <div class="d-flex align-items-start justify-content-between">
                                <div>
                                    <div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #ef4444;">
                                        Outstanding Payments</div>
                                    <div class="h5 mb-0 font-weight-bold text-gray-800">R {{ outstanding_total|floatformat:2 }}</div>
                                    {# === BREAKDOWN — only shown when there are pending adjustments === #}
                                    {% if pending_adj_add_total or pending_adj_sub_total %}
                                    <div class="mt-2 pt-2 border-top" style="font-size: 0.75rem; color: #64748b;">
                                        <div class="d-flex justify-content-between">
                                            <span>Unpaid wages</span>
                                            <span>R {{ unpaid_wages_total|floatformat:2 }}</span>
                                        </div>
                                        {% if pending_adj_add_total %}
                                        <div class="d-flex justify-content-between">
                                            <span>+ Additions</span>
                                            <span class="text-success">R {{ pending_adj_add_total|floatformat:2 }}</span>
                                        </div>
                                        {% endif %}
                                        {% if pending_adj_sub_total %}
                                        <div class="d-flex justify-content-between">
                                            <span>- Deductions</span>
                                            <span class="text-danger">-R {{ pending_adj_sub_total|floatformat:2 }}</span>
                                        </div>
                                        {% endif %}
                                    </div>
                                    {% endif %}
                                    <div class="mt-1" style="font-size: 0.65rem; color: #94a3b8;">
                                        <i class="fas fa-info-circle"></i> Loan repayments deducted at payment time
                                    </div>
                                </div>
                                <i class="fas fa-exclamation-circle fa-2x text-danger opacity-25"></i>
                            </div>
                        </div>
                    </div>
                </div>

                {# Recent Payments #}
                <div class="col-sm-6">
                    <div class="card stat-card h-100 py-2">
                        <div class="card-body">
                            <div class="d-flex align-items-center justify-content-between">
                                <div>
                                    <div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #10b981;">
                                        Paid (Last 60 Days)</div>
                                    <div class="h5 mb-0 font-weight-bold text-gray-800">R {{ recent_payments_total|floatformat:2 }}</div>
                                </div>
                                <i class="fas fa-check-circle fa-2x text-success opacity-25"></i>
                            </div>
                        </div>
                    </div>
                </div>

                {# Active Loans — spans full width below the first two #}
                <div class="col-12">
                    <div class="card stat-card h-100 py-2">
                        <div class="card-body">
                            <div class="d-flex align-items-center justify-content-between">
                                <div>
                                    <div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #f59e0b;">
                                        Active Loans & Advances ({{ active_loans_count }})</div>
                                    <div class="h5 mb-0 font-weight-bold text-gray-800">R {{ active_loans_balance|floatformat:2 }}</div>
                                </div>
                                <i class="fas fa-hand-holding-usd fa-2x text-warning opacity-25"></i>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        {# --- Right column: project breakdown (grows to fit all projects) --- #}
        <div class="col-xl-5 d-flex">
            <div class="card stat-card py-2 w-100">
                <div class="card-body d-flex flex-column">
                    <div class="d-flex align-items-center justify-content-between mb-3">
                        <div class="text-xs font-weight-bold text-uppercase" style="color: #3b82f6;">
                            Outstanding by Project</div>
                        <i class="fas fa-chart-pie fa-2x text-primary opacity-25"></i>
                    </div>
                    {% if outstanding_project_costs %}
                    <div class="flex-grow-1">
                        {% for pc in outstanding_project_costs %}
                        <div class="d-flex justify-content-between align-items-center {% if not forloop.last %}mb-2 pb-2 border-bottom{% endif %}">
                            <span class="fw-semibold text-gray-800">{{ pc.name }}</span>
                            <span class="fw-bold" style="color: #3b82f6;">R {{ pc.cost|floatformat:2 }}</span>
                        </div>
                        {% endfor %}
                    </div>
                    {% else %}
                    <div class="flex-grow-1 d-flex align-items-center justify-content-center">
                        <span class="text-muted"><i class="fas fa-check-circle me-1"></i> No outstanding amounts</span>
                    </div>
                    {% endif %}
                </div>
            </div>
        </div>

    </div>

    {# === CHARTS === #}
    <div class="row mb-4">
        <div class="col-lg-6 mb-4 mb-lg-0">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-header py-3 bg-white">
                    {# === CHART TOGGLE: Overall vs By Worker === #}
                    {# Two small buttons to switch between the total line chart #}
                    {# and a per-worker stacked bar chart breakdown. #}
                    <div class="d-flex justify-content-between align-items-center">
                        <h6 class="m-0 font-weight-bold" style="color: var(--primary-dark);">Monthly Payroll</h6>
                        <div class="btn-group btn-group-sm" role="group" aria-label="Chart view toggle">
                            <button type="button" class="btn btn-sm btn-accent" id="btnOverall">
                                <i class="fas fa-chart-line fa-sm me-1"></i>Overall
                            </button>
                            <button type="button" class="btn btn-sm btn-outline-secondary" id="btnByWorker">
                                <i class="fas fa-user fa-sm me-1"></i>By Worker
                            </button>
                        </div>
                    </div>
                </div>
                <div class="card-body">
                    {# --- Overall view (default): the existing line chart --- #}
                    <div id="monthlyOverallView">
                        <canvas id="monthlyChart" height="200"></canvas>
                    </div>

                    {# --- By Worker view (hidden): worker dropdown + stacked bar --- #}
                    <div id="monthlyWorkerView" style="display: none;">
                        <div class="mb-3">
                            <select id="workerChartSelect" class="form-select form-select-sm">
                                <option value="">-- Select Worker --</option>
                            </select>
                        </div>
                        <div id="workerChartContainer">
                            <canvas id="workerChart" height="200"></canvas>
                        </div>
                        {# Placeholder shown when no worker is selected #}
                        <div id="workerChartPlaceholder" class="text-center py-4 text-muted">
                            <i class="fas fa-chart-bar fa-2x mb-2 d-block opacity-50"></i>
                            <span>Select a worker to see their payment breakdown</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-lg-6">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-header py-3 bg-white">
                    <h6 class="m-0 font-weight-bold" style="color: #0f172a;">Cost by Project (Monthly)</h6>
                </div>
                <div class="card-body">
                    <canvas id="projectChart" height="200"></canvas>
                </div>
            </div>
        </div>
    </div>

    {# === TAB NAVIGATION === #}
    <ul class="nav nav-tabs mb-3" role="tablist">
        <li class="nav-item" role="presentation">
            <a class="nav-link {% if active_tab == 'pending' %}active{% endif %}" href="?status=pending">
                <i class="fas fa-clock me-1"></i> Pending Payments
            </a>
        </li>
        <li class="nav-item" role="presentation">
            <a class="nav-link {% if active_tab == 'paid' %}active{% endif %}" href="?status=paid">
                <i class="fas fa-check-circle me-1"></i> Payment History
            </a>
        </li>
        <li class="nav-item" role="presentation">
            <a class="nav-link {% if active_tab == 'loans' %}active{% endif %}" href="?status=loans">
                <i class="fas fa-hand-holding-usd me-1"></i> Loans & Advances
            </a>
        </li>
    </ul>

    {# =============================================== #}
    {# === PENDING PAYMENTS TAB === #}
    {# =============================================== #}
    {% if active_tab == 'pending' %}

    {# === PENDING PAYMENTS FILTER BAR === #}
    {# Lets admin filter by team, show only overdue workers, or exclude workers with loans #}
    <div class="d-flex align-items-center gap-3 mb-3 flex-wrap" id="pendingFilters">
        <div class="d-flex align-items-center gap-2">
            <label class="text-muted small mb-0" for="pendingTeamFilter">Team:</label>
            <select id="pendingTeamFilter" class="form-select form-select-sm" style="width: auto;">
                <option value="">All Teams</option>
                {% for team in all_teams %}
                <option value="{{ team.name }}">{{ team.name }}</option>
                {% endfor %}
            </select>
        </div>
        <div class="form-check mb-0">
            <input type="checkbox" class="form-check-input" id="pendingOverdueOnly">
            <label class="form-check-label text-muted small" for="pendingOverdueOnly">Overdue only</label>
        </div>
        <div class="d-flex align-items-center gap-2">
            <label class="text-muted small mb-0" for="pendingLoanFilter">Loans:</label>
            <select id="pendingLoanFilter" class="form-select form-select-sm" style="width: auto;">
                <option value="">All Workers</option>
                <option value="with">With loans only</option>
                <option value="without">Without loans</option>
            </select>
        </div>
    </div>

    <div class="card shadow-sm border-0">
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0" id="pendingTable">
                    <thead class="table-light">
                        <tr>
                            <th scope="col" class="ps-4">Worker</th>
                            <th scope="col">Days</th>
                            <th scope="col">Day Rate</th>
                            <th scope="col">Log Amount</th>
                            <th scope="col">Adjustments</th>
                            <th scope="col">Net Adj</th>
                            <th scope="col" class="fw-bold">Total</th>
                            <th scope="col" class="pe-4 text-end">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for wd in workers_data %}
                        <tr data-team="{{ wd.team_name }}"
                            data-overdue="{{ wd.is_overdue|yesno:'true,false' }}"
                            data-has-loan="{{ wd.has_loan|yesno:'true,false' }}">
                            <td class="ps-4 align-middle">
                                <a href="#" class="worker-lookup-link text-decoration-none text-dark fw-bold"
                                   data-worker-id="{{ wd.worker.id }}">{{ wd.worker.name }}</a>
                                {% if wd.is_overdue %}
                                <span class="badge bg-danger ms-1" title="Has unpaid work from a completed pay period (since {{ wd.earliest_unpaid|date:'d M Y' }})">Overdue</span>
                                {% endif %}
                                {% if wd.has_loan %}
                                <span class="badge bg-warning text-dark ms-1" title="Has active loan or advance">Loan</span>
                                {% endif %}
                            </td>
                            <td class="align-middle">{{ wd.unpaid_count }}</td>
                            <td class="align-middle">R {{ wd.day_rate }}</td>
                            <td class="align-middle">R {{ wd.unpaid_amount|floatformat:2 }}</td>
                            <td class="align-middle">
                                {# Show each pending adjustment as a badge #}
                                {% for adj in wd.adjustments %}
                                <span class="badge {% if adj.type == 'Bonus' or adj.type == 'Overtime' or adj.type == 'New Loan' or adj.type == 'Advance Payment' %}bg-success{% else %}bg-danger{% endif %} mb-1 me-1 adjustment-badge"
                                      style="cursor: pointer;"
                                      data-adj-id="{{ adj.id }}"
                                      data-adj-type="{{ adj.type }}"
                                      data-adj-amount="{{ adj.amount }}"
                                      data-adj-date="{{ adj.date|date:'Y-m-d' }}"
                                      data-adj-description="{{ adj.description }}"
                                      data-adj-project="{{ adj.project_id|default:'' }}"
                                      data-adj-worker="{{ adj.worker.name }}">
                                    {% if adj.type == 'Bonus' or adj.type == 'Overtime' or adj.type == 'New Loan' or adj.type == 'Advance Payment' %}+{% else %}-{% endif %}R{{ adj.amount|floatformat:2 }}
                                    {{ adj.type }}
                                    {% if adj.project %}({{ adj.project.name }}){% endif %}
                                </span>
                                {% endfor %}
                                {% if not wd.adjustments %}
                                <span class="text-muted">-</span>
                                {% endif %}
                            </td>
                            <td class="align-middle {% if wd.adj_amount >= 0 %}text-success{% else %}text-danger{% endif %}">
                                {% if wd.adj_amount >= 0 %}+{% endif %}R {{ wd.adj_amount|floatformat:2 }}
                            </td>
                            <td class="align-middle fw-bold">R {{ wd.total_payable|floatformat:2 }}</td>
                            <td class="pe-4 align-middle text-end">
                                <div class="d-flex gap-1 justify-content-end">
                                    <button type="button" class="btn btn-sm btn-outline-info preview-payslip-btn"
                                            data-worker-id="{{ wd.worker.id }}"
                                            data-worker-name="{{ wd.worker.name }}">
                                        <i class="fas fa-eye"></i>
                                    </button>
                                    <button type="button" class="btn btn-sm btn-outline-secondary quick-adjust-btn"
                                            data-worker-id="{{ wd.worker.id }}"
                                            data-worker-project="{{ wd.last_project_id|default:'' }}"
                                            title="Add adjustment for {{ wd.worker.name }}">
                                        <i class="fas fa-sliders-h"></i>
                                    </button>
                                    <form method="POST" action="{% url 'process_payment' wd.worker.id %}"
                                          class="d-inline pay-form">
                                        {% csrf_token %}
                                        <button type="submit" class="btn btn-sm btn-accent"
                                                title="Pay all pending items. Use Preview (eye icon) for selective payment.">
                                            <i class="fas fa-money-bill-wave me-1"></i> Pay
                                        </button>
                                    </form>
                                </div>
                            </td>
                        </tr>
                        {% empty %}
                        <tr>
                            <td colspan="8" class="text-center py-5 text-muted">
                                <i class="fas fa-check-circle fa-2x mb-3 d-block opacity-50"></i>
                                No pending payments. All workers are paid up!
                            </td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    {% endif %}

    {# =============================================== #}
    {# === PAYMENT HISTORY TAB === #}
    {# =============================================== #}
    {% if active_tab == 'paid' %}
    <div class="card shadow-sm border-0">
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0">
                    <thead class="table-light">
                        <tr>
                            <th scope="col" class="ps-4">Date</th>
                            <th scope="col">Worker</th>
                            <th scope="col">Amount Paid</th>
                            <th scope="col">Work Logs</th>
                            <th scope="col">Adjustments</th>
                            <th scope="col" class="pe-4 text-end">Payslip</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for record in paid_records %}
                        <tr>
                            <td class="ps-4 align-middle">{{ record.date }}</td>
                            <td class="align-middle"><a href="#" class="worker-lookup-link text-decoration-none text-dark fw-bold"
                                   data-worker-id="{{ record.worker.id }}">{{ record.worker.name }}</a></td>
                            <td class="align-middle">R {{ record.amount_paid|floatformat:2 }}</td>
                            <td class="align-middle">
                                {{ record.work_logs.count }} day{{ record.work_logs.count|pluralize }}
                            </td>
                            <td class="align-middle">
                                {% for adj in record.adjustments.all %}
                                <span class="badge {% if adj.type == 'Bonus' or adj.type == 'Overtime' or adj.type == 'New Loan' or adj.type == 'Advance Payment' %}bg-success{% else %}bg-danger{% endif %} me-1">
                                    {{ adj.type }}: R {{ adj.amount|floatformat:2 }}
                                </span>
                                {% empty %}
                                <span class="text-muted">-</span>
                                {% endfor %}
                            </td>
                            <td class="pe-4 align-middle text-end">
                                <a href="{% url 'payslip_detail' record.id %}" class="btn btn-sm btn-outline-secondary">
                                    <i class="fas fa-file-alt me-1"></i> View
                                </a>
                            </td>
                        </tr>
                        {% empty %}
                        <tr>
                            <td colspan="6" class="text-center py-5 text-muted">
                                <i class="fas fa-inbox fa-2x mb-3 d-block opacity-50"></i>
                                No payment history yet.
                            </td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    {% endif %}

    {# =============================================== #}
    {# === LOANS TAB === #}
    {# =============================================== #}
    {% if active_tab == 'loans' %}
    <div class="mb-3 d-flex gap-2">
        <a href="?status=loans&loan_status=active"
           class="btn btn-sm {% if loan_filter == 'active' %}btn-accent{% else %}btn-outline-secondary{% endif %}">
            Active
        </a>
        <a href="?status=loans&loan_status=history"
           class="btn btn-sm {% if loan_filter == 'history' %}btn-accent{% else %}btn-outline-secondary{% endif %}">
            History
        </a>
    </div>
    <div class="card shadow-sm border-0">
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover mb-0">
                    <thead class="table-light">
                        <tr>
                            <th scope="col" class="ps-4">Worker</th>
                            <th scope="col">Type</th>
                            <th scope="col">Principal</th>
                            <th scope="col">Balance</th>
                            <th scope="col">Date</th>
                            <th scope="col">Reason</th>
                            <th scope="col" class="pe-4">Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for loan in loans %}
                        <tr>
                            <td class="ps-4 align-middle"><a href="#" class="worker-lookup-link text-decoration-none text-dark fw-bold"
                                   data-worker-id="{{ loan.worker.id }}">{{ loan.worker.name }}</a></td>
                            <td class="align-middle">
                                {% if loan.loan_type == 'advance' %}
                                <span class="badge bg-info text-dark">Advance</span>
                                {% else %}
                                <span class="badge bg-primary">Loan</span>
                                {% endif %}
                            </td>
                            <td class="align-middle">R {{ loan.principal_amount|floatformat:2 }}</td>
                            <td class="align-middle">R {{ loan.remaining_balance|floatformat:2 }}</td>
                            <td class="align-middle">{{ loan.date }}</td>
                            <td class="align-middle">{{ loan.reason|default:"-" }}</td>
                            <td class="pe-4 align-middle">
                                {% if loan.active %}
                                <span class="badge bg-warning text-dark">Active</span>
                                {% else %}
                                <span class="badge bg-success">Paid Off</span>
                                {% endif %}
                            </td>
                        </tr>
                        {% empty %}
                        <tr>
                            <td colspan="7" class="text-center py-5 text-muted">
                                <i class="fas fa-hand-holding-usd fa-2x mb-3 d-block opacity-50"></i>
                                {% if loan_filter == 'active' %}No active loans or advances.{% else %}No loan/advance history.{% endif %}
                            </td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    {% endif %}

</div>

{# ================================================================== #}
{# === MODALS === #}
{# ================================================================== #}

{# --- ADD ADJUSTMENT MODAL --- #}
<div class="modal fade" id="addAdjustmentModal" tabindex="-1" aria-labelledby="addAdjLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <form method="POST" action="{% url 'add_adjustment' %}">
                {% csrf_token %}
                <div class="modal-header">
                    <h5 class="modal-title" id="addAdjLabel">Add Payroll Adjustment</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="row g-3">
                        {# Type #}
                        <div class="col-md-6">
                            <label class="form-label">Type</label>
                            <select name="type" class="form-select" required id="addAdjType">
                                {% for value, label in adjustment_types %}
                                <option value="{{ value }}">{{ label }}</option>
                                {% endfor %}
                            </select>
                        </div>

                        {# Project — required for most types, hidden for Loan types #}
                        <div class="col-md-6" id="addAdjProjectGroup">
                            <label class="form-label">Project</label>
                            <select name="project" class="form-select" id="addAdjProject" required>
                                <option value="">-- Select Project --</option>
                                {% for p in active_projects %}
                                <option value="{{ p.id }}">{{ p.name }}</option>
                                {% endfor %}
                            </select>
                        </div>

                        {# Amount #}
                        <div class="col-md-6">
                            <label class="form-label">Amount (R)</label>
                            <input type="number" name="amount" class="form-control" step="0.01" min="0.01" required>
                        </div>

                        {# Date #}
                        <div class="col-md-6">
                            <label class="form-label">Date</label>
                            <input type="date" name="date" class="form-control" value="{{ today|date:'Y-m-d' }}">
                        </div>

                        {# Workers - multi-select with team helper #}
                        <div class="col-12">
                            <label class="form-label">Workers</label>
                            <div class="mb-2 d-flex flex-wrap gap-2 align-items-center">
                                <select id="addAdjTeamSelect" class="form-select form-select-sm" style="max-width: 250px;">
                                    <option value="">Quick select by team...</option>
                                    {% for team in all_teams %}
                                    <option value="{{ team.id }}">{{ team.name }}</option>
                                    {% endfor %}
                                </select>
                                <a href="#" id="adjSelectAll" class="small text-primary text-decoration-none text-nowrap">Select All</a>
                                <a href="#" id="adjDeselectAll" class="small text-muted text-decoration-none text-nowrap">Clear</a>
                            </div>
                            <div style="max-height: 200px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 4px; padding: 8px;">
                                {% for w in all_workers %}
                                <div class="form-check">
                                    <input class="form-check-input add-adj-worker" type="checkbox"
                                           name="workers" value="{{ w.id }}" id="addW{{ w.id }}">
                                    <label class="form-check-label" for="addW{{ w.id }}">{{ w.name }}</label>
                                </div>
                                {% endfor %}
                            </div>
                            {# Counter + validation message for workers #}
                            <div class="form-text mt-1">
                                <span id="adjSelectedCount">0</span> worker(s) selected
                            </div>
                            <div class="invalid-feedback" id="addAdjWorkerError" style="display: none;">
                                Please select at least one worker.
                            </div>
                        </div>

                        {# Description #}
                        <div class="col-12">
                            <label class="form-label">Description</label>
                            <textarea name="description" class="form-control" rows="2" placeholder="Reason for this adjustment..."></textarea>
                        </div>

                        {# Pay Immediately — only shown for New Loan type #}
                        {# When checked, the loan is paid to the worker right away and #}
                        {# a payslip is emailed to Spark. When unchecked, the loan sits #}
                        {# in pending payments and gets included in the next pay cycle. #}
                        <div class="col-12" id="addAdjPayImmediatelyGroup" style="display: none;">
                            <div class="form-check">
                                <input type="checkbox" class="form-check-input" name="pay_immediately"
                                       id="addAdjPayImmediately" value="1" checked>
                                <label class="form-check-label" for="addAdjPayImmediately">
                                    <i class="fas fa-bolt me-1 text-warning"></i>
                                    <strong>Pay Immediately</strong>
                                    <span class="text-muted small">— send payslip to Spark now and record as paid</span>
                                </label>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                    <button type="submit" class="btn btn-primary">
                        <i class="fas fa-plus me-1"></i> Add Adjustment
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>

{# --- EDIT ADJUSTMENT MODAL --- #}
<div class="modal fade" id="editAdjustmentModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <form method="POST" id="editAdjForm" action="">
                {% csrf_token %}
                <div class="modal-header">
                    <h5 class="modal-title">Edit Adjustment</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="mb-2">
                        <strong id="editAdjWorkerName"></strong>
                    </div>
                    <div class="row g-3">
                        {# Type (only Bonus ↔ Deduction is allowed) #}
                        <div class="col-md-6">
                            <label class="form-label">Type</label>
                            <select name="type" class="form-select" id="editAdjType">
                                {% for value, label in adjustment_types %}
                                <option value="{{ value }}">{{ label }}</option>
                                {% endfor %}
                            </select>
                        </div>

                        {# Project #}
                        <div class="col-md-6">
                            <label class="form-label">Project</label>
                            <select name="project" class="form-select" id="editAdjProject">
                                <option value="">-- Select Project --</option>
                                {% for p in active_projects %}
                                <option value="{{ p.id }}">{{ p.name }}</option>
                                {% endfor %}
                            </select>
                        </div>

                        {# Amount #}
                        <div class="col-md-6">
                            <label class="form-label">Amount (R)</label>
                            <input type="number" name="amount" class="form-control" id="editAdjAmount"
                                   step="0.01" min="0.01" required>
                        </div>

                        {# Date #}
                        <div class="col-md-6">
                            <label class="form-label">Date</label>
                            <input type="date" name="date" class="form-control" id="editAdjDate">
                        </div>

                        {# Description #}
                        <div class="col-12">
                            <label class="form-label">Description</label>
                            <textarea name="description" class="form-control" id="editAdjDescription" rows="2"></textarea>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-outline-danger btn-sm" id="editAdjDeleteBtn">
                        <i class="fas fa-trash me-1"></i> Delete
                    </button>
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                    <button type="submit" class="btn btn-primary">
                        <i class="fas fa-save me-1"></i> Save Changes
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>

{# --- DELETE CONFIRMATION MODAL --- #}
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-sm">
        <div class="modal-content">
            <form method="POST" id="deleteAdjForm" action="">
                {% csrf_token %}
                <div class="modal-header">
                    <h5 class="modal-title text-danger">Confirm Delete</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <p>Are you sure you want to delete this <strong id="deleteAdjType"></strong> adjustment for <strong id="deleteAdjWorker"></strong>?</p>
                    <p class="text-muted small mb-0">This action cannot be undone.</p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
                    <button type="submit" class="btn btn-danger btn-sm">
                        <i class="fas fa-trash me-1"></i> Delete
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>

{# --- PRICE OVERTIME MODAL --- #}
<div class="modal fade" id="priceOvertimeModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-xl">
        <div class="modal-content">
            <form method="POST" action="{% url 'price_overtime' %}">
                {% csrf_token %}
                <div class="modal-header">
                    <h5 class="modal-title"><i class="fas fa-clock me-2"></i>Price Unpriced Overtime</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    {# Filter row #}
                    <div class="row g-2 mb-3">
                        <div class="col-md-4">
                            <input type="text" id="otFilterWorker" class="form-control form-control-sm" placeholder="Filter by worker...">
                        </div>
                        <div class="col-md-4">
                            <select id="otFilterProject" class="form-select form-select-sm">
                                <option value="">All Projects</option>
                                {% for p in active_projects %}
                                <option value="{{ p.name }}">{{ p.name }}</option>
                                {% endfor %}
                            </select>
                        </div>
                        <div class="col-md-4 d-flex align-items-center gap-2">
                            <div class="form-check">
                                <input class="form-check-input" type="checkbox" id="otSelectAll">
                                <label class="form-check-label small" for="otSelectAll">Select All</label>
                            </div>
                        </div>
                    </div>

                    <div class="table-responsive" style="max-height: 400px; overflow-y: auto;">
                        <table class="table table-sm table-hover mb-0">
                            <thead class="table-light sticky-top">
                                <tr>
                                    <th><input type="checkbox" class="form-check-input" id="otCheckAll"></th>
                                    <th>Worker</th>
                                    <th>Date</th>
                                    <th>Project</th>
                                    <th>Overtime</th>
                                    <th>Rate %</th>
                                </tr>
                            </thead>
                            <tbody id="otTableBody">
                                {# Populated by JavaScript from overtime_data_json #}
                            </tbody>
                        </table>
                    </div>
                    <p class="text-muted small mt-2 mb-0" id="otCountMsg">Loading overtime data...</p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                    <button type="submit" class="btn btn-primary">
                        <i class="fas fa-calculator me-1"></i> Price Selected
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>

{# --- PREVIEW PAYSLIP MODAL --- #}
{# === BATCH PAY MODAL === #}
{# Shows a preview of which workers will be paid (based on team pay schedules), #}
{# then lets the admin confirm to process all payments at once. #}
<div class="modal fade" id="batchPayModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><i class="fas fa-users me-2"></i>Batch Pay by Schedule</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body" id="batchPayModalBody">
                {# Content loaded via JavaScript #}
                <div class="text-center py-4">
                    <div class="spinner-border text-primary" role="status"></div>
                    <p class="text-muted mt-2 small">Loading preview...</p>
                </div>
            </div>
            <div class="modal-footer" id="batchPayModalFooter" style="display:none;">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-accent" id="confirmBatchPayBtn">
                    <i class="fas fa-money-bill-wave me-1"></i> Confirm & Pay All
                </button>
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="previewPayslipModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><i class="fas fa-file-invoice me-2"></i>Payslip Preview & Repayments</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body" id="previewPayslipBody">
                {# Content loaded via JavaScript #}
                <div class="text-center py-4">
                    <div class="spinner-border text-primary" role="status"></div>
                    <p class="text-muted mt-2 small">Loading preview...</p>
                </div>
            </div>
        </div>
    </div>
</div>

{# === WORKER LOOKUP MODAL === #}
{# Shows a comprehensive financial report card for any active worker. #}
{# Triggered by clicking a worker name or the "Worker Lookup" button. #}
<div class="modal fade" id="workerLookupModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><i class="fas fa-id-card me-2"></i>Worker Lookup</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                {# Worker selector dropdown #}
                <div class="mb-3">
                    <select id="workerLookupSelect" class="form-select">
                        <option value="">Select a worker...</option>
                        {% for w in all_workers %}
                        <option value="{{ w.id }}">{{ w.name }}</option>
                        {% endfor %}
                    </select>
                </div>
                {# Report card content — populated dynamically by JavaScript #}
                <div id="workerLookupBody">
                    <div class="text-center py-5 text-muted">
                        <i class="fas fa-id-card fa-3x mb-3 opacity-25"></i>
                        <p>Select a worker to view their report card.</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


{# ================================================================== #}
{# === JAVASCRIPT === #}
{# ================================================================== #}

{# Django's json_script filter safely outputs JSON without XSS risk #}
{{ overtime_data_json|json_script:"otDataJson" }}
{{ team_workers_map_json|json_script:"teamWorkersJson" }}
{{ chart_labels_json|json_script:"chartLabelsJson" }}
{{ chart_totals_json|json_script:"chartTotalsJson" }}
{{ project_chart_json|json_script:"projectChartJson" }}
{{ worker_chart_json|json_script:"workerChartJson" }}

<script>
document.addEventListener('DOMContentLoaded', function() {
    // === SAFE DATA LOADING ===
    // json_script outputs data in a <script type="application/json"> tag,
    // which is the Django-recommended way to pass data to JavaScript safely.
    const allOtData = JSON.parse(document.getElementById('otDataJson').textContent);
    const teamWorkersMap = JSON.parse(document.getElementById('teamWorkersJson').textContent);
    const chartLabels = JSON.parse(document.getElementById('chartLabelsJson').textContent);
    const chartTotals = JSON.parse(document.getElementById('chartTotalsJson').textContent);
    const projectChartData = JSON.parse(document.getElementById('projectChartJson').textContent);
    const workerChartData = JSON.parse(document.getElementById('workerChartJson').textContent);

    // === HELPER: Format currency ===
    function fmt(val) {
        return 'R ' + parseFloat(val).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }

    // === HELPER: Create a table cell with text ===
    function createTd(text, className) {
        const td = document.createElement('td');
        td.textContent = text;
        if (className) td.className = className;
        return td;
    }

    // =================================================================
    // PENDING PAYMENTS TABLE — Team / Overdue / Loan Filters
    // Shows/hides rows based on filter selections. Pure client-side.
    // =================================================================
    var pendingTable = document.getElementById('pendingTable');
    var pendingTeamFilter = document.getElementById('pendingTeamFilter');
    var pendingOverdueOnly = document.getElementById('pendingOverdueOnly');
    var pendingLoanFilter = document.getElementById('pendingLoanFilter');

    if (pendingTable && pendingTeamFilter) {
        function applyPendingFilters() {
            var team = pendingTeamFilter.value;
            var overdueOnly = pendingOverdueOnly ? pendingOverdueOnly.checked : false;
            var loanMode = pendingLoanFilter ? pendingLoanFilter.value : '';
            var rows = pendingTable.querySelectorAll('tbody tr[data-team]');
            for (var i = 0; i < rows.length; i++) {
                var row = rows[i];
                var teamMatch = !team || row.dataset.team === team;
                var overdueMatch = !overdueOnly || row.dataset.overdue === 'true';
                var loanMatch = !loanMode
                    || (loanMode === 'with' && row.dataset.hasLoan === 'true')
                    || (loanMode === 'without' && row.dataset.hasLoan !== 'true');
                row.style.display = (teamMatch && overdueMatch && loanMatch) ? '' : 'none';
            }
        }
        pendingTeamFilter.addEventListener('change', applyPendingFilters);
        if (pendingOverdueOnly) pendingOverdueOnly.addEventListener('change', applyPendingFilters);
        if (pendingLoanFilter) pendingLoanFilter.addEventListener('change', applyPendingFilters);
    }

    // =================================================================
    // CHART.JS — Monthly Totals (Line Chart)
    // Wrapped in try-catch so a Chart.js failure doesn't prevent
    // the rest of the page's JavaScript from running.
    // =================================================================
    try {
        const monthlyCtx = document.getElementById('monthlyChart');
        if (monthlyCtx) {
            new Chart(monthlyCtx, {
                type: 'line',
                data: {
                    labels: chartLabels,
                    datasets: [{
                        label: 'Total Paid',
                        data: chartTotals,
                        borderColor: '#10b981',
                        backgroundColor: 'rgba(16, 185, 129, 0.1)',
                        fill: true,
                        tension: 0.3,
                        pointRadius: 4,
                        pointHoverRadius: 6,
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: { display: false },
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return fmt(context.parsed.y);
                                }
                            }
                        }
                    },
                    scales: {
                        y: {
                            beginAtZero: true,
                            ticks: {
                                callback: function(val) { return 'R ' + val.toLocaleString(); }
                            }
                        }
                    }
                }
            });
        }
    } catch (e) {
        console.warn('Monthly chart failed to render:', e);
    }

    // =================================================================
    // CHART.JS — Per-Project Costs (Stacked Bar Chart)
    // =================================================================
    try {
        const projectCtx = document.getElementById('projectChart');
        if (projectCtx) {
            // Color palette for projects
            const colors = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#06b6d4', '#84cc16'];
            const datasets = projectChartData.map(function(proj, i) {
                return {
                    label: proj.name,
                    data: proj.data,
                    backgroundColor: colors[i % colors.length],
                };
            });

            new Chart(projectCtx, {
                type: 'bar',
                data: {
                    labels: chartLabels,
                    datasets: datasets,
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return context.dataset.label + ': ' + fmt(context.parsed.y);
                                },
                                // Show the month total at the bottom of the tooltip
                                footer: function(tooltipItems) {
                                    var total = 0;
                                    tooltipItems[0].chart.data.datasets.forEach(function(ds) {
                                        total += ds.data[tooltipItems[0].dataIndex] || 0;
                                    });
                                    return 'Total: ' + fmt(total);
                                }
                            }
                        }
                    },
                    scales: {
                        x: { stacked: true },
                        y: {
                            stacked: true,
                            beginAtZero: true,
                            ticks: {
                                callback: function(val) { return 'R ' + val.toLocaleString(); }
                            }
                        }
                    }
                }
            });
        }
    } catch (e) {
        console.warn('Project chart failed to render:', e);
    }

    // =================================================================
    // CHART TOGGLE — Switch between "Overall" line chart and
    // "By Worker" stacked bar chart in the Monthly Payroll card.
    // =================================================================

    var btnOverall = document.getElementById('btnOverall');
    var btnByWorker = document.getElementById('btnByWorker');
    var monthlyOverallView = document.getElementById('monthlyOverallView');
    var monthlyWorkerView = document.getElementById('monthlyWorkerView');

    if (btnOverall && btnByWorker) {
        // Switch to "Overall" — show the line chart, hide the worker view
        btnOverall.addEventListener('click', function() {
            monthlyOverallView.style.display = '';
            monthlyWorkerView.style.display = 'none';
            btnOverall.className = 'btn btn-sm btn-accent';
            btnByWorker.className = 'btn btn-sm btn-outline-secondary';
        });

        // Switch to "By Worker" — hide line chart, show worker dropdown + bar chart
        btnByWorker.addEventListener('click', function() {
            monthlyOverallView.style.display = 'none';
            monthlyWorkerView.style.display = '';
            btnByWorker.className = 'btn btn-sm btn-accent';
            btnOverall.className = 'btn btn-sm btn-outline-secondary';
        });
    }

    // =================================================================
    // CHART.JS — Per-Worker Breakdown (Stacked Bar Chart)
    // Shows base pay, overtime, bonuses as positive bars going up,
    // and deductions, loan repayments, advance payments going down.
    // =================================================================

    var workerChartSelect = document.getElementById('workerChartSelect');
    var workerChartContainer = document.getElementById('workerChartContainer');
    var workerChartPlaceholder = document.getElementById('workerChartPlaceholder');
    var workerChartInstance = null;  // Track so we can destroy before re-creating

    if (workerChartSelect) {
        // Hide the chart canvas initially (show placeholder instead)
        if (workerChartContainer) workerChartContainer.style.display = 'none';

        // Populate the worker dropdown from pre-computed data
        // (already sorted alphabetically by the server)
        Object.keys(workerChartData).forEach(function(workerId) {
            var opt = document.createElement('option');
            opt.value = workerId;
            opt.textContent = workerChartData[workerId].name;
            workerChartSelect.appendChild(opt);
        });

        // When a worker is selected, render their stacked bar chart
        workerChartSelect.addEventListener('change', function() {
            var workerId = this.value;
            var canvasEl = document.getElementById('workerChart');

            // No worker selected — show placeholder, hide chart
            if (!workerId) {
                if (workerChartPlaceholder) workerChartPlaceholder.style.display = '';
                if (workerChartContainer) workerChartContainer.style.display = 'none';
                if (workerChartInstance) {
                    workerChartInstance.destroy();
                    workerChartInstance = null;
                }
                return;
            }

            // Worker selected — hide placeholder, show chart canvas
            if (workerChartPlaceholder) workerChartPlaceholder.style.display = 'none';
            if (workerChartContainer) workerChartContainer.style.display = '';

            // Destroy the previous chart before creating a new one
            if (workerChartInstance) {
                workerChartInstance.destroy();
                workerChartInstance = null;
            }

            var data = workerChartData[workerId];
            if (!data) return;

            // Pull out monthly values into separate arrays (one per component)
            var basePay = data.months.map(function(m) { return m.base; });
            var overtime = data.months.map(function(m) { return m.overtime; });
            var bonus = data.months.map(function(m) { return m.bonus; });
            var newLoan = data.months.map(function(m) { return m.new_loan; });
            // Deductive items shown as negative values (bars go below zero)
            var deduction = data.months.map(function(m) { return -m.deduction; });
            var loanRepayment = data.months.map(function(m) { return -m.loan_repayment; });
            var advance = data.months.map(function(m) { return -m.advance; });

            // Build datasets — only include types that have non-zero data
            // so the legend doesn't show irrelevant items
            var datasets = [];

            if (basePay.some(function(v) { return v > 0; })) {
                datasets.push({
                    label: 'Base Pay',
                    data: basePay,
                    backgroundColor: '#10b981',
                    stack: 'positive',
                });
            }
            if (overtime.some(function(v) { return v > 0; })) {
                datasets.push({
                    label: 'Overtime',
                    data: overtime,
                    backgroundColor: '#f59e0b',
                    stack: 'positive',
                });
            }
            if (bonus.some(function(v) { return v > 0; })) {
                datasets.push({
                    label: 'Bonus',
                    data: bonus,
                    backgroundColor: '#3b82f6',
                    stack: 'positive',
                });
            }
            if (newLoan.some(function(v) { return v > 0; })) {
                datasets.push({
                    label: 'New Loan',
                    data: newLoan,
                    backgroundColor: '#8b5cf6',
                    stack: 'positive',
                });
            }
            if (deduction.some(function(v) { return v < 0; })) {
                datasets.push({
                    label: 'Deductions',
                    data: deduction,
                    backgroundColor: '#ef4444',
                    stack: 'negative',
                });
            }
            if (loanRepayment.some(function(v) { return v < 0; })) {
                datasets.push({
                    label: 'Loan Repayments',
                    data: loanRepayment,
                    backgroundColor: '#991b1b',
                    stack: 'negative',
                });
            }
            if (advance.some(function(v) { return v < 0; })) {
                datasets.push({
                    label: 'Advance Payments',
                    data: advance,
                    backgroundColor: '#7c3aed',
                    stack: 'negative',
                });
            }

            try {
                workerChartInstance = new Chart(canvasEl, {
                    type: 'bar',
                    data: {
                        labels: chartLabels,
                        datasets: datasets,
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: {
                            tooltip: {
                                callbacks: {
                                    label: function(context) {
                                        var val = context.parsed.y;
                                        var prefix = val >= 0 ? '+' : '';
                                        return context.dataset.label + ': ' + prefix + fmt(val);
                                    }
                                }
                            },
                            legend: {
                                position: 'bottom',
                                labels: {
                                    boxWidth: 12,
                                    padding: 8,
                                    font: { size: 11 }
                                }
                            }
                        },
                        scales: {
                            x: { stacked: true },
                            y: {
                                stacked: true,
                                ticks: {
                                    callback: function(val) { return 'R ' + val.toLocaleString(); }
                                }
                            }
                        }
                    }
                });
            } catch (e) {
                console.warn('Worker chart failed to render:', e);
            }
        });
    }

    // =================================================================
    // OVERTIME MODAL — Build table rows using DOM methods (no innerHTML)
    // =================================================================
    const otTableBody = document.getElementById('otTableBody');
    const otCountMsg = document.getElementById('otCountMsg');
    const otFilterWorker = document.getElementById('otFilterWorker');
    const otFilterProject = document.getElementById('otFilterProject');
    const otSelectAll = document.getElementById('otSelectAll');
    const otCheckAll = document.getElementById('otCheckAll');

    function buildOtTable(data) {
        // Clear existing rows safely
        while (otTableBody && otTableBody.firstChild) {
            otTableBody.removeChild(otTableBody.firstChild);
        }

        if (data.length === 0) {
            const tr = document.createElement('tr');
            const td = document.createElement('td');
            td.setAttribute('colspan', '6');
            td.className = 'text-center py-3 text-muted';
            td.textContent = 'No unpriced overtime found.';
            tr.appendChild(td);
            otTableBody.appendChild(tr);
            if (otCountMsg) otCountMsg.textContent = '0 entries';
            return;
        }

        data.forEach(function(entry) {
            const tr = document.createElement('tr');

            // Checkbox cell
            const tdCheck = document.createElement('td');
            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.className = 'form-check-input ot-check';
            checkbox.checked = true;
            tdCheck.appendChild(checkbox);
            tr.appendChild(tdCheck);

            // Worker name
            tr.appendChild(createTd(entry.worker_name));

            // Date
            tr.appendChild(createTd(entry.date));

            // Project
            tr.appendChild(createTd(entry.project));

            // Overtime label
            tr.appendChild(createTd(entry.ot_label));

            // Rate % select
            const tdRate = document.createElement('td');
            const select = document.createElement('select');
            select.className = 'form-select form-select-sm';
            select.style.width = '100px';
            select.name = 'rate_pct[]';
            [100, 150, 200].forEach(function(pct) {
                const opt = document.createElement('option');
                opt.value = pct;
                opt.textContent = pct + '%';
                if (pct === 150) opt.selected = true;
                select.appendChild(opt);
            });
            tdRate.appendChild(select);
            tr.appendChild(tdRate);

            // Hidden inputs for form submission
            const hiddenLogId = document.createElement('input');
            hiddenLogId.type = 'hidden';
            hiddenLogId.name = 'log_id[]';
            hiddenLogId.value = entry.log_id;
            hiddenLogId.className = 'ot-hidden';
            tr.appendChild(hiddenLogId);

            const hiddenWorkerId = document.createElement('input');
            hiddenWorkerId.type = 'hidden';
            hiddenWorkerId.name = 'worker_id[]';
            hiddenWorkerId.value = entry.worker_id;
            hiddenWorkerId.className = 'ot-hidden';
            tr.appendChild(hiddenWorkerId);

            // Store data on the row for filtering
            tr.dataset.worker = entry.worker_name.toLowerCase();
            tr.dataset.project = entry.project;

            otTableBody.appendChild(tr);
        });

        if (otCountMsg) {
            otCountMsg.textContent = data.length + ' unpriced overtime entr' + (data.length === 1 ? 'y' : 'ies');
        }
    }

    // Initial build
    buildOtTable(allOtData);

    // Filter overtime table
    function filterOtTable() {
        if (!otTableBody) return;
        const workerFilter = (otFilterWorker ? otFilterWorker.value : '').toLowerCase();
        const projectFilter = otFilterProject ? otFilterProject.value : '';
        let visibleCount = 0;

        Array.from(otTableBody.children).forEach(function(tr) {
            if (!tr.dataset.worker) return; // skip "no data" row
            const matchWorker = !workerFilter || tr.dataset.worker.indexOf(workerFilter) !== -1;
            const matchProject = !projectFilter || tr.dataset.project === projectFilter;
            tr.style.display = (matchWorker && matchProject) ? '' : 'none';
            if (matchWorker && matchProject) visibleCount++;
        });
        if (otCountMsg) {
            otCountMsg.textContent = visibleCount + ' of ' + allOtData.length + ' entries shown';
        }
    }

    if (otFilterWorker) otFilterWorker.addEventListener('input', filterOtTable);
    if (otFilterProject) otFilterProject.addEventListener('change', filterOtTable);

    // Select All / Deselect All
    function toggleAllOt(checked) {
        if (!otTableBody) return;
        otTableBody.querySelectorAll('.ot-check').forEach(function(cb) {
            if (cb.closest('tr').style.display !== 'none') {
                cb.checked = checked;
            }
        });
    }
    if (otSelectAll) otSelectAll.addEventListener('change', function() { toggleAllOt(this.checked); });
    if (otCheckAll) otCheckAll.addEventListener('change', function() { toggleAllOt(this.checked); });

    // Before submit: remove hidden inputs for unchecked rows
    const otForm = document.querySelector('#priceOvertimeModal form');
    if (otForm) {
        otForm.addEventListener('submit', function() {
            otTableBody.querySelectorAll('tr').forEach(function(tr) {
                const cb = tr.querySelector('.ot-check');
                if (cb && !cb.checked) {
                    tr.querySelectorAll('.ot-hidden').forEach(function(h) { h.disabled = true; });
                    tr.querySelector('select').disabled = true;
                }
            });
        });
    }

    // =================================================================
    // ADD ADJUSTMENT — Team quick-select, project visibility,
    // worker count display, and form validation
    // =================================================================
    const addAdjType = document.getElementById('addAdjType');
    const addAdjProjectGroup = document.getElementById('addAdjProjectGroup');
    const addAdjProject = document.getElementById('addAdjProject');
    const addAdjTeamSelect = document.getElementById('addAdjTeamSelect');
    const addAdjWorkerCheckboxes = document.querySelectorAll('.add-adj-worker');
    const adjSelectedCount = document.getElementById('adjSelectedCount');
    const addAdjWorkerError = document.getElementById('addAdjWorkerError');

    // Show/hide project field and "Pay Immediately" checkbox based on adjustment type.
    // Also toggles the HTML "required" attribute so browser validation
    // only enforces the project when the type actually needs one.
    var addAdjPayImmediatelyGroup = document.getElementById('addAdjPayImmediatelyGroup');
    function toggleProjectField() {
        if (!addAdjType || !addAdjProjectGroup) return;
        // Loan types and repayments don't need a project.
        // Advance Payment DOES need a project (for cost tracking).
        var noProjectTypes = ['New Loan', 'Loan Repayment', 'Advance Repayment'];
        var needsProject = noProjectTypes.indexOf(addAdjType.value) === -1;
        addAdjProjectGroup.style.display = needsProject ? '' : 'none';
        if (addAdjProject) {
            if (needsProject) {
                addAdjProject.setAttribute('required', '');
            } else {
                addAdjProject.removeAttribute('required');
                addAdjProject.value = '';  // Clear selection when hidden
            }
        }
        // "Pay Immediately" checkbox — only shown for New Loan type
        if (addAdjPayImmediatelyGroup) {
            addAdjPayImmediatelyGroup.style.display = (addAdjType.value === 'New Loan') ? '' : 'none';
        }
    }
    if (addAdjType) {
        addAdjType.addEventListener('change', toggleProjectField);
        toggleProjectField();
    }

    // Update the "X worker(s) selected" counter
    function updateWorkerCount() {
        var count = 0;
        addAdjWorkerCheckboxes.forEach(function(cb) {
            if (cb.checked) count++;
        });
        if (adjSelectedCount) adjSelectedCount.textContent = count;
        // Hide the error message when workers are selected
        if (addAdjWorkerError && count > 0) {
            addAdjWorkerError.style.display = 'none';
        }
    }
    addAdjWorkerCheckboxes.forEach(function(cb) {
        cb.addEventListener('change', updateWorkerCount);
    });

    // Select All / Deselect All links
    var adjSelectAllLink = document.getElementById('adjSelectAll');
    var adjDeselectAllLink = document.getElementById('adjDeselectAll');
    if (adjSelectAllLink) {
        adjSelectAllLink.addEventListener('click', function(e) {
            e.preventDefault();
            addAdjWorkerCheckboxes.forEach(function(cb) { cb.checked = true; });
            updateWorkerCount();
        });
    }
    if (adjDeselectAllLink) {
        adjDeselectAllLink.addEventListener('click', function(e) {
            e.preventDefault();
            addAdjWorkerCheckboxes.forEach(function(cb) { cb.checked = false; });
            updateWorkerCount();
        });
    }

    // Team quick-select: check workers in that team
    if (addAdjTeamSelect) {
        addAdjTeamSelect.addEventListener('change', function() {
            var teamId = this.value;
            if (!teamId) return;
            var workerIds = teamWorkersMap[teamId] || [];
            addAdjWorkerCheckboxes.forEach(function(cb) {
                if (workerIds.indexOf(parseInt(cb.value)) !== -1) {
                    cb.checked = true;
                }
            });
            updateWorkerCount();
        });
    }

    // === QUICK ADJUST BUTTON ===
    // Opens the Add Adjustment modal with one worker pre-checked
    // and their most recent project pre-selected.
    var _quickAdjustOpen = false;  // Flag to distinguish quick-adjust from header button
    document.querySelectorAll('.quick-adjust-btn').forEach(function(btn) {
        btn.addEventListener('click', function() {
            _quickAdjustOpen = true;
            var workerId = this.dataset.workerId;
            var projectId = this.dataset.workerProject;

            // Uncheck all workers, then check only the target worker
            addAdjWorkerCheckboxes.forEach(function(cb) {
                cb.checked = (cb.value === workerId);
            });
            updateWorkerCount();

            // Pre-select the worker's most recent project (if available)
            if (projectId && addAdjProject) {
                addAdjProject.value = projectId;
            }

            // Reset type to default (Bonus) and trigger field visibility update
            if (addAdjType) {
                addAdjType.value = 'Bonus';
                toggleProjectField();
            }

            // Open the modal
            var modal = new bootstrap.Modal(document.getElementById('addAdjustmentModal'));
            modal.show();
        });
    });

    // When the modal is opened from the HEADER button (not quick-adjust),
    // clear any pre-selected workers and project from a previous quick-adjust.
    var addAdjModal = document.getElementById('addAdjustmentModal');
    if (addAdjModal) {
        addAdjModal.addEventListener('show.bs.modal', function() {
            if (_quickAdjustOpen) {
                _quickAdjustOpen = false;
                return;  // Quick-adjust already set the values
            }
            // Reset: uncheck all workers, clear project, reset type
            addAdjWorkerCheckboxes.forEach(function(cb) { cb.checked = false; });
            updateWorkerCount();
            if (addAdjProject) addAdjProject.value = '';
            if (addAdjType) {
                addAdjType.value = 'Bonus';
                toggleProjectField();
            }
        });
    }

    // Form validation: ensure at least one worker is selected before submit.
    // Without this, the form would submit and silently create 0 adjustments.
    var addAdjForm = document.querySelector('#addAdjustmentModal form');
    if (addAdjForm) {
        addAdjForm.addEventListener('submit', function(e) {
            var anyChecked = false;
            addAdjWorkerCheckboxes.forEach(function(cb) {
                if (cb.checked) anyChecked = true;
            });
            if (!anyChecked) {
                e.preventDefault();
                if (addAdjWorkerError) {
                    addAdjWorkerError.style.display = 'block';
                }
                // Scroll to the workers section so the error is visible
                var workersLabel = addAdjForm.querySelector('.col-12');
                if (workersLabel) workersLabel.scrollIntoView({behavior: 'smooth', block: 'center'});
                return false;
            }
        });
    }

    // =================================================================
    // EDIT ADJUSTMENT — Click badge to open edit modal
    // =================================================================
    document.querySelectorAll('.adjustment-badge').forEach(function(badge) {
        badge.addEventListener('click', function() {
            const adjId = this.dataset.adjId;
            const adjType = this.dataset.adjType;
            const adjAmount = this.dataset.adjAmount;
            const adjDate = this.dataset.adjDate;
            const adjDesc = this.dataset.adjDescription;
            const adjProject = this.dataset.adjProject;
            const adjWorker = this.dataset.adjWorker;

            // Set form action URL
            const editForm = document.getElementById('editAdjForm');
            editForm.action = '/payroll/adjustment/' + adjId + '/edit/';

            // Populate fields
            document.getElementById('editAdjWorkerName').textContent = adjWorker + ' — ' + adjType;
            document.getElementById('editAdjType').value = adjType;
            document.getElementById('editAdjAmount').value = adjAmount;
            document.getElementById('editAdjDate').value = adjDate;
            document.getElementById('editAdjDescription').value = adjDesc;

            // Pre-select project
            const editProjectSelect = document.getElementById('editAdjProject');
            editProjectSelect.value = adjProject || '';

            // Disable type field unless it's Bonus or Deduction
            const editTypeSelect = document.getElementById('editAdjType');
            if (adjType !== 'Bonus' && adjType !== 'Deduction') {
                editTypeSelect.disabled = true;
            } else {
                editTypeSelect.disabled = false;
            }

            // Wire delete button
            document.getElementById('editAdjDeleteBtn').onclick = function() {
                const deleteForm = document.getElementById('deleteAdjForm');
                deleteForm.action = '/payroll/adjustment/' + adjId + '/delete/';
                document.getElementById('deleteAdjType').textContent = adjType;
                document.getElementById('deleteAdjWorker').textContent = adjWorker;
                // Close edit modal, open delete modal
                var editModal = bootstrap.Modal.getOrCreateInstance(document.getElementById('editAdjustmentModal'));
                editModal.hide();
                // Wait for edit modal to finish hiding before showing delete modal
                document.getElementById('editAdjustmentModal').addEventListener('hidden.bs.modal', function handler() {
                    document.getElementById('editAdjustmentModal').removeEventListener('hidden.bs.modal', handler);
                    bootstrap.Modal.getOrCreateInstance(document.getElementById('deleteConfirmModal')).show();
                });
            };

            // Show the modal
            bootstrap.Modal.getOrCreateInstance(document.getElementById('editAdjustmentModal')).show();
        });
    });

    // =================================================================
    // PREVIEW PAYSLIP — Fetch JSON and build DOM (no innerHTML for data)
    // Refactored into refreshPreview() so we can re-fetch after adding
    // a repayment from the inline form inside the modal.
    // Now also supports SPLIT PAYSLIP — checkboxes on logs and adjustments,
    // a "Split at Pay Date" button, and a "Pay Selected" submit button.
    // =================================================================

    // Helper: fetch preview data and build the modal content
    function refreshPreview(workerId, modalBody) {
        // Show loading spinner (safe hardcoded content)
        while (modalBody.firstChild) modalBody.removeChild(modalBody.firstChild);
        var loadingDiv = document.createElement('div');
        loadingDiv.className = 'text-center py-4';
        var spinner = document.createElement('div');
        spinner.className = 'spinner-border text-primary';
        spinner.setAttribute('role', 'status');
        loadingDiv.appendChild(spinner);
        var loadingText = document.createElement('p');
        loadingText.className = 'text-muted mt-2 small';
        loadingText.textContent = 'Loading preview...';
        loadingDiv.appendChild(loadingText);
        modalBody.appendChild(loadingDiv);

        // Fetch preview data
        fetch('/payroll/preview/' + workerId + '/')
            .then(function(resp) {
                if (!resp.ok) throw new Error('Network error');
                return resp.json();
            })
            .then(function(data) {
                // Clear loading
                while (modalBody.firstChild) modalBody.removeChild(modalBody.firstChild);

                // === Build payslip preview using DOM methods ===

                // -------------------------------------------------------
                // We'll store references to elements that recalcNetPay()
                // needs to update when checkboxes change.
                // -------------------------------------------------------
                var earningsLabel, earningsVal, adjTotalVal, netVal, negWarnDiv;

                // === RECALCULATE NET PAY ===
                // Called whenever a log or adjustment checkbox changes.
                // Counts checked items and recalculates the displayed totals.
                function recalcNetPay() {
                    var checkedLogs = modalBody.querySelectorAll('.log-checkbox:checked');
                    var logTotal = checkedLogs.length * data.day_rate;

                    var adjSum = 0;
                    modalBody.querySelectorAll('.adj-checkbox:checked').forEach(function(cb) {
                        var amt = parseFloat(cb.dataset.adjAmount);
                        adjSum += (cb.dataset.adjSign === '+') ? amt : -amt;
                    });

                    var net = logTotal + adjSum;

                    // Update the earnings line
                    if (earningsLabel) earningsLabel.textContent = checkedLogs.length + ' day(s) \u00d7 ' + fmt(data.day_rate);
                    if (earningsVal) earningsVal.textContent = fmt(logTotal);

                    // Update adjustment total
                    if (adjTotalVal) {
                        adjTotalVal.textContent = (adjSum >= 0 ? '+' : '') + fmt(adjSum);
                        adjTotalVal.className = adjSum >= 0 ? 'text-success' : 'text-danger';
                    }

                    // Update net pay
                    if (netVal) {
                        netVal.textContent = fmt(net);
                        netVal.className = 'fw-bold ' + (net >= 0 ? 'text-success' : 'text-danger');
                    }

                    // Show or hide the negative pay warning
                    if (negWarnDiv) {
                        negWarnDiv.style.display = net < 0 ? '' : 'none';
                    }
                }

                // Worker header
                var header = document.createElement('div');
                header.className = 'border-bottom pb-3 mb-3';
                var h4 = document.createElement('h4');
                h4.className = 'mb-1';
                h4.textContent = data.worker_name;
                header.appendChild(h4);
                if (data.worker_id_number) {
                    var idP = document.createElement('p');
                    idP.className = 'text-muted small mb-0';
                    idP.textContent = 'ID: ' + data.worker_id_number;
                    header.appendChild(idP);
                }
                modalBody.appendChild(header);

                // =============================================================
                // WORK LOGS WITH CHECKBOXES — select which days to pay
                // =============================================================
                if (data.logs && data.logs.length > 0) {

                    // --- "Split at Pay Date" button (only if team has a schedule) ---
                    if (data.pay_period && data.pay_period.has_schedule) {
                        var periodInfo = document.createElement('div');
                        periodInfo.className = 'alert alert-info py-2 px-3 small mb-2';
                        periodInfo.style.backgroundColor = '#e0f2fe';
                        periodInfo.style.borderColor = '#7dd3fc';
                        periodInfo.style.color = '#0c4a6e';

                        var infoIcon = document.createElement('i');
                        infoIcon.className = 'fas fa-calendar-alt me-2';
                        periodInfo.appendChild(infoIcon);
                        // Show current period info + cutoff date
                        // cutoff_date = end of the last COMPLETED period (everything due for payment)
                        periodInfo.appendChild(document.createTextNode(
                            data.pay_period.team_name + ' \u2014 ' +
                            data.pay_period.frequency + ' | Current period: ' +
                            data.pay_period.start + ' to ' + data.pay_period.end +
                            ' | Pay through: ' + data.pay_period.cutoff_date
                        ));
                        modalBody.appendChild(periodInfo);

                        var splitBtn = document.createElement('button');
                        splitBtn.type = 'button';
                        splitBtn.className = 'btn btn-sm btn-outline-warning mb-3';
                        var splitIcon = document.createElement('i');
                        splitIcon.className = 'fas fa-cut me-1';
                        splitBtn.appendChild(splitIcon);
                        splitBtn.appendChild(document.createTextNode(
                            'Split at Pay Date (up to ' + data.pay_period.cutoff_date + ')'
                        ));
                        splitBtn.addEventListener('click', function() {
                            // Use cutoff_date (end of last completed period) — includes ALL
                            // overdue work, not just one period. Leaves current in-progress
                            // period for the next pay run.
                            var cutoff = data.pay_period.cutoff_date;
                            // Uncheck logs after the cutoff date
                            modalBody.querySelectorAll('.log-checkbox').forEach(function(cb) {
                                cb.checked = (cb.dataset.logDate <= cutoff);
                            });
                            // Uncheck adjustments after the cutoff date
                            modalBody.querySelectorAll('.adj-checkbox').forEach(function(cb) {
                                cb.checked = (cb.dataset.adjDate <= cutoff);
                            });
                            recalcNetPay();
                        });
                        modalBody.appendChild(splitBtn);
                    }

                    var logsH6 = document.createElement('h6');
                    logsH6.className = 'fw-bold mb-2';
                    logsH6.textContent = 'Work Logs';
                    modalBody.appendChild(logsH6);

                    var table = document.createElement('table');
                    table.className = 'table table-sm mb-2';
                    var thead = document.createElement('thead');
                    var headRow = document.createElement('tr');

                    // "Select All" checkbox in header
                    var thCb = document.createElement('th');
                    thCb.style.width = '35px';
                    var selectAllLog = document.createElement('input');
                    selectAllLog.type = 'checkbox';
                    selectAllLog.className = 'form-check-input';
                    selectAllLog.checked = true;
                    selectAllLog.title = 'Select All / None';
                    selectAllLog.addEventListener('change', function() {
                        var checked = selectAllLog.checked;
                        modalBody.querySelectorAll('.log-checkbox').forEach(function(cb) {
                            cb.checked = checked;
                        });
                        recalcNetPay();
                    });
                    thCb.appendChild(selectAllLog);
                    headRow.appendChild(thCb);

                    ['Date', 'Project'].forEach(function(h) {
                        var th = document.createElement('th');
                        th.textContent = h;
                        headRow.appendChild(th);
                    });
                    thead.appendChild(headRow);
                    table.appendChild(thead);

                    var tbody = document.createElement('tbody');
                    data.logs.forEach(function(log) {
                        var tr = document.createElement('tr');

                        // Checkbox cell
                        var cbTd = document.createElement('td');
                        var cb = document.createElement('input');
                        cb.type = 'checkbox';
                        cb.className = 'form-check-input log-checkbox';
                        cb.checked = true;
                        cb.dataset.logId = log.id;
                        cb.dataset.logDate = log.date;
                        cb.addEventListener('change', recalcNetPay);
                        cbTd.appendChild(cb);
                        tr.appendChild(cbTd);

                        tr.appendChild(createTd(log.date));
                        tr.appendChild(createTd(log.project));
                        tbody.appendChild(tr);
                    });
                    table.appendChild(tbody);
                    modalBody.appendChild(table);
                }

                // =============================================================
                // EARNINGS SUMMARY — updates dynamically when checkboxes change
                // =============================================================
                var earningsH6 = document.createElement('h6');
                earningsH6.className = 'fw-bold mb-2';
                earningsH6.textContent = 'Earnings';
                modalBody.appendChild(earningsH6);

                var earningsRow = document.createElement('div');
                earningsRow.className = 'd-flex justify-content-between mb-1';
                earningsLabel = document.createElement('span');
                earningsLabel.textContent = data.days_worked + ' day(s) \u00d7 ' + fmt(data.day_rate);
                earningsRow.appendChild(earningsLabel);
                earningsVal = document.createElement('strong');
                earningsVal.textContent = fmt(data.log_amount);
                earningsRow.appendChild(earningsVal);
                modalBody.appendChild(earningsRow);

                // =============================================================
                // ADJUSTMENTS WITH CHECKBOXES — select which to include
                // =============================================================
                if (data.adjustments && data.adjustments.length > 0) {
                    var adjHr = document.createElement('hr');
                    modalBody.appendChild(adjHr);

                    var adjH6 = document.createElement('h6');
                    adjH6.className = 'fw-bold mb-2 d-flex justify-content-between align-items-center';

                    var adjTitle = document.createElement('span');
                    adjTitle.textContent = 'Adjustments';
                    adjH6.appendChild(adjTitle);

                    // "Select All" checkbox for adjustments
                    var adjSelectAllWrap = document.createElement('span');
                    adjSelectAllWrap.className = 'small fw-normal text-muted';
                    var selectAllAdj = document.createElement('input');
                    selectAllAdj.type = 'checkbox';
                    selectAllAdj.className = 'form-check-input me-1';
                    selectAllAdj.checked = true;
                    selectAllAdj.title = 'Select All / None';
                    selectAllAdj.addEventListener('change', function() {
                        var checked = selectAllAdj.checked;
                        modalBody.querySelectorAll('.adj-checkbox').forEach(function(cb) {
                            cb.checked = checked;
                        });
                        recalcNetPay();
                    });
                    adjSelectAllWrap.appendChild(selectAllAdj);
                    adjSelectAllWrap.appendChild(document.createTextNode('All'));
                    adjH6.appendChild(adjSelectAllWrap);

                    modalBody.appendChild(adjH6);

                    data.adjustments.forEach(function(adj) {
                        var row = document.createElement('div');
                        row.className = 'd-flex align-items-center mb-1';

                        // Checkbox
                        var cb = document.createElement('input');
                        cb.type = 'checkbox';
                        cb.className = 'form-check-input adj-checkbox me-2';
                        cb.checked = true;
                        cb.dataset.adjId = adj.id;
                        cb.dataset.adjDate = adj.date;
                        cb.dataset.adjAmount = adj.amount;
                        cb.dataset.adjSign = adj.sign;
                        cb.addEventListener('change', recalcNetPay);
                        row.appendChild(cb);

                        // Label + value wrapper (fills remaining space)
                        var labelWrap = document.createElement('div');
                        labelWrap.className = 'd-flex justify-content-between flex-grow-1';

                        var label = document.createElement('span');
                        label.textContent = adj.type + (adj.project ? ' (' + adj.project + ')' : '');
                        if (adj.description) {
                            var descSmall = document.createElement('small');
                            descSmall.className = 'text-muted ms-1';
                            descSmall.textContent = '\u2014 ' + adj.description;
                            label.appendChild(descSmall);
                        }
                        labelWrap.appendChild(label);

                        var val = document.createElement('span');
                        val.className = adj.sign === '+' ? 'text-success' : 'text-danger';
                        val.textContent = adj.sign + fmt(adj.amount);
                        labelWrap.appendChild(val);

                        row.appendChild(labelWrap);
                        modalBody.appendChild(row);
                    });

                    // Adjustment total line
                    var adjTotalRow = document.createElement('div');
                    adjTotalRow.className = 'd-flex justify-content-between mt-1 pt-1 border-top';
                    var adjTotalLabel = document.createElement('small');
                    adjTotalLabel.className = 'text-muted';
                    adjTotalLabel.textContent = 'Net adjustments';
                    adjTotalRow.appendChild(adjTotalLabel);
                    adjTotalVal = document.createElement('small');
                    adjTotalVal.className = data.adj_total >= 0 ? 'text-success' : 'text-danger';
                    adjTotalVal.textContent = (data.adj_total >= 0 ? '+' : '') + fmt(data.adj_total);
                    adjTotalRow.appendChild(adjTotalVal);
                    modalBody.appendChild(adjTotalRow);
                }

                // =============================================================
                // NET PAY — updates dynamically
                // =============================================================
                var netHr = document.createElement('hr');
                netHr.className = 'my-3';
                modalBody.appendChild(netHr);

                var netRow = document.createElement('div');
                netRow.className = 'd-flex justify-content-between';
                var netLabel = document.createElement('h5');
                netLabel.className = 'fw-bold';
                netLabel.textContent = 'Net Pay';
                netRow.appendChild(netLabel);
                netVal = document.createElement('h5');
                netVal.className = 'fw-bold ' + (data.net_pay >= 0 ? 'text-success' : 'text-danger');
                netVal.textContent = fmt(data.net_pay);
                netRow.appendChild(netVal);
                modalBody.appendChild(netRow);

                // === NEGATIVE NET PAY WARNING ===
                negWarnDiv = document.createElement('div');
                negWarnDiv.className = 'alert alert-warning py-2 px-3 small mt-2 mb-0';
                negWarnDiv.style.display = data.net_pay < 0 ? '' : 'none';
                var warnIcon = document.createElement('i');
                warnIcon.className = 'fas fa-exclamation-triangle me-2';
                negWarnDiv.appendChild(warnIcon);
                negWarnDiv.appendChild(document.createTextNode(
                    'Net pay is negative. Consider editing the Advance Repayment ' +
                    'amount on the Pending Payments table before processing.'
                ));
                modalBody.appendChild(negWarnDiv);

                // =============================================================
                // PAY SELECTED BUTTON — submits only checked logs/adjustments
                // =============================================================
                var payBtn = document.createElement('button');
                payBtn.type = 'button';
                payBtn.className = 'btn btn-accent w-100 mt-3';
                var payIcon = document.createElement('i');
                payIcon.className = 'fas fa-money-bill-wave me-2';
                payBtn.appendChild(payIcon);
                payBtn.appendChild(document.createTextNode('Pay Selected'));

                payBtn.addEventListener('click', function() {
                    // Gather checked log IDs
                    var logIds = [];
                    modalBody.querySelectorAll('.log-checkbox:checked').forEach(function(cb) {
                        logIds.push(cb.dataset.logId);
                    });
                    // Gather checked adjustment IDs
                    var adjIds = [];
                    modalBody.querySelectorAll('.adj-checkbox:checked').forEach(function(cb) {
                        adjIds.push(cb.dataset.adjId);
                    });

                    if (logIds.length === 0 && adjIds.length === 0) {
                        alert('Nothing selected to pay.');
                        return;
                    }

                    // Build a hidden form and submit it
                    var form = document.createElement('form');
                    form.method = 'POST';
                    form.action = '/payroll/pay/' + data.worker_id + '/';

                    // CSRF token
                    var csrf = document.createElement('input');
                    csrf.type = 'hidden';
                    csrf.name = 'csrfmiddlewaretoken';
                    csrf.value = '{{ csrf_token }}';
                    form.appendChild(csrf);

                    // Selected log IDs
                    logIds.forEach(function(lid) {
                        var inp = document.createElement('input');
                        inp.type = 'hidden';
                        inp.name = 'selected_log_ids';
                        inp.value = lid;
                        form.appendChild(inp);
                    });

                    // Selected adjustment IDs
                    adjIds.forEach(function(aid) {
                        var inp = document.createElement('input');
                        inp.type = 'hidden';
                        inp.name = 'selected_adj_ids';
                        inp.value = aid;
                        form.appendChild(inp);
                    });

                    document.body.appendChild(form);

                    // Prevent double-click
                    payBtn.disabled = true;
                    payBtn.textContent = '';
                    var procSpinner = document.createElement('span');
                    procSpinner.className = 'spinner-border spinner-border-sm me-2';
                    payBtn.appendChild(procSpinner);
                    payBtn.appendChild(document.createTextNode('Processing...'));

                    form.submit();
                });
                modalBody.appendChild(payBtn);

                // =============================================================
                // OUTSTANDING LOANS & ADVANCES — shows active balances with
                // inline repayment forms so the admin can deduct right here.
                // =============================================================
                if (data.active_loans && data.active_loans.length > 0) {
                    var loansHr = document.createElement('hr');
                    loansHr.className = 'my-3';
                    modalBody.appendChild(loansHr);

                    var loansH6 = document.createElement('h6');
                    loansH6.className = 'fw-bold mb-2';
                    loansH6.textContent = 'Outstanding Loans & Advances';
                    modalBody.appendChild(loansH6);

                    data.active_loans.forEach(function(loan) {
                        // Card container for each loan/advance
                        var card = document.createElement('div');
                        card.className = 'border rounded p-2 mb-2';
                        card.style.backgroundColor = '#f8f9fa';

                        // Row 1: Type badge + Balance
                        var topRow = document.createElement('div');
                        topRow.className = 'd-flex justify-content-between align-items-center mb-1';

                        var badge = document.createElement('span');
                        badge.className = 'badge ' + (loan.type === 'advance' ? 'bg-info text-dark' : 'bg-primary');
                        badge.textContent = loan.type_label;
                        topRow.appendChild(badge);

                        var balSpan = document.createElement('span');
                        balSpan.className = 'fw-bold text-danger';
                        balSpan.textContent = 'Balance: ' + fmt(loan.balance);
                        topRow.appendChild(balSpan);
                        card.appendChild(topRow);

                        // Row 2: Details (principal, date, reason)
                        var detailRow = document.createElement('div');
                        detailRow.className = 'small text-muted mb-2';
                        detailRow.textContent = 'Principal: ' + fmt(loan.principal) + '  |  ' + loan.date;
                        if (loan.reason) {
                            detailRow.textContent += '  |  ' + loan.reason;
                        }
                        card.appendChild(detailRow);

                        // Row 3: Inline repayment form
                        var formRow = document.createElement('div');
                        formRow.className = 'd-flex gap-2 align-items-center';

                        var amtInput = document.createElement('input');
                        amtInput.type = 'number';
                        amtInput.className = 'form-control form-control-sm';
                        amtInput.style.maxWidth = '130px';
                        amtInput.placeholder = 'Amount';
                        amtInput.step = '0.01';
                        amtInput.min = '0.01';
                        amtInput.max = loan.balance;
                        amtInput.value = loan.balance;
                        formRow.appendChild(amtInput);

                        var noteInput = document.createElement('input');
                        noteInput.type = 'text';
                        noteInput.className = 'form-control form-control-sm';
                        noteInput.placeholder = 'Note (optional)';
                        noteInput.style.flex = '1';
                        formRow.appendChild(noteInput);

                        var deductBtn = document.createElement('button');
                        deductBtn.type = 'button';
                        deductBtn.className = 'btn btn-sm btn-outline-danger';
                        deductBtn.title = 'Add ' + loan.type_label + ' Repayment';
                        var btnIcon = document.createElement('i');
                        btnIcon.className = 'fas fa-minus-circle me-1';
                        deductBtn.appendChild(btnIcon);
                        deductBtn.appendChild(document.createTextNode('Deduct'));
                        formRow.appendChild(deductBtn);

                        card.appendChild(formRow);

                        // Wire up the "Deduct" button — POST via AJAX, then refresh
                        deductBtn.addEventListener('click', function() {
                            var repayAmt = parseFloat(amtInput.value);
                            if (!repayAmt || repayAmt <= 0) {
                                amtInput.classList.add('is-invalid');
                                return;
                            }
                            if (repayAmt > loan.balance) {
                                repayAmt = loan.balance;
                                amtInput.value = loan.balance;
                            }
                            amtInput.classList.remove('is-invalid');

                            // Disable form while submitting
                            deductBtn.disabled = true;
                            amtInput.disabled = true;
                            noteInput.disabled = true;
                            deductBtn.textContent = 'Adding...';

                            fetch('/payroll/repayment/' + workerId + '/', {
                                method: 'POST',
                                headers: {
                                    'X-CSRFToken': '{{ csrf_token }}',
                                    'Content-Type': 'application/json'
                                },
                                body: JSON.stringify({
                                    loan_id: loan.id,
                                    amount: repayAmt,
                                    description: noteInput.value
                                })
                            })
                            .then(function(resp) {
                                if (!resp.ok) return resp.json().then(function(e) { throw new Error(e.error || 'Error'); });
                                return resp.json();
                            })
                            .then(function(result) {
                                // Show brief success feedback
                                var msg = document.createElement('div');
                                msg.className = 'alert alert-success py-1 px-2 small mt-2 mb-0';
                                msg.textContent = result.message;
                                card.appendChild(msg);

                                // After a brief pause, re-fetch the entire preview
                                setTimeout(function() {
                                    refreshPreview(workerId, modalBody);
                                }, 800);
                            })
                            .catch(function(err) {
                                // Re-enable form on error
                                deductBtn.disabled = false;
                                amtInput.disabled = false;
                                noteInput.disabled = false;
                                deductBtn.textContent = '';
                                var errIcon2 = document.createElement('i');
                                errIcon2.className = 'fas fa-minus-circle me-1';
                                deductBtn.appendChild(errIcon2);
                                deductBtn.appendChild(document.createTextNode('Deduct'));

                                var errMsg = document.createElement('div');
                                errMsg.className = 'alert alert-danger py-1 px-2 small mt-2 mb-0';
                                errMsg.textContent = err.message || 'Something went wrong.';
                                card.appendChild(errMsg);
                                setTimeout(function() {
                                    if (errMsg.parentNode) errMsg.parentNode.removeChild(errMsg);
                                }, 3000);
                            });
                        });

                        modalBody.appendChild(card);
                    });
                }
            })
            .catch(function() {
                // Show error (safe hardcoded content)
                while (modalBody.firstChild) modalBody.removeChild(modalBody.firstChild);
                var errDiv = document.createElement('div');
                errDiv.className = 'text-center py-4 text-danger';
                var errIcon3 = document.createElement('i');
                errIcon3.className = 'fas fa-exclamation-triangle fs-3';
                errDiv.appendChild(errIcon3);
                var errText = document.createElement('p');
                errText.className = 'mt-2';
                errText.textContent = 'Could not load preview.';
                errDiv.appendChild(errText);
                modalBody.appendChild(errDiv);
            });
    }

    // Wire up preview buttons to call the reusable refreshPreview function
    document.querySelectorAll('.preview-payslip-btn').forEach(function(btn) {
        btn.addEventListener('click', function() {
            var workerId = this.dataset.workerId;
            var modalBody = document.getElementById('previewPayslipBody');

            // Show modal first, then fetch data
            bootstrap.Modal.getOrCreateInstance(document.getElementById('previewPayslipModal')).show();
            refreshPreview(workerId, modalBody);
        });
    });

    // =================================================================
    // PAY FORM — Disable button after click to prevent double-submission.
    // Shows a spinner so the user knows the payment is being processed.
    // Backend also has select_for_update() as a safety net in case the
    // frontend disable fails (slow JS on mobile, etc.).
    // =================================================================
    document.querySelectorAll('.pay-form').forEach(function(form) {
        form.addEventListener('submit', function(e) {
            var btn = this.querySelector('button[type="submit"]');
            // If already disabled, block the second submit entirely
            if (btn.disabled) {
                e.preventDefault();
                return false;
            }
            btn.disabled = true;
            // Replace button content with a spinner + "Processing..."
            while (btn.firstChild) btn.removeChild(btn.firstChild);
            var spinner = document.createElement('span');
            spinner.className = 'spinner-border spinner-border-sm me-2';
            spinner.setAttribute('role', 'status');
            btn.appendChild(spinner);
            btn.appendChild(document.createTextNode('Processing...'));
        });
    });

    // =================================================================
    // === BATCH PAY FLOW ===
    // Step 1: Click "Batch Pay" → fetch preview → show confirmation modal
    // Step 2: Click "Confirm & Pay All" → POST to batch_pay → redirect
    // =================================================================

    // --- Helper: Format number as money (e.g., 45320 → "45,320.00") ---
    function formatMoney(num) {
        return Number(num).toLocaleString('en-ZA', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    }

    // --- Helper: Build the "Skipped workers" collapsible section ---
    function buildSkippedSection(skipped) {
        var div = document.createElement('div');
        div.className = 'mt-2';

        var toggle = document.createElement('a');
        toggle.href = '#';
        toggle.className = 'text-muted small';
        var warnIcon = document.createElement('i');
        warnIcon.className = 'fas fa-exclamation-triangle me-1';
        toggle.appendChild(warnIcon);
        toggle.appendChild(document.createTextNode(skipped.length + ' worker(s) skipped '));
        var chevron = document.createElement('i');
        chevron.className = 'fas fa-chevron-down ms-1';
        toggle.appendChild(chevron);
        div.appendChild(toggle);

        var list = document.createElement('div');
        list.style.display = 'none';
        list.className = 'mt-2';

        var ul = document.createElement('ul');
        ul.className = 'list-unstyled small text-muted mb-0';
        skipped.forEach(function(s) {
            var li = document.createElement('li');
            li.textContent = s.worker_name + ' — ' + s.reason;
            ul.appendChild(li);
        });
        list.appendChild(ul);
        div.appendChild(list);

        toggle.addEventListener('click', function(e) {
            e.preventDefault();
            list.style.display = list.style.display === 'none' ? 'block' : 'none';
        });

        return div;
    }

    // --- Helper: Update batch summary when checkboxes change ---
    function updateBatchSummary(data, summaryEl) {
        var checked = document.querySelectorAll('.batch-worker-cb:checked');
        var count = checked.length;
        var total = 0;
        checked.forEach(function(cb) {
            var idx = parseInt(cb.dataset.index);
            total += data.eligible[idx].net_pay;
        });
        // Clear and rebuild summary safely
        while (summaryEl.firstChild) summaryEl.removeChild(summaryEl.firstChild);
        var leftSpan = document.createElement('span');
        var strong = document.createElement('strong');
        strong.textContent = count + ' worker(s)';
        leftSpan.appendChild(strong);
        leftSpan.appendChild(document.createTextNode(' selected for payment'));
        summaryEl.appendChild(leftSpan);
        var rightSpan = document.createElement('span');
        rightSpan.className = 'fw-bold';
        rightSpan.textContent = 'Total: R ' + formatMoney(total);
        summaryEl.appendChild(rightSpan);
    }

    // --- Helper: Build a table row for an eligible worker ---
    function buildWorkerRow(w, idx) {
        var tr = document.createElement('tr');
        tr.dataset.team = w.team_name;  // Used by team filter
        tr.dataset.hasLoan = w.has_loan ? 'true' : 'false';  // Used by loan filter

        // Checkbox cell
        var tdCb = document.createElement('td');
        var cb = document.createElement('input');
        cb.type = 'checkbox';
        cb.className = 'batch-worker-cb';
        cb.dataset.index = idx;
        cb.checked = true;
        tdCb.appendChild(cb);
        tr.appendChild(tdCb);

        // Worker name
        var tdName = document.createElement('td');
        tdName.textContent = w.worker_name;
        tr.appendChild(tdName);

        // Team badge
        var tdTeam = document.createElement('td');
        var badge = document.createElement('span');
        badge.className = 'badge bg-secondary';
        badge.textContent = w.team_name;
        tdTeam.appendChild(badge);
        tr.appendChild(tdTeam);

        // Period
        var tdPeriod = document.createElement('td');
        var small = document.createElement('small');
        small.textContent = w.period;
        tdPeriod.appendChild(small);
        tr.appendChild(tdPeriod);

        // Days
        var tdDays = document.createElement('td');
        tdDays.className = 'text-end';
        tdDays.textContent = w.days;
        tr.appendChild(tdDays);

        // Net pay
        var tdNet = document.createElement('td');
        tdNet.className = 'text-end fw-bold';
        tdNet.textContent = 'R ' + formatMoney(w.net_pay);
        tr.appendChild(tdNet);

        return tr;
    }

    // === BATCH PAY MODAL: Radio buttons control split mode ===
    // 'schedule' = split at last paydate (default), 'all' = pay everything unpaid

    // --- Helper: Load batch preview for the given mode ---
    // Persistent radio group reference (survives DOM removal/re-append)
    var _batchRadioGroup = null;

    function loadBatchPreview(mode) {
        var body = document.getElementById('batchPayModalBody');
        var footer = document.getElementById('batchPayModalFooter');
        footer.style.display = 'none';

        // Clear all content from modal body
        while (body.firstChild) body.removeChild(body.firstChild);

        // === Radio button group (created once, re-appended each time) ===
        if (!_batchRadioGroup) {
            _batchRadioGroup = document.createElement('div');
            _batchRadioGroup.id = 'batchModeRadioGroup';
            _batchRadioGroup.className = 'btn-group w-100 mb-3';
            _batchRadioGroup.setAttribute('role', 'group');

            // "Until Last Paydate" radio
            var radioSchedule = document.createElement('input');
            radioSchedule.type = 'radio';
            radioSchedule.className = 'btn-check';
            radioSchedule.name = 'batchMode';
            radioSchedule.id = 'batchModeSchedule';
            radioSchedule.value = 'schedule';
            radioSchedule.checked = (mode === 'schedule');
            _batchRadioGroup.appendChild(radioSchedule);

            var labelSchedule = document.createElement('label');
            labelSchedule.className = 'btn btn-outline-primary';
            labelSchedule.setAttribute('for', 'batchModeSchedule');
            var iconSchedule = document.createElement('i');
            iconSchedule.className = 'fas fa-calendar-check me-1';
            labelSchedule.appendChild(iconSchedule);
            labelSchedule.appendChild(document.createTextNode('Until Last Paydate'));
            _batchRadioGroup.appendChild(labelSchedule);

            // "Pay All" radio
            var radioAll = document.createElement('input');
            radioAll.type = 'radio';
            radioAll.className = 'btn-check';
            radioAll.name = 'batchMode';
            radioAll.id = 'batchModeAll';
            radioAll.value = 'all';
            radioAll.checked = (mode === 'all');
            _batchRadioGroup.appendChild(radioAll);

            var labelAll = document.createElement('label');
            labelAll.className = 'btn btn-outline-primary';
            labelAll.setAttribute('for', 'batchModeAll');
            var iconAll = document.createElement('i');
            iconAll.className = 'fas fa-list me-1';
            labelAll.appendChild(iconAll);
            labelAll.appendChild(document.createTextNode('Pay All'));
            _batchRadioGroup.appendChild(labelAll);

            // Re-fetch preview when radio changes
            radioSchedule.addEventListener('change', function() { loadBatchPreview('schedule'); });
            radioAll.addEventListener('change', function() { loadBatchPreview('all'); });
        }
        // Re-append radio group to DOM first, THEN set checked state.
        // Radio buttons only properly toggle siblings when attached to the DOM.
        body.appendChild(_batchRadioGroup);
        _batchRadioGroup.querySelector('#batchModeSchedule').checked = (mode === 'schedule');
        _batchRadioGroup.querySelector('#batchModeAll').checked = (mode === 'all');

        // Show loading spinner below radio buttons
        var loadDiv = document.createElement('div');
        loadDiv.className = 'text-center py-4';
        var spinner = document.createElement('div');
        spinner.className = 'spinner-border text-primary';
        spinner.setAttribute('role', 'status');
        loadDiv.appendChild(spinner);
        var loadText = document.createElement('p');
        loadText.className = 'text-muted mt-2 small';
        loadText.textContent = 'Calculating pay periods...';
        loadDiv.appendChild(loadText);
        body.appendChild(loadDiv);

        // Fetch batch pay preview with mode parameter
        fetch('/payroll/batch-pay/preview/?mode=' + mode)
            .then(function(resp) { return resp.json(); })
            .then(function(data) {
                // Clear everything except the radio group
                while (body.children.length > 1) body.removeChild(body.lastChild);

                // --- No eligible workers ---
                if (data.eligible.length === 0) {
                    var noData = document.createElement('div');
                    noData.className = 'text-center py-4';
                    var icon = document.createElement('i');
                    icon.className = 'fas fa-check-circle fa-3x text-muted mb-3 d-block';
                    noData.appendChild(icon);
                    var msg = document.createElement('p');
                    msg.className = 'text-muted';
                    if (mode === 'schedule') {
                        msg.textContent = 'No workers eligible for batch payment — no completed pay periods with unpaid work.';
                    } else {
                        msg.textContent = 'No workers with unpaid work found.';
                    }
                    noData.appendChild(msg);
                    body.appendChild(noData);

                    if (data.skipped.length > 0) {
                        body.appendChild(buildSkippedSection(data.skipped));
                    }
                    return;
                }

                // --- Team filter dropdown ---
                // Extract unique team names from the eligible workers
                var teamNames = [];
                data.eligible.forEach(function(w) {
                    if (teamNames.indexOf(w.team_name) === -1) teamNames.push(w.team_name);
                });
                teamNames.sort();

                var filterRow = document.createElement('div');
                filterRow.className = 'd-flex align-items-center gap-2 mb-3';

                var filterLabel = document.createElement('label');
                filterLabel.className = 'text-muted small mb-0';
                filterLabel.textContent = 'Filter by team:';
                filterLabel.setAttribute('for', 'batchTeamFilter');
                filterRow.appendChild(filterLabel);

                var filterSelect = document.createElement('select');
                filterSelect.id = 'batchTeamFilter';
                filterSelect.className = 'form-select form-select-sm';
                filterSelect.style.width = 'auto';

                var optAll = document.createElement('option');
                optAll.value = '';
                optAll.textContent = 'All Teams';
                filterSelect.appendChild(optAll);

                teamNames.forEach(function(name) {
                    var opt = document.createElement('option');
                    opt.value = name;
                    opt.textContent = name;
                    filterSelect.appendChild(opt);
                });
                filterRow.appendChild(filterSelect);

                // Loan filter dropdown (All / With loans only / Without loans)
                var batchLoanFilter = null;
                var anyHasLoan = data.eligible.some(function(w) { return w.has_loan; });
                if (anyHasLoan) {
                    var loanDiv = document.createElement('div');
                    loanDiv.className = 'd-flex align-items-center gap-2 ms-3';
                    var loanLabel = document.createElement('label');
                    loanLabel.className = 'text-muted small mb-0';
                    loanLabel.textContent = 'Loans:';
                    loanLabel.setAttribute('for', 'batchLoanFilter');
                    loanDiv.appendChild(loanLabel);
                    batchLoanFilter = document.createElement('select');
                    batchLoanFilter.id = 'batchLoanFilter';
                    batchLoanFilter.className = 'form-select form-select-sm';
                    batchLoanFilter.style.width = 'auto';
                    var opts = [['', 'All Workers'], ['with', 'With loans only'], ['without', 'Without loans']];
                    opts.forEach(function(o) {
                        var opt = document.createElement('option');
                        opt.value = o[0];
                        opt.textContent = o[1];
                        batchLoanFilter.appendChild(opt);
                    });
                    loanDiv.appendChild(batchLoanFilter);
                    filterRow.appendChild(loanDiv);
                }

                body.appendChild(filterRow);

                // --- Summary header ---
                var summary = document.createElement('div');
                summary.className = 'alert alert-info d-flex justify-content-between align-items-center mb-3';
                var leftSpan = document.createElement('span');
                var strong = document.createElement('strong');
                strong.textContent = data.worker_count + ' worker(s)';
                leftSpan.appendChild(strong);
                leftSpan.appendChild(document.createTextNode(' eligible for payment'));
                summary.appendChild(leftSpan);
                var rightSpan = document.createElement('span');
                rightSpan.className = 'fw-bold';
                rightSpan.textContent = 'Total: R ' + formatMoney(data.total_amount);
                summary.appendChild(rightSpan);
                body.appendChild(summary);

                // --- Eligible workers table ---
                var table = document.createElement('table');
                table.className = 'table table-sm table-hover mb-3';

                // Table header
                var thead = document.createElement('thead');
                var headerRow = document.createElement('tr');

                var thCb = document.createElement('th');
                thCb.style.width = '30px';
                var selectAllCb = document.createElement('input');
                selectAllCb.type = 'checkbox';
                selectAllCb.id = 'batchSelectAll';
                selectAllCb.checked = true;
                thCb.appendChild(selectAllCb);
                headerRow.appendChild(thCb);

                ['Worker', 'Team', 'Period'].forEach(function(text) {
                    var th = document.createElement('th');
                    th.textContent = text;
                    headerRow.appendChild(th);
                });
                ['Days', 'Net Pay'].forEach(function(text) {
                    var th = document.createElement('th');
                    th.className = 'text-end';
                    th.textContent = text;
                    headerRow.appendChild(th);
                });
                thead.appendChild(headerRow);
                table.appendChild(thead);

                // Table body
                var tbody = document.createElement('tbody');
                data.eligible.forEach(function(w, idx) {
                    tbody.appendChild(buildWorkerRow(w, idx));
                });
                table.appendChild(tbody);
                body.appendChild(table);

                // --- Select All checkbox behavior ---
                // Only affects VISIBLE rows (respects team filter)
                selectAllCb.addEventListener('change', function() {
                    var rows = tbody.querySelectorAll('tr');
                    for (var i = 0; i < rows.length; i++) {
                        if (rows[i].style.display !== 'none') {
                            rows[i].querySelector('.batch-worker-cb').checked = selectAllCb.checked;
                        }
                    }
                    updateBatchSummary(data, summary);
                });

                // Update summary when individual checkboxes change
                body.addEventListener('change', function(e) {
                    if (e.target.classList.contains('batch-worker-cb')) {
                        updateBatchSummary(data, summary);
                        // Check if all VISIBLE checkboxes are checked
                        var allChecked = true;
                        var rows = tbody.querySelectorAll('tr');
                        for (var i = 0; i < rows.length; i++) {
                            if (rows[i].style.display !== 'none') {
                                if (!rows[i].querySelector('.batch-worker-cb').checked) {
                                    allChecked = false; break;
                                }
                            }
                        }
                        selectAllCb.checked = allChecked;
                    }
                });

                // --- Shared filter function (team + loan filters combined) ---
                function applyBatchFilters() {
                    var selectedTeam = filterSelect.value;
                    var loanMode = batchLoanFilter ? batchLoanFilter.value : '';
                    var rows = tbody.querySelectorAll('tr');
                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i];
                        var teamMatch = !selectedTeam || row.dataset.team === selectedTeam;
                        var loanMatch = !loanMode
                            || (loanMode === 'with' && row.dataset.hasLoan === 'true')
                            || (loanMode === 'without' && row.dataset.hasLoan !== 'true');
                        if (teamMatch && loanMatch) {
                            row.style.display = '';
                            row.querySelector('.batch-worker-cb').checked = true;
                        } else {
                            row.style.display = 'none';
                            row.querySelector('.batch-worker-cb').checked = false;
                        }
                    }
                    selectAllCb.checked = true;
                    updateBatchSummary(data, summary);
                }

                filterSelect.addEventListener('change', applyBatchFilters);
                if (batchLoanFilter) {
                    batchLoanFilter.addEventListener('change', applyBatchFilters);
                }

                // --- Skipped workers (collapsible) ---
                if (data.skipped.length > 0) {
                    body.appendChild(buildSkippedSection(data.skipped));
                }

                // Store data for the confirm button
                window._batchPayData = data.eligible;

                // Show footer with Confirm button
                footer.style.display = '';

                // Reset confirm button state
                var cBtn = document.getElementById('confirmBatchPayBtn');
                cBtn.disabled = false;
                while (cBtn.firstChild) cBtn.removeChild(cBtn.firstChild);
                var btnIcon = document.createElement('i');
                btnIcon.className = 'fas fa-money-bill-wave me-1';
                cBtn.appendChild(btnIcon);
                cBtn.appendChild(document.createTextNode('Confirm & Pay All'));
            })
            .catch(function() {
                while (body.children.length > 1) body.removeChild(body.lastChild);
                var errDiv = document.createElement('div');
                errDiv.className = 'alert alert-danger';
                errDiv.textContent = 'Failed to load batch preview. Please try again.';
                body.appendChild(errDiv);
            });
    }

    var batchPayBtn = document.getElementById('batchPayBtn');
    if (batchPayBtn) {
        batchPayBtn.addEventListener('click', function() {
            var modal = new bootstrap.Modal(document.getElementById('batchPayModal'));
            // Reset radio group so it gets re-created fresh each time modal opens
            _batchRadioGroup = null;
            modal.show();
            // Default mode: split at last paydate
            loadBatchPreview('schedule');
        });
    }

    // --- Confirm & Pay All button ---
    var confirmBatchBtn = document.getElementById('confirmBatchPayBtn');
    if (confirmBatchBtn) {
        confirmBatchBtn.addEventListener('click', function() {
            var btn = this;

            // Gather checked workers
            var workers = [];
            document.querySelectorAll('.batch-worker-cb:checked').forEach(function(cb) {
                var idx = parseInt(cb.dataset.index);
                var w = window._batchPayData[idx];
                workers.push({
                    worker_id: w.worker_id,
                    log_ids: w.log_ids,
                    adj_ids: w.adj_ids,
                });
            });

            if (workers.length === 0) {
                alert('No workers selected. Check at least one worker to proceed.');
                return;
            }

            // Disable button and show processing state
            btn.disabled = true;
            while (btn.firstChild) btn.removeChild(btn.firstChild);
            var sp = document.createElement('span');
            sp.className = 'spinner-border spinner-border-sm me-2';
            sp.setAttribute('role', 'status');
            btn.appendChild(sp);
            btn.appendChild(document.createTextNode('Processing ' + workers.length + ' payment(s)...'));

            // POST to batch pay endpoint
            fetch('/payroll/batch-pay/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': '{{ csrf_token }}',
                },
                body: JSON.stringify({ workers: workers }),
            }).then(function() {
                // Redirect to refresh page and show Django success messages
                window.location.href = '/payroll/';
            }).catch(function() {
                btn.disabled = false;
                while (btn.firstChild) btn.removeChild(btn.firstChild);
                var retryIcon = document.createElement('i');
                retryIcon.className = 'fas fa-money-bill-wave me-1';
                btn.appendChild(retryIcon);
                btn.appendChild(document.createTextNode('Confirm & Pay All'));
                alert('Batch payment failed. Please try again.');
            });
        });
    }

    // ================================================================
    // === WORKER LOOKUP ===
    // Fetches a worker's financial report card via AJAX and displays
    // it in the Worker Lookup modal. Can be triggered by clicking any
    // worker name on the dashboard, or via the "Worker Lookup" button.
    // ================================================================

    var workerLookupModal = document.getElementById('workerLookupModal');
    var workerLookupSelect = document.getElementById('workerLookupSelect');
    var workerLookupBody = document.getElementById('workerLookupBody');
    var workerLookupBtn = document.getElementById('workerLookupBtn');

    // === HELPER: format a number as South African Rand ===
    function formatRand(amount) {
        return 'R ' + Number(amount).toLocaleString('en-ZA', {
            minimumFractionDigits: 2, maximumFractionDigits: 2
        });
    }

    // === HELPER: format a date string (YYYY-MM-DD) for display ===
    function formatDate(dateStr) {
        if (!dateStr) return '';
        var parts = dateStr.split('-');
        var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
        return parseInt(parts[2]) + ' ' + months[parseInt(parts[1]) - 1] + ' ' + parts[0];
    }

    // === HELPER: create a text element safely (no innerHTML with user data) ===
    function el(tag, className, text) {
        var node = document.createElement(tag);
        if (className) node.className = className;
        if (text !== undefined) node.textContent = text;
        return node;
    }

    // === LOAD WORKER DATA AND RENDER THE REPORT CARD ===
    function loadWorkerLookup(workerId) {
        // Show spinner while loading
        workerLookupBody.textContent = '';
        var spinner = el('div', 'text-center py-4');
        var spinEl = el('div', 'spinner-border text-primary');
        spinEl.setAttribute('role', 'status');
        spinner.appendChild(spinEl);
        spinner.appendChild(el('p', 'text-muted mt-2 small', 'Loading report card...'));
        workerLookupBody.appendChild(spinner);

        fetch('/payroll/worker-lookup/' + workerId + '/')
            .then(function(resp) { return resp.json(); })
            .then(function(data) {
                renderWorkerLookup(data);
            })
            .catch(function() {
                workerLookupBody.textContent = '';
                workerLookupBody.appendChild(
                    el('div', 'alert alert-danger', 'Failed to load worker data. Please try again.')
                );
            });
    }

    // === RENDER THE FULL REPORT CARD FROM JSON DATA ===
    function renderWorkerLookup(data) {
        workerLookupBody.textContent = '';

        // --- IDENTITY SECTION ---
        var identity = el('div', 'mb-4');
        identity.appendChild(el('h4', 'mb-1', data.name));

        var detailLine1 = el('div', 'text-muted small');
        detailLine1.appendChild(el('span', '', 'ID: ' + data.id_number));
        if (data.phone) {
            detailLine1.appendChild(document.createTextNode(' \u00B7 Phone: ' + data.phone));
        }
        identity.appendChild(detailLine1);

        var detailLine2 = el('div', 'text-muted small');
        if (data.employment_date) {
            detailLine2.appendChild(document.createTextNode('Employed: ' + formatDate(data.employment_date)));
        }
        if (data.team) {
            detailLine2.appendChild(document.createTextNode(' \u00B7 Team: ' + data.team));
        }
        identity.appendChild(detailLine2);

        if (data.current_project) {
            var projLine = el('div', 'text-muted small');
            projLine.appendChild(document.createTextNode(
                'Current Project: ' + data.current_project + ' \u00B7 ' + data.days_on_project + ' days on project'
            ));
            identity.appendChild(projLine);
        }

        workerLookupBody.appendChild(identity);

        // --- QUICK STATS (4 cards in a row) ---
        var statsRow = el('div', 'row g-2 mb-4');

        var stats = [
            { label: 'Amount Payable', value: data.amount_payable, color: '#0f172a' },
            { label: 'Outstanding Loans', value: data.outstanding_loans, color: '#f59e0b' },
            { label: 'Paid This Month', value: data.paid_this_month, color: '#10b981' },
            { label: 'Loans This Year', value: data.loans_this_year, color: '#ef4444' },
        ];

        stats.forEach(function(stat) {
            var col = el('div', 'col-6 col-md-3');
            var card = el('div', 'card border-0 shadow-sm h-100');
            var body = el('div', 'card-body text-center py-2 px-2');
            var label = el('div', 'text-uppercase small fw-bold mb-1');
            label.style.color = stat.color;
            label.style.fontSize = '0.65rem';
            label.textContent = stat.label;
            body.appendChild(label);
            body.appendChild(el('div', 'fw-bold', formatRand(stat.value)));
            card.appendChild(body);
            col.appendChild(card);
            statsRow.appendChild(col);
        });

        workerLookupBody.appendChild(statsRow);

        // --- RECENT ACTIVITY ---
        var actSection = el('div', 'mb-4');
        var actHeader = el('h6', 'text-muted small text-uppercase mb-2', 'Recent Activity');
        actSection.appendChild(actHeader);

        var activities = [
            { icon: 'fas fa-money-bill-wave', label: 'Last Payslip Paid', data: data.last_payslip, color: 'text-success' },
            { icon: 'fas fa-file-invoice-dollar', label: 'Last Loan Given', data: data.last_loan, color: 'text-primary' },
            { icon: 'fas fa-hand-holding-usd', label: 'Last Loan Repayment', data: data.last_repayment, color: 'text-info' },
            { icon: 'fas fa-bolt', label: 'Last Advance Paid', data: data.last_advance, color: 'text-warning' },
        ];

        activities.forEach(function(act) {
            var row = el('div', 'd-flex justify-content-between align-items-center py-2 border-bottom');
            var left = el('div', '');
            var icon = el('i', act.icon + ' me-2 ' + act.color);
            left.appendChild(icon);
            left.appendChild(document.createTextNode(act.label));
            row.appendChild(left);

            if (act.data) {
                var right = el('div', 'text-end');
                right.appendChild(el('span', 'fw-bold me-2', formatRand(act.data.amount)));
                right.appendChild(el('span', 'text-muted small', formatDate(act.data.date)));
                if (act.data.reason) {
                    right.appendChild(document.createTextNode(' '));
                    right.appendChild(el('span', 'text-muted small fst-italic', '(' + act.data.reason + ')'));
                }
                row.appendChild(right);
            } else {
                row.appendChild(el('span', 'text-muted small', 'None'));
            }

            actSection.appendChild(row);
        });

        workerLookupBody.appendChild(actSection);

        // --- ACTIVE LOANS TABLE (only shown if the worker has active loans) ---
        if (data.active_loans && data.active_loans.length > 0) {
            var loanSection = el('div', 'mb-4');
            loanSection.appendChild(el('h6', 'text-muted small text-uppercase mb-2', 'Active Loans'));

            var table = el('table', 'table table-sm table-hover mb-0');
            var thead = el('thead', 'table-light');
            var headRow = el('tr', '');
            ['Type', 'Amount', 'Balance', 'Date', 'Reason'].forEach(function(h) {
                headRow.appendChild(el('th', 'small', h));
            });
            thead.appendChild(headRow);
            table.appendChild(thead);

            var tbody = el('tbody', '');
            data.active_loans.forEach(function(loan) {
                var tr = el('tr', '');
                tr.appendChild(el('td', 'small', loan.type));
                tr.appendChild(el('td', 'small', formatRand(loan.principal)));
                tr.appendChild(el('td', 'small fw-bold', formatRand(loan.balance)));
                tr.appendChild(el('td', 'small', formatDate(loan.date)));
                tr.appendChild(el('td', 'small', loan.reason || '-'));
                tbody.appendChild(tr);
            });
            table.appendChild(tbody);

            var tableWrap = el('div', 'table-responsive');
            tableWrap.appendChild(table);
            loanSection.appendChild(tableWrap);
            workerLookupBody.appendChild(loanSection);
        }

        // --- PAID THIS YEAR ---
        var yearSection = el('div', 'mb-4 p-3 rounded');
        yearSection.style.backgroundColor = '#f1f5f9';
        var yearLabel = el('span', 'text-muted small text-uppercase', 'Paid This Year: ');
        var yearValue = el('span', 'fw-bold', formatRand(data.paid_this_year));
        yearSection.appendChild(yearLabel);
        yearSection.appendChild(yearValue);
        workerLookupBody.appendChild(yearSection);

        // --- SIZING & INFO ---
        var infoSection = el('div', 'mb-2');
        infoSection.appendChild(el('h6', 'text-muted small text-uppercase mb-2', 'Sizing & Info'));

        // Sizing line — only show if at least one size is filled in
        var hasSizing = data.shoe_size || data.overall_top_size || data.pants_size || data.tshirt_size;
        if (hasSizing) {
            var sizeLine = el('div', 'small mb-1');
            var sizeParts = [];
            if (data.shoe_size) sizeParts.push('Shoe: ' + data.shoe_size);
            if (data.overall_top_size) sizeParts.push('Overall Top: ' + data.overall_top_size);
            if (data.pants_size) sizeParts.push('Pants: ' + data.pants_size);
            if (data.tshirt_size) sizeParts.push('T-Shirt: ' + data.tshirt_size);
            sizeLine.textContent = sizeParts.join(' \u00B7 ');
            infoSection.appendChild(sizeLine);
        }

        // Drivers license
        var licLine = el('div', 'small mb-1');
        licLine.textContent = 'Drivers License: ' + (data.has_drivers_license ? '\u2705 Yes' : '\u274C No');
        infoSection.appendChild(licLine);

        // Notes
        if (data.notes) {
            var notesLabel = el('div', 'small text-muted mt-2', 'Notes:');
            infoSection.appendChild(notesLabel);
            var notesText = el('div', 'small p-2 rounded');
            notesText.style.backgroundColor = '#f8f9fa';
            notesText.textContent = data.notes;
            infoSection.appendChild(notesText);
        }

        workerLookupBody.appendChild(infoSection);
    }

    // === EVENT LISTENERS ===

    // "Worker Lookup" button in header — opens modal with empty selection
    if (workerLookupBtn) {
        workerLookupBtn.addEventListener('click', function() {
            workerLookupSelect.value = '';
            workerLookupBody.textContent = '';
            var placeholder = el('div', 'text-center py-5 text-muted');
            placeholder.appendChild(el('i', 'fas fa-id-card fa-3x mb-3 opacity-25'));
            placeholder.appendChild(el('p', '', 'Select a worker to view their report card.'));
            workerLookupBody.appendChild(placeholder);
            var modal = new bootstrap.Modal(workerLookupModal);
            modal.show();
        });
    }

    // Dropdown change — load the selected worker's data
    if (workerLookupSelect) {
        workerLookupSelect.addEventListener('change', function() {
            if (this.value) {
                loadWorkerLookup(this.value);
            }
        });
    }

    // Clickable worker names — open modal with that worker pre-loaded
    document.querySelectorAll('.worker-lookup-link').forEach(function(link) {
        link.addEventListener('click', function(e) {
            e.preventDefault();
            var workerId = this.dataset.workerId;
            workerLookupSelect.value = workerId;
            loadWorkerLookup(workerId);
            var modal = new bootstrap.Modal(workerLookupModal);
            modal.show();
        });
    });

}); // end DOMContentLoaded
</script>

{% endblock %}
