<?php
$machineQuery = "
    SELECT 
        ((sm.id * 10) + pt.no_of_table) AS machine_id,
        CONCAT(sm.resource_code, ' - Table ', pt.no_of_table) AS resource_code
    FROM station_detail_table sm
    JOIN pu_mapping_tables pt 
        ON pt.machine_id = sm.id
    WHERE sm.machine_type = 4
      AND sm.hide = 0
    ORDER BY sm.resource_code, pt.no_of_table
";
$machineResult = $conn->query($machineQuery);
?>


<style>
    .container {
        max-width: 100%;
        margin: 0 auto;
        background: white;
        border-radius: 10px;
        box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        overflow: hidden;
    }

    .header {
		
        background: #2c3e50;
        color: white;
        padding: 2px 30px;
    }

    .header h1 {
        font-size: 21px;
        margin-bottom: 2px;
		margin-top: 5px;
    }

    .header p {
        opacity: 0.9;
        font-size: 14px;
    }

    .filters {
        padding: 20px 30px;
        background: #f8f9fa;
        border-bottom: 1px solid #e9ecef;
        display: flex;
        gap: 15px;
        flex-wrap: wrap;
        align-items: center;
    }

    .filter-group {
        display: flex;
        flex-direction: column;
        gap: 5px;
    }

    .filter-group label {
        font-size: 12px;
        font-weight: 600;
        color: #495057;
        text-transform: uppercase;
    }

    .filter-group input,
    .filter-group select {
        padding: 8px 12px;
        border: 1px solid #ced4da;
        border-radius: 5px;
        font-size: 14px;
        min-width: 180px;
    }

    .filter-group input:focus,
    .filter-group select:focus {
        outline: none;
        border-color: #3498db;
        box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
    }

    .btn-reset {
        padding: 8px 20px;
        background: #6c757d;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
        font-size: 14px;
        margin-top: 20px;
        transition: background 0.3s;
    }

    .btn-reset:hover {
        background: #5a6268;
    }

    .stats {
        padding: 15px 30px;
        background: #d1ecf1;
        border-bottom: 1px solid #bee5eb;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }

    .stats-item {
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .stats-item strong {
        color: #0c5460;
    }

    .table-wrapper {
        overflow-x: auto;
        padding: 20px 30px;
        min-height: 400px;
        position: relative;
    }

    .loading-overlay {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(255, 255, 255, 0.9);
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        z-index: 100;
    }

    .loading-overlay.hidden {
        display: none;
    }

    .spinner {
        border: 4px solid #f3f3f3;
        border-top: 4px solid #3498db;
        border-radius: 50%;
        width: 50px;
        height: 50px;
        animation: spin 1s linear infinite;
    }

    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }

    table {
        width: 100%;
        border-collapse: collapse;
        font-size: 14px;
    }

    thead {
        background: #f8f9fa;
        position: sticky;
        top: 0;
        z-index: 10;
    }

    th {
        padding: 12px 10px;
        text-align: left;
        font-weight: 600;
        color: #495057;
        border-bottom: 2px solid #dee2e6;
        white-space: nowrap;
    }

    td {
        padding: 12px 10px;
        border-bottom: 1px solid #e9ecef;
        color: #212529;
    }

    tbody tr {
        transition: background 0.2s;
    }

    tbody tr:hover {
        background: #f8f9fa;
    }

    .priority-badge {
        display: inline-block;
        padding: 4px 10px;
        border-radius: 12px;
        font-size: 12px;
        font-weight: 600;
        text-align: center;
        min-width: 60px;
    }

    .priority-1 { background: #dc3545; color: white; }
    .priority-2 { background: #fd7e14; color: white; }
    .priority-3 { background: #ffc107; color: #000; }
    .priority-4 { background: #28a745; color: white; }
    .priority-5 { background: #17a2b8; color: white; }

    .no-data {
        text-align: center;
        padding: 60px 20px;
        color: #6c757d;
    }

    .no-data svg {
        width: 80px;
        height: 80px;
        margin-bottom: 20px;
        opacity: 0.5;
    }

    .breakdown-indicator {
        color: #dc3545;
        font-weight: 600;
    }

    .table-indicator {
        display: inline-block;
        background: #3498db;
        color: white;
        padding: 2px 8px;
        border-radius: 4px;
        font-size: 12px;
        margin-left: 5px;
    }

    .text-muted {
        color: #6c757d;
        font-size: 12px;
    }

    .text-center {
        text-align: center;
    }

    .text-right {
        text-align: right;
    }

    .pagination-wrapper {
        padding: 20px 30px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-top: 1px solid #e9ecef;
        background: #f8f9fa;
    }

    .pagination {
        display: flex;
        gap: 5px;
        align-items: center;
    }

    .pagination a,
    .pagination span {
        padding: 8px 12px;
        border: 1px solid #dee2e6;
        background: white;
        color: #495057;
        text-decoration: none;
        border-radius: 5px;
        font-size: 14px;
        transition: all 0.2s;
        cursor: pointer;
    }

    .pagination a:hover {
        background: #3498db;
        color: white;
        border-color: #3498db;
    }

    .pagination .active {
        background: #3498db;
        color: white;
        border-color: #3498db;
        font-weight: 600;
    }

    .pagination .disabled {
        opacity: 0.5;
        cursor: not-allowed;
        pointer-events: none;
    }

    .per-page-selector {
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .per-page-selector select {
        padding: 8px 12px;
        border: 1px solid #ced4da;
        border-radius: 5px;
        font-size: 14px;
    }

    .hidden {
        display: none !important;
    }
	/* ===== PU DnD button ===== */
.btn-dnd {
    padding: 8px 20px;
    background: #2c3e50;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 14px;
    margin-top: 20px;
    transition: background 0.3s;
    display: inline-flex;
    align-items: center;
    gap: 7px;
}
.btn-dnd:hover { background: #1a252f; }

/* ===== PU DnD Modal ===== */
.dnd-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
}
.dnd-overlay.open { opacity: 1; pointer-events: all; }

.dnd-modal {
    background: #fff;
    border-radius: 12px;
    width: min(1400px, 98vw);
    height: min(900px, 95vh);
    display: flex;
    flex-direction: column;
    box-shadow: 0 20px 60px rgba(0,0,0,0.25);
    transform: translateY(20px);
    transition: transform 0.22s;
    overflow: hidden;
}
.dnd-overlay.open .dnd-modal { transform: translateY(0); }

.dnd-modal-header {
    background: #2c3e50;
    color: white;
    padding: 14px 22px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
}
.dnd-modal-header h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
}
.dnd-close {
    background: rgba(255,255,255,0.15);
    border: none;
    color: white;
    width: 30px; height: 30px;
    border-radius: 50%;
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s;
}
.dnd-close:hover { background: rgba(255,255,255,0.3); }

.dnd-machine-selectors {
    padding: 14px 20px;
    border-bottom: 1px solid #e9ecef;
    display: flex;
    gap: 20px;
    background: #f8f9fa;
    flex-shrink: 0;
    align-items: flex-start;
}
.dnd-side-controls { flex: 1; display: flex; flex-direction: column; gap: 10px; }

.dnd-sel-group { display: flex; flex-direction: column; gap: 5px; }
.dnd-sel-group label {
    font-size: 11px;
    font-weight: 700;
    color: #6c757d;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.dnd-sel-group select {
    padding: 8px 12px;
    border: 1px solid #ced4da;
    border-radius: 6px;
    font-size: 14px;
    background: white;
    color: #212529;
    width: 100%;
    cursor: pointer;
}
.dnd-sel-group select:focus {
    outline: none;
    border-color: #e67e22;
    box-shadow: 0 0 0 3px rgba(230,126,34,0.15);
}

/* Table pills — dynamic count per machine */
.dnd-table-pills-wrap {
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.dnd-table-pills-wrap label {
    font-size: 11px;
    font-weight: 700;
    color: #6c757d;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.dnd-table-pills {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    min-height: 34px;
    align-items: center;
}
.dnd-table-pill {
    padding: 6px 14px;
    border: 1.5px solid #ced4da;
    border-radius: 20px;
    background: white;
    font-size: 12px;
    font-weight: 600;
    color: #6c757d;
    cursor: pointer;
    transition: all 0.18s;
    white-space: nowrap;
}
.dnd-table-pill:hover { border-color: #e67e22; color: #e67e22; }
.dnd-table-pill.active {
    background: #e67e22;
    border-color: #e67e22;
    color: white;
}
.dnd-table-pills-loading {
    font-size: 12px;
    color: #adb5bd;
    font-style: italic;
}

.dnd-columns {
    display: flex;
    flex: 1;
    overflow: hidden;
}
.dnd-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.dnd-col:first-child { border-right: 1px solid #dee2e6; }

.dnd-col-header {
    padding: 10px 16px;
    background: #f8f9fa;
    border-bottom: 1px solid #e9ecef;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
}
.dnd-col-machine-name { font-weight: 700; font-size: 14px; color: #2c3e50; }
.dnd-col-meta { display: flex; align-items: center; gap: 8px; }
.dnd-col-count {
    font-size: 11px;
    background: #dee2e6;
    color: #495057;
    padding: 2px 8px;
    border-radius: 10px;
    font-weight: 600;
}
.dnd-col-table-badge {
    font-size: 11px;
    background: #e67e22;
    color: white;
    padding: 2px 8px;
    border-radius: 10px;
    font-weight: 600;
}

.dnd-col-body {
    flex: 1;
    overflow-y: auto;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-height: 100px;
    transition: background 0.15s;
}
.dnd-col-body.drag-over { background: #fef3e8; }

/* Task cards */
.pu-task-card {
    background: white;
    border: 1px solid #e9ecef;
    border-left: 4px solid #e67e22;
    border-radius: 7px;
    padding: 10px 12px;
    cursor: grab;
    user-select: none;
    transition: box-shadow 0.15s, opacity 0.15s, transform 0.1s;
}
.pu-task-card:hover { box-shadow: 0 2px 10px rgba(0,0,0,0.1); transform: translateY(-1px); }
.pu-task-card:active { cursor: grabbing; }
.pu-task-card.dragging { opacity: 0.3; }

.pu-task-card.border-p1 { border-left-color: #dc3545; }
.pu-task-card.border-p2 { border-left-color: #fd7e14; }
.pu-task-card.border-p3 { border-left-color: #ffc107; }
.pu-task-card.border-p4 { border-left-color: #28a745; }
.pu-task-card.border-p5 { border-left-color: #17a2b8; }

.pu-task-card.drag-placeholder {
    border: 2px dashed #e67e22;
    background: #fef3e8;
    border-left: 2px dashed #e67e22;
    height: 64px;
    border-radius: 7px;
    pointer-events: none;
}

.tc-wo   { font-size: 13px; font-weight: 700; color: #212529; margin-bottom: 2px; }
.tc-prod { font-size: 12px; color: #6c757d; margin-bottom: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tc-meta { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.tc-badge { font-size: 10px; padding: 2px 8px; border-radius: 10px; font-weight: 700; }
.tc-badge.p1 { background: #f8d7da; color: #721c24; }
.tc-badge.p2 { background: #fde8d0; color: #7d3c01; }
.tc-badge.p3 { background: #fff3cd; color: #856404; }
.tc-badge.p4 { background: #d4edda; color: #155724; }
.tc-badge.p5 { background: #d1ecf1; color: #0c5460; }
.tc-badge.tbl { background: #fde8d0; color: #7d3c01; }
.tc-hours { font-size: 10px; color: #adb5bd; font-weight: 600; }

.dnd-empty   { text-align: center; padding: 50px 16px; color: #adb5bd; font-size: 13px; }
.dnd-loading { text-align: center; padding: 50px 16px; font-size: 13px; color: #6c757d; }

.dnd-footer {
    padding: 10px 20px;
    border-top: 1px solid #e9ecef;
    background: #f8f9fa;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
}
.dnd-status { font-size: 12px; color: #6c757d; }
.dnd-status.ok     { color: #155724; font-weight: 600; }
.dnd-status.err    { color: #721c24; font-weight: 600; }
.dnd-status.saving { color: #004085; font-weight: 600; }

.btn-dnd-refresh {
    padding: 6px 16px;
    font-size: 12px;
    background: white;
    border: 1px solid #ced4da;
    border-radius: 5px;
    cursor: pointer;
    color: #495057;
    transition: background 0.2s;
}
.btn-dnd-refresh:hover { background: #e9ecef; }

/* Ghost */
#puDndGhost {
    position: fixed;
    pointer-events: none;
    z-index: 999999;
    background: white;
    border: 1px solid #dee2e6;
    border-left: 4px solid #e67e22;
    border-radius: 7px;
    padding: 8px 12px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    font-size: 12px;
    max-width: 240px;
    display: none;
    transform: rotate(2deg);
}
#puDndGhost .g-wo   { font-weight: 700; color: #212529; }
#puDndGhost .g-prod { color: #6c757d; font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
</style>

<div class="container">
    <div class="header">
        <h1>⚙️ PU Scheduler - Work Order List</h1>
        <p>View and filter PU machine work orders</p>
    </div>

    <div class="filters">
        <div class="filter-group">
            <label>Search Work Order</label>
            <input type="text" id="filterWorkOrder" placeholder="Enter work order number...">
        </div>
        <div class="filter-group">
            <label>Product Name</label>
            <input type="text" id="filterProduct" placeholder="Search product...">
        </div>
        <div class="filter-group">
            <label>Machine</label>
            <select id="filterMachine">
				<option value="">All Machines</option>
				<?php
				while ($machine = $machineResult->fetch_assoc()) {
					echo "<option value='{$machine['machine_id']}'>{$machine['resource_code']}</option>";
				}
				?>
			</select>
        </div>
        <div class="filter-group hide">
            <label>Priority</label>
            <select id="filterPriority">
                <option value="">All Priorities</option>
                <option value="1">Priority 1 (Highest)</option>
                <option value="2">Priority 2</option>
                <option value="3">Priority 3</option>
                <option value="4">Priority 4</option>
                <option value="5">Priority 5 (Lowest)</option>
            </select>
        </div>
        <div class="filter-group">
            <label>Start Date From</label>
            <input type="date" id="filterStartDate" value="<?php echo date('Y-m-d'); ?>">
        </div>
        <button class="btn-reset" onclick="resetFilters()">🔄 Reset Filters</button>
		<button class="btn-dnd" onclick="puOpenDnd()">
    <svg width="15" height="15" viewBox="0 0 16 16" fill="none">
        <rect x="1" y="2.5" width="6" height="11" rx="1.5" stroke="white" stroke-width="1.3"/>
        <rect x="9" y="2.5" width="6" height="11" rx="1.5" stroke="white" stroke-width="1.3"/>
        <path d="M7 8H9M9 8L7.5 6.5M9 8L7.5 9.5" stroke="white" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
    Drag &amp; Drop
</button>
    </div>

    <div class="stats">
        <div class="stats-item">
            <strong>Total Work Orders:</strong>
            <span id="totalCount">0</span>
        </div>
        <div class="stats-item">
            <strong>Showing:</strong>
            <span id="showingRange">0 - 0</span>
        </div>
        <div class="stats-item">
            <strong>Page:</strong>
            <span id="pageInfo">0 of 0</span>
        </div>
    </div>

    <div class="table-wrapper">
        <div id="loadingOverlay" class="loading-overlay">
            <div class="spinner"></div>
            <p style="margin-top: 15px; color: #3498db; font-weight: 600;">Loading CNC work orders...</p>
        </div>

        <div id="noDataMessage" class="no-data hidden">
            
            <h3>No PU Work Orders Found</h3>
            <p>There are no scheduled work orders matching your criteria.</p>
        </div>

        <table id="workOrderTable">
            <thead>
                <tr>
                    <th class="text-center hide">Priority</th>
                    <th>Work Order No.</th>
                    <th>Product Name</th>
                    <th>Machine</th>
                    <th class="text-center">Table</th>
                    <th class="text-center">Quantity</th>
					<th>Required Date</th>
                    <th>Start Date</th>
                    <th>End Date</th>
                    <th class="text-right">Total Hours</th>
                    <th class="text-right">Setup Hours</th>
                    <th>Customer Orders</th>
                    <th class="hide">Part Number</th>
                    <th class="hide">Status</th>
                </tr>
            </thead>
            <tbody id="tableBody">
                <!-- Data will be loaded via AJAX -->
            </tbody>
        </table>
    </div>

    <div id="paginationWrapper" class="pagination-wrapper hidden">
        <div class="per-page-selector">
            <label><strong>Records per page:</strong></label>
            <select id="perPageSelect" onchange="changePerPage(this.value)">
                <option value="25">25</option>
                <option value="50" selected>50</option>
                <option value="100">100</option>
                <option value="200">200</option>
                <option value="500">500</option>
            </select>
        </div>

        <div id="paginationControls" class="pagination">
            <!-- Pagination will be generated dynamically -->
        </div>
    </div>
</div>
<!-- ===== PU DRAG & DROP MODAL ===== -->
<div class="dnd-overlay" id="puDndOverlay">
    <div class="dnd-modal" role="dialog" aria-modal="true" aria-label="PU drag and drop scheduler">

        <div class="dnd-modal-header">
            <h3>
                <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
                    <rect x="1" y="2.5" width="6" height="11" rx="1.5" stroke="white" stroke-width="1.3"/>
                    <rect x="9" y="2.5" width="6" height="11" rx="1.5" stroke="white" stroke-width="1.3"/>
                    <path d="M7 8H9M9 8L7.5 6.5M9 8L7.5 9.5" stroke="white" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
                PU Drag &amp; Drop Task Scheduler
            </h3>
            <button class="dnd-close" onclick="puCloseDnd()" aria-label="Close">&times;</button>
        </div>

        <div class="dnd-machine-selectors">

            <!-- LEFT side controls -->
            <div class="dnd-side-controls">
                <div class="dnd-sel-group">
                    <label>Left Machine</label>
                    <select id="puDndMachineLeft" onchange="puDndOnMachineChange('left')">
                        <option value="">— Select a machine —</option>
                        <?php
                        // In your frontend PHP file — machine dropdown query for the DnD modal
$puMachineQuery = "
    SELECT DISTINCT sm.id AS machine_id, sm.resource_code
    FROM station_detail_table sm
    JOIN pu_mapping_tables pm ON pm.machine_id = sm.id
    WHERE sm.machine_type = 4 AND sm.hide = 0
    ORDER BY sm.resource_code
";
                        $puMachineResult = $conn->query($puMachineQuery);
                        while ($m = $puMachineResult->fetch_assoc()):
                        ?>
                            <option value="<?= $m['machine_id'] ?>"><?= htmlspecialchars($m['resource_code']) ?></option>
                        <?php endwhile; ?>
                    </select>
                </div>
                <div class="dnd-table-pills-wrap">
                    <label>Left Table (Virtual Machine)</label>
                    <div class="dnd-table-pills" id="puDndPillsLeft">
                        <span class="dnd-table-pills-loading">Select a machine first</span>
                    </div>
                </div>
            </div>

            <!-- RIGHT side controls -->
            <div class="dnd-side-controls">
                <div class="dnd-sel-group">
                    <label>Right Machine</label>
                    <select id="puDndMachineRight" onchange="puDndOnMachineChange('right')">
                        <option value="">— Select a machine —</option>
                        <?php
                        
						$puMachineQuery2 = "
    SELECT DISTINCT sm.id AS machine_id, sm.resource_code
    FROM station_detail_table sm
    JOIN pu_mapping_tables pm ON pm.machine_id = sm.id
    WHERE sm.machine_type = 4 AND sm.hide = 0
    ORDER BY sm.resource_code
";
                        $puMachineResult2 = $conn->query($puMachineQuery2);
                        while ($m = $puMachineResult2->fetch_assoc()):
                        ?>
                            <option value="<?= $m['machine_id'] ?>"><?= htmlspecialchars($m['resource_code']) ?></option>
                        <?php endwhile; ?>
                    </select>
                </div>
                <div class="dnd-table-pills-wrap">
                    <label>Right Table (Virtual Machine)</label>
                    <div class="dnd-table-pills" id="puDndPillsRight">
                        <span class="dnd-table-pills-loading">Select a machine first</span>
                    </div>
                </div>
            </div>

        </div>

        <!-- Kanban columns -->
        <div class="dnd-columns">
            <div class="dnd-col">
                <div class="dnd-col-header">
                    <span class="dnd-col-machine-name" id="puDndColLeftName">Left Machine</span>
                    <div class="dnd-col-meta">
                        <span class="dnd-col-table-badge" id="puDndColLeftBadge" style="display:none"></span>
                        <span class="dnd-col-count" id="puDndColLeftCount">0</span>
                    </div>
                </div>
                <div class="dnd-col-body" id="puDndBodyLeft" data-side="left">
                    <div class="dnd-empty">Select a machine and table above</div>
                </div>
            </div>
            <div class="dnd-col">
                <div class="dnd-col-header">
                    <span class="dnd-col-machine-name" id="puDndColRightName">Right Machine</span>
                    <div class="dnd-col-meta">
                        <span class="dnd-col-table-badge" id="puDndColRightBadge" style="display:none"></span>
                        <span class="dnd-col-count" id="puDndColRightCount">0</span>
                    </div>
                </div>
                <div class="dnd-col-body" id="puDndBodyRight" data-side="right">
                    <div class="dnd-empty">Select a machine and table above</div>
                </div>
            </div>
        </div>

        <div class="dnd-footer">
            <span class="dnd-status" id="puDndStatus">Select machines and tables to load tasks</span>
            <button class="btn-dnd-refresh" onclick="puDndRefreshBoth()">&#8635; Refresh</button>
        </div>
    </div>
</div>

<!-- Ghost -->
<div id="puDndGhost">
    <div class="g-wo"   id="puDndGhostWo"></div>
    <div class="g-prod" id="puDndGhostProd"></div>
</div>
<script>
    // Global state
    let currentPage = 1;
    let perPage = 50;
    let totalPages = 0;

    // Load data on page load
    document.addEventListener('DOMContentLoaded', function() {
        loadData();
    });

    // Filter change handlers
    document.getElementById('filterWorkOrder').addEventListener('input', debounce(loadData, 500));
    document.getElementById('filterProduct').addEventListener('input', debounce(loadData, 500));
    document.getElementById('filterMachine').addEventListener('change', loadData);
    document.getElementById('filterPriority').addEventListener('change', loadData);
    document.getElementById('filterStartDate').addEventListener('change', loadData);

    // Debounce function for text inputs
    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }

    // Load data via AJAX
    function loadData(resetPage = true) {
        if (resetPage) {
            currentPage = 1;
        }

        const params = new URLSearchParams({
            current_page: currentPage,
            per_page: perPage,
            start_date: document.getElementById('filterStartDate').value,
            work_order: document.getElementById('filterWorkOrder').value,
            product: document.getElementById('filterProduct').value,
            machine: document.getElementById('filterMachine').value,
            priority: document.getElementById('filterPriority').value
        });

        // Show loading
        document.getElementById('loadingOverlay').classList.remove('hidden');
        document.getElementById('noDataMessage').classList.add('hidden');
        document.getElementById('workOrderTable').style.opacity = '0.3';

        // Use site_url routing pattern
        const url = site_url +
  "/modules/machines_management/index.php?page=ajax_pu_list_data&" +
  params.toString();


        fetch(url)
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    renderTable(data.data);
                    updatePagination(data.pagination);
                    updateStats(data.pagination);
                } else {
                    console.error('Error:', data.error);
                    alert('Error loading data: ' + data.error);
                }
            })
            .catch(error => {
                console.error('Error:', error);
                const errorMsg = error.message || 'Please try again or refresh the page';
                alert(`Error loading data: ${errorMsg}`);
                document.getElementById('tableBody').innerHTML = `
                    <tr>
                        <td colspan="13" class="text-center" style="padding: 40px; color: #e74c3c;">
                            <div style="font-size: 18px; font-weight: bold;">Error loading data</div>
                            <div style="font-size: 14px; margin-top: 10px;">${errorMsg}</div>
                        </td>
                    </tr>
                `;
            })
            .finally(() => {
                document.getElementById('loadingOverlay').classList.add('hidden');
                document.getElementById('workOrderTable').style.opacity = '1';
            });
    }

    // Render table rows (UPDATED - removed setting_instruction)
    function renderTable(workOrders) {
        const tbody = document.getElementById('tableBody');
        const noDataMsg = document.getElementById('noDataMessage');

        if (workOrders.length === 0) {
            tbody.innerHTML = '';
            noDataMsg.classList.remove('hidden');
            return;
        }

        noDataMsg.classList.add('hidden');

        tbody.innerHTML = workOrders.map(row => {
            const startDate = new Date(row.start_date);
            const endDate = new Date(row.end_date);
            const startTime = row.start_time ? formatTime(row.start_time) : '';
            const machineName = row.machine_name || row.task || 'N/A';
            const productName = row.product_name || row.work_order_name || '';
            
            // Check if manufacture_description exists and add it as extra info
            const extraInfo = row.manufacture_description ? 
                `<br><span class="text-muted">${escapeHtml(row.manufacture_description.substring(0, 50))}</span>` : '';

            return `
                <tr>
                    <td class="text-center hide">
                        <span class="priority-badge priority-${row.priority}">
                            P${row.priority}
                        </span>
                    </td>
                    <td><strong>${escapeHtml(row.work_order_name || row.work_order_no)}</strong></td>
                    <td>
                        ${escapeHtml(productName)}
                        ${extraInfo}
                    </td>
                    <td>${escapeHtml(machineName)}</td>
                    <td class="text-center">
                        ${row.table_id ? '<span class="table-indicator">Table ' + row.table_id + '</span>' : '-'}
                    </td>
                    <td class="text-center"><strong>${formatNumber(row.quantity)}</strong></td>
					<td>${row.require_date ? formatDate(new Date(row.require_date)) : '-'}</td>
                    <td>
                        ${formatDate(startDate)}
                        ${startTime ? '<br><span class="text-muted">' + startTime + '</span>' : ''}
                    </td>
                    <td>${formatDate(endDate)}</td>
                    <td class="text-right"><strong>${formatNumber(row.total_hours, 2)}</strong> hrs</td>
                    <td class="text-right">${formatNumber(row.setup_hours, 2)} hrs</td>
                    <td>${escapeHtml(row.customer_order_nos || '-')}</td>
                    <td class="hide">${escapeHtml(row.parent_part_number || '-')}</td>
                    <td class="hide">
                        ${row.is_breakdown_affected == 1 
                            ? '<span class="breakdown-indicator">⚠️ Breakdown</span><br><span class="text-muted">' + escapeHtml(row.machine_breakdown_reason || '') + '</span>'
                            : (row.finished == 1 
                                ? '<span style="color: #6c757d;">✓ Completed</span>'
                                : '<span style="color: #28a745;">✓ Active</span>'
                              )
                        }
                    </td>
                </tr>
            `;
        }).join('');
    }

    // Update pagination controls
    function updatePagination(pagination) {
        totalPages = pagination.total_pages;
        const wrapper = document.getElementById('paginationWrapper');
        const controls = document.getElementById('paginationControls');

        if (totalPages <= 1) {
            wrapper.classList.add('hidden');
            return;
        }

        wrapper.classList.remove('hidden');

        let html = '';

        // First and Previous
        if (currentPage > 1) {
            html += `<a onclick="goToPage(1)">« First</a>`;
            html += `<a onclick="goToPage(${currentPage - 1})">‹ Prev</a>`;
        } else {
            html += `<span class="disabled">« First</span>`;
            html += `<span class="disabled">‹ Prev</span>`;
        }

        // Page numbers
        const startPage = Math.max(1, currentPage - 2);
        const endPage = Math.min(totalPages, currentPage + 2);

        if (startPage > 1) {
            html += '<span>...</span>';
        }

        for (let i = startPage; i <= endPage; i++) {
            if (i === currentPage) {
                html += `<span class="active">${i}</span>`;
            } else {
                html += `<a onclick="goToPage(${i})">${i}</a>`;
            }
        }

        if (endPage < totalPages) {
            html += '<span>...</span>';
        }

        // Next and Last
        if (currentPage < totalPages) {
            html += `<a onclick="goToPage(${currentPage + 1})">Next ›</a>`;
            html += `<a onclick="goToPage(${totalPages})">Last »</a>`;
        } else {
            html += `<span class="disabled">Next ›</span>`;
            html += `<span class="disabled">Last »</span>`;
        }

        controls.innerHTML = html;
    }

    // Update stats
    function updateStats(pagination) {
        document.getElementById('totalCount').textContent = formatNumber(pagination.total_records);
        document.getElementById('showingRange').textContent = 
            `${formatNumber(pagination.showing_from)} - ${formatNumber(pagination.showing_to)}`;
        document.getElementById('pageInfo').textContent = 
            `${pagination.current_page} of ${pagination.total_pages}`;
    }

    // Navigation functions
    function goToPage(page) {
        currentPage = page;
        loadData(false);
    }

    function changePerPage(newPerPage) {
        perPage = parseInt(newPerPage);
        currentPage = 1;
        loadData(false);
    }

    function resetFilters() {
        document.getElementById('filterWorkOrder').value = '';
        document.getElementById('filterProduct').value = '';
        document.getElementById('filterMachine').value = '';
        document.getElementById('filterPriority').value = '';
        document.getElementById('filterStartDate').value = '<?php echo date('Y-m-d'); ?>';
        loadData();
    }

    // Utility functions
    function escapeHtml(text) {
        if (!text) return '';
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    function formatNumber(num, decimals = 0) {
        if (!num) return '0';
        return parseFloat(num).toLocaleString('en-IN', {
            minimumFractionDigits: decimals,
            maximumFractionDigits: decimals
        });
    }

    function formatDate(date) {
        const options = { day: '2-digit', month: 'short', year: 'numeric' };
        return date.toLocaleDateString('en-GB', options);
    }

    function formatTime(timeStr) {
        const [hours, minutes] = timeStr.split(':');
        const hour = parseInt(hours);
        const ampm = hour >= 12 ? 'PM' : 'AM';
        const displayHour = hour % 12 || 12;
        return `${displayHour}:${minutes} ${ampm}`;
    }
</script>
<script>
/* =============================================
   PU DRAG & DROP SCHEDULER
   Key difference from CNC/VAC:
   - machine_id in pu_machine_table = virtual_id
     (encodes both physical machine + table slot)
   - Tables are loaded dynamically from server
     via ajax_pu_list_data?action=get_pu_tables
   - No setting_instruction, no dual-table logic
============================================= */

const PU_DATA_URL = site_url + '/modules/machines_management/index.php?page=ajax_pu_list_data';
const PU_SAVE_URL = site_url + '/modules/machines_management/index.php?page=ajax_pu_list_data';

// State — keyed by side ('left'|'right')
let puTasks         = { left: [], right: [] };
// Physical machine id selected per side
let puPhysicalIds   = { left: 0,  right: 0  };
// Virtual machine id (= actual machine_id in pu_machine_table) selected per side
let puVirtualIds    = { left: 0,  right: 0  };
// Table number (1-based slot) for display only
let puTableNums     = { left: 0,  right: 0  };
// Available virtual machines per side [{virtual_id, no_of_table, table_num}]
let puTableMaps     = { left: [], right: [] };

// Drag state
let puDragging    = null;
let puPlaceholder = null;
const puGhost     = document.getElementById('puDndGhost');

/* ---- Open / Close ---- */
function puOpenDnd()  { document.getElementById('puDndOverlay').classList.add('open'); }
function puCloseDnd() { document.getElementById('puDndOverlay').classList.remove('open'); }
document.getElementById('puDndOverlay').addEventListener('click', function(e) {
    if (e.target === this) puCloseDnd();
});

/* ---- Machine change: load virtual table list from server ---- */
async function puDndOnMachineChange(side) {
    const selEl = document.getElementById(side === 'left' ? 'puDndMachineLeft' : 'puDndMachineRight');
    const physId = parseInt(selEl.value) || 0;
    puPhysicalIds[side] = physId;
    puVirtualIds[side]  = 0;
    puTableNums[side]   = 0;
    puTableMaps[side]   = [];

    const nameEl = document.getElementById(side === 'left' ? 'puDndColLeftName' : 'puDndColRightName');
    nameEl.textContent = selEl.options[selEl.selectedIndex]?.text || (side + ' machine');

    puRenderColumn(side, []);

    const pillsEl = document.getElementById(side === 'left' ? 'puDndPillsLeft' : 'puDndPillsRight');

    if (!physId) {
        pillsEl.innerHTML = '<span class="dnd-table-pills-loading">Select a machine first</span>';
        return;
    }

    pillsEl.innerHTML = '<span class="dnd-table-pills-loading">⏳ Loading tables…</span>';

    try {
        // ✅ Use the EXISTING get_tables_by_machine action (POST, same as Gantt)
        const res = await fetch(
            site_url + '/modules/machines_management/index.php?page=ajax_actions_for_pu&action=get_tables_by_machine',
            { method: 'POST', body: new URLSearchParams({ machine_id: physId }) }
        );
        const dat = await res.json();

        if (!dat.success || !dat.tables || !Object.keys(dat.tables).length) {
            pillsEl.innerHTML = '<span class="dnd-table-pills-loading">No tables found</span>';
            return;
        }

        // dat.tables = { virtual_id: no_of_table_label, 121: "1", 122: "2" }
        // virtual_id is the key, value is the table label/count
        puTableMaps[side] = Object.entries(dat.tables).map(([virtualId, label]) => ({
            virtual_id: parseInt(virtualId),
            table_num:  parseInt(virtualId) % 10,  // last digit = table number
        }));

        pillsEl.innerHTML = '';
        let first = true;
        puTableMaps[side].forEach(t => {
            const pill = document.createElement('button');
            pill.className = 'dnd-table-pill' + (first ? ' active' : '');
            pill.textContent = 'Table ' + t.table_num;
            pill.dataset.virtualId = t.virtual_id;
            pill.addEventListener('click', () => puDndSelectTable(side, t.virtual_id, t.table_num, pill));
            pillsEl.appendChild(pill);
            if (first) {
                // Auto-select first table
                puDndSelectTable(side, t.virtual_id, t.table_num, pill);
                first = false;
            }
        });

    } catch(err) {
        pillsEl.innerHTML = '<span class="dnd-table-pills-loading">Failed to load tables</span>';
    }
}

/* ---- Table pill selected ---- */
function puDndSelectTable(side, virtualId, tableNum, pillEl) {
    puVirtualIds[side] = virtualId;
    puTableNums[side]  = tableNum;

    // Update pill active state
    const pillsEl = document.getElementById(side === 'left' ? 'puDndPillsLeft' : 'puDndPillsRight');
    pillsEl.querySelectorAll('.dnd-table-pill').forEach(p => p.classList.remove('active'));
    if (pillEl) pillEl.classList.add('active');

    // Update column header badge
    const badgeEl = document.getElementById(side === 'left' ? 'puDndColLeftBadge' : 'puDndColRightBadge');
    badgeEl.textContent = 'Table ' + tableNum;
    badgeEl.style.display = '';

    // Load tasks for this virtual machine
    puDndLoadColumn(side);
}

/* ---- Load tasks for one column ---- */
async function puDndLoadColumn(side) {
    const virtualId = puVirtualIds[side];
    if (!virtualId) { puRenderColumn(side, []); return; }

    const bodyEl = document.getElementById(side === 'left' ? 'puDndBodyLeft' : 'puDndBodyRight');
    bodyEl.innerHTML = '<div class="dnd-loading">⏳ Loading tasks…</div>';

    try {
        // machine filter = virtual_id → server returns only tasks for that machine+table
        const url = PU_DATA_URL + `&machine=${virtualId}&per_page=500&current_page=1`;
        const res = await fetch(url);
        const dat = await res.json();

        puTasks[side] = dat.success ? dat.data : [];
        puRenderColumn(side, puTasks[side]);
    } catch(err) {
        bodyEl.innerHTML = '<div class="dnd-empty">Failed to load tasks.</div>';
    }
}

/* ---- Render cards ---- */
function puRenderColumn(side, rows) {
    const bodyEl  = document.getElementById(side === 'left'  ? 'puDndBodyLeft'      : 'puDndBodyRight');
    const countEl = document.getElementById(side === 'left'  ? 'puDndColLeftCount'  : 'puDndColRightCount');
    countEl.textContent = rows.length;

    if (!rows.length) {
        bodyEl.innerHTML = '<div class="dnd-empty">No tasks found for this machine / table</div>';
        puSetupDropZone(bodyEl, side);
        return;
    }

    bodyEl.innerHTML = '';
    rows.forEach(row => bodyEl.appendChild(puMakeCard(row, side)));
    puSetupDropZone(bodyEl, side);
}

/* ---- Build one task card ---- */
function puMakeCard(row, side) {
    const card = document.createElement('div');
    const pNum = Math.min(Math.max(parseInt(row.priority) || 1, 1), 5);
    card.className = `pu-task-card border-p${pNum}`;
    card.draggable = true;

    card.dataset.taskId      = row.task_id      || '';
    card.dataset.workOrderId = row.work_order_id || '';
    card.dataset.partId      = row.part_id       || '';
    card.dataset.priority    = row.priority      || 0;
    card.dataset.virtualId   = row.task          || '';
    card.dataset.tableId     = row.table_id      || '';
    card.dataset.side        = side;

    card.innerHTML = `
    <div style="display:flex; align-items:flex-start; gap:10px;">

        <!-- LEFT: main info -->
        <div style="flex:1; min-width:0;">
            <div class="tc-wo" style="font-size:12px; font-weight:700; color:#212529; margin-bottom:1px;">
                ${escapeHtml(row.work_order_name || row.work_order_no || '—')}
            </div>
            <div class="tc-prod" style="font-size:12px; font-weight:700; color:#212529; margin-bottom:1px;"
                 title="${escapeHtml(row.product_name || row.work_order_name || '')}">
                ${escapeHtml(row.product_name || row.work_order_name || '—')}
            </div>
            <div style="font-size:11px; color:#6c757d; margin-bottom:1px;">
                Required: ${row.require_date ? formatDate(new Date(row.require_date)) : '—'}
            </div>
            <div style="font-size:11px; color:#495057; font-weight:600;">
                Qty: ${formatNumber(row.quantity || 0)}
            </div>
            <div class="tc-hours" style="font-size:10px; color:#adb5bd; font-weight:600; margin-top:2px;">
                ${parseFloat(row.total_hours || 0).toFixed(1)} hrs
            </div>
        </div>

        <!-- CENTER: setting instruction -->
        <div style="flex:0 0 200px; text-align:center;">
            <div style="font-size:10px; color:#6c757d;">Setting Instruction:</div>
            <div style="
                font-size:13px;
                font-weight:800;
                color:#212529;
                white-space:nowrap;
                overflow:hidden;
                text-overflow:ellipsis;
            ">
                ${escapeHtml(row.setting_instruction || '—')}
            </div>
        </div>

        <!-- RIGHT: component + inventory dots -->
         <div style="flex:0 0 180px; text-align:right;">
            <div>
                <div style="font-size:10px; color:#6c757d; margin-bottom:2px;">Component:</div>
                <div style="font-size:13px; font-weight:800; color:#212529;">
    ${(() => {
        const mats = Array.isArray(row.bought_in_materials) ? row.bought_in_materials : [];
        return mats.length ? escapeHtml(mats.join(', ')) : '—';
    })()}
</div>
                ${(() => {
                    // Bought-in material names
                    const mats = Array.isArray(row.bought_in_materials) ? row.bought_in_materials : [];
                    if (mats.length === 0) return '';
                    return '<div style="font-size:10px; color:#495057; margin-top:2px;">' +
                        mats.map(m => escapeHtml(m)).join(', ') +
                    '</div>';
                })()}
                ${(() => {
                    // Inventory dots — one per BOM sub-part
                    const dots = Array.isArray(row.inventory_dots) ? row.inventory_dots : [];
                    if (dots.length === 0) return '';
                    return '<div style="display:flex; gap:4px; flex-wrap:wrap; justify-content:flex-end; margin-top:4px;">' +
                        dots.map(d =>
                            `<span title="${escapeHtml(d.part_number || '')} — ${d.in_stock ? 'In Stock' : 'No Stock'}"
                                style="display:inline-block; width:10px; height:10px; border-radius:50%;
                                       background:${d.in_stock ? '#28a745' : '#dc3545'};
                                       flex-shrink:0;"></span>`
                        ).join('') +
                    '</div>';
                })()}
            </div>
            <!--<div style="
                width:12px; height:12px; border-radius:50%; margin-top:4px;
                background: ${row.finished == 1 ? '#28a745' : (row.quantity_made > 0 ? '#007bff' : '#ffc107')};
            " title="${row.finished == 1 ? 'Done' : (row.quantity_made > 0 ? 'In Progress' : 'Pending')}"></div>-->
        </div>

    </div>`;

    card.addEventListener('dragstart', puOnDragStart);
    card.addEventListener('dragend',   puOnDragEnd);
    return card;
}

/* ---- Drop zone ---- */
function puSetupDropZone(bodyEl, side) {
    const fresh = bodyEl.cloneNode(true);
    bodyEl.parentNode.replaceChild(fresh, bodyEl);

    fresh.querySelectorAll('.pu-task-card').forEach(c => {
        c.addEventListener('dragstart', puOnDragStart);
        c.addEventListener('dragend',   puOnDragEnd);
    });

    fresh.addEventListener('dragover', function(e) {
        e.preventDefault();
        fresh.classList.add('drag-over');
        if (puPlaceholder) {
            const after = puGetAfterElement(fresh, e.clientY);
            if (after) fresh.insertBefore(puPlaceholder, after);
            else        fresh.appendChild(puPlaceholder);
        }
    });

    fresh.addEventListener('dragleave', function(e) {
        if (!fresh.contains(e.relatedTarget)) fresh.classList.remove('drag-over');
    });

    fresh.addEventListener('drop', function(e) {
        e.preventDefault();
        fresh.classList.remove('drag-over');
        if (!puDragging) return;

        const destVirtualId = puVirtualIds[side];
        if (!destVirtualId) {
            puDndSetStatus('Please select a machine and table for this column first.', 'err');
            return;
        }

        const after    = puGetAfterElement(fresh, e.clientY);
        const allCards = [...fresh.querySelectorAll('.pu-task-card:not(.dragging):not(.drag-placeholder)')];
        let leftNeighborCard = null;

        if (after) {
            const idx = allCards.indexOf(after);
            leftNeighborCard = idx > 0 ? allCards[idx - 1] : null;
        } else {
            leftNeighborCard = allCards.length ? allCards[allCards.length - 1] : null;
        }

        puSaveMove(puDragging, destVirtualId, leftNeighborCard);
    });
}

/* ---- Drag events ---- */
function puOnDragStart(e) {
    puDragging = e.currentTarget;
    setTimeout(() => { if (puDragging) puDragging.classList.add('dragging'); }, 0);

    puPlaceholder = document.createElement('div');
    puPlaceholder.className = 'pu-task-card drag-placeholder';

    puGhost.style.display = 'block';
    document.getElementById('puDndGhostWo').textContent   = puDragging.querySelector('.tc-wo')?.textContent?.trim()   || '';
    document.getElementById('puDndGhostProd').textContent = puDragging.querySelector('.tc-prod')?.textContent?.trim() || '';
}

function puOnDragEnd() {
    if (puDragging) puDragging.classList.remove('dragging');
    if (puPlaceholder?.parentNode) puPlaceholder.parentNode.removeChild(puPlaceholder);
    document.querySelectorAll('.dnd-col-body').forEach(b => b.classList.remove('drag-over'));
    puGhost.style.display = 'none';
    puDragging    = null;
    puPlaceholder = null;
}

document.addEventListener('dragover', function(e) {
    puGhost.style.left = (e.clientX + 16) + 'px';
    puGhost.style.top  = (e.clientY + 10) + 'px';
});

function puGetAfterElement(container, y) {
    const els = [...container.querySelectorAll('.pu-task-card:not(.dragging):not(.drag-placeholder)')];
    return els.reduce((closest, child) => {
        const box    = child.getBoundingClientRect();
        const offset = y - box.top - box.height / 2;
        if (offset < 0 && offset > closest.offset) return { offset, element: child };
        return closest;
    }, { offset: Number.NEGATIVE_INFINITY }).element;
}

/* ---- Save move ---- */
async function puSaveMove(card, destVirtualId, leftNeighborCard) {
    const taskId      = card.dataset.taskId;
    const workOrderId = card.dataset.workOrderId;
    const partId      = card.dataset.partId;
    const leftPriority = leftNeighborCard ? leftNeighborCard.dataset.priority : null;
    const leftTaskId   = leftNeighborCard ? leftNeighborCard.dataset.taskId   : null;

    puDndSetStatus('Saving…', 'saving');

    try {
        const params = new URLSearchParams({
            action:         'update_pu_task_priority',
            task_id:        taskId,
            new_machine_id: destVirtualId,   // virtual id → backend decodes table + physical machine
            work_order_id:  workOrderId,
            part_id:        partId,
        });
        if (leftPriority !== null) params.append('left_neighbor_priority', leftPriority);
        if (leftTaskId   !== null) params.append('left_neighbor_task_id',   leftTaskId);

        const res = await fetch(PU_SAVE_URL, { method: 'POST', body: params });
        const dat = await res.json();

        if (dat.status === 'success') {
            puDndSetStatus('Task moved successfully!', 'ok');
            setTimeout(puDndRefreshBoth, 500);
            loadData(false); // refresh main table
        } else {
            puDndSetStatus('Error: ' + (dat.message || 'Unknown error'), 'err');
            puDndRefreshBoth();
        }
    } catch(err) {
        puDndSetStatus('Network error — refreshing…', 'err');
        puDndRefreshBoth();
    }
}

/* ---- Refresh both ---- */
function puDndRefreshBoth() {
    if (puVirtualIds.left)  puDndLoadColumn('left');
    if (puVirtualIds.right) puDndLoadColumn('right');
}

function puDndSetStatus(msg, type) {
    const el = document.getElementById('puDndStatus');
    el.textContent = msg;
    el.className   = 'dnd-status ' + (type || '');
}
</script>