<?php
ob_start();
require("includes/check_auth_user.php");
require("includes/dbconnect.php");
require("includes/config.php");
require("includes/function.php");
require("includes/check_permission.php");

$formname = 'Dispatch Alert';
$zdb = $_SESSION["zdbyear_" . $dbname];
mysqli_select_db($conn, $zdb);

// ── Defensive auto-migrate (in case saleorder.php hasn't run yet) ─────────
foreach ([
    'dispatchdate'   => "DATE NULL",
    'dispatchby'     => "VARCHAR(50) NOT NULL DEFAULT ''",
    'lrno'           => "VARCHAR(50) NOT NULL DEFAULT ''",
    'transporter'    => "VARCHAR(100) NOT NULL DEFAULT ''",
    'lrdate'         => "DATE NULL",
    'transportmode'  => "VARCHAR(30) NOT NULL DEFAULT ''",
    'invoiceno'      => "INT(11) NOT NULL DEFAULT 0",
    'invoicedate'    => "DATE NULL",
    'godown'         => "INT(11) NOT NULL DEFAULT 0",
    // LR (Lorry Receipt) copy upload — same feature as Sale Invoice's LR
    // Copy (see sale.php / includes/sale_lrimage_upload.php), just attached
    // to the sale order here so it's available as soon as it's dispatched,
    // before an invoice even exists yet.
    'lrimage'        => "VARCHAR(200) NOT NULL DEFAULT ''",
    // Links a shortfall/split sale order (created from the Difference Qty
    // modal below) back to the original order it was split from.
    'parentso'       => "INT(11) NOT NULL DEFAULT 0",
] as $col => $def) {
    $chk = mysqli_query($conn, "SHOW COLUMNS FROM `saleorder` LIKE '$col'");
    if ($chk && mysqli_num_rows($chk) == 0)
        mysqli_query($conn, "ALTER TABLE `saleorder` ADD COLUMN `$col` $def");
}

// Order Qty (total customer request, may exceed Qty committed from this
// order's own godown) — see saleorder.php for the entry-side of this field.
$chk = mysqli_query($conn, "SHOW COLUMNS FROM `saleorderdtl` LIKE 'orderqty'");
if ($chk && mysqli_num_rows($chk) == 0) {
    mysqli_query($conn, "ALTER TABLE `saleorderdtl` ADD COLUMN `orderqty` DOUBLE NOT NULL DEFAULT 0");
    mysqli_query($conn, "UPDATE `saleorderdtl` SET `orderqty` = `qty` WHERE `orderqty` = 0");
}

require_once("includes/upload_path.php");
// LR copy images for sale orders get their own bucket (uploads/so_lrimage/{finyear}/),
// separate from Sale Invoice's own 'lrimage' bucket.
$_upSO      = upload_path('so_lrimage');
$uploadurlSO = $_upSO['url'];

$audituser = audituser();
$_ut = (int)$_SESSION["usertype_".$dbname];
$_ac = (int)($_SESSION["agentcode_".$dbname] ?? 0);

$filter = isset($_GET['filter']) ? $_GET['filter'] : 'pending';
if (!in_array($filter, ['all','pending','dispatched','invoiced'])) $filter = 'pending';
$search  = isset($_GET['q']) ? trim($_GET['q']) : '';
// From/To default to today's date whenever they're not explicitly supplied
// (first page load, or a "Clear" click) rather than sitting blank.
$fromDt  = (isset($_GET['fromdt']) && trim($_GET['fromdt']) !== '') ? trim($_GET['fromdt']) : date('Y-m-d');
$toDt    = (isset($_GET['todt'])   && trim($_GET['todt'])   !== '') ? trim($_GET['todt'])   : date('Y-m-d');

$where = [];
// "Dispatched" means dispatched but NOT yet invoiced — once an order has an
// invoice generated against it, it belongs in the Invoiced tab only. Without
// the invoiceno exclusion here, a dispatched-and-invoiced order would show
// up in both tabs at once.
if ($filter == 'pending')    $where[] = "(s.dispatchdate IS NULL OR s.dispatchdate='0000-00-00')";
if ($filter == 'dispatched') $where[] = "(s.dispatchdate IS NOT NULL AND s.dispatchdate!='0000-00-00') AND (s.invoiceno IS NULL OR s.invoiceno=0)";
if ($filter == 'invoiced')   $where[] = "(s.invoiceno IS NOT NULL AND s.invoiceno>0)";
if ($search !== '') {
    $sq = mysqli_real_escape_string($conn, $search);
    $where[] = "(a.name LIKE '%$sq%' OR s.vouchno LIKE '%$sq%' OR s.lrno LIKE '%$sq%' OR s.remarks LIKE '%$sq%')";
}
// Date range is always active — defaults to today/today on a bare page load
// or a plain tab click, and the tab links below carry the current
// fromdt/todt/q forward so switching tabs doesn't drop the filter. Built as
// a plain (unaliased) condition too, so the tab badge counts below can stay
// in sync with the same date range instead of always showing the all-time total.
$dateCondPlain = '';
if ($fromDt !== '') {
    $where[] = "s.vouchdt >= '" . mysqli_real_escape_string($conn, $fromDt) . "'";
    $dateCondPlain .= " AND vouchdt >= '" . mysqli_real_escape_string($conn, $fromDt) . "'";
}
if ($toDt !== '') {
    $where[] = "s.vouchdt <= '" . mysqli_real_escape_string($conn, $toDt) . "'";
    $dateCondPlain .= " AND vouchdt <= '" . mysqli_real_escape_string($conn, $toDt) . "'";
}
if ($_ut === 3 && $_ac > 0) $where[] = "s.salesman='$_ac'";
$whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';

// parentso (already part of s.*) links a split-off order back to the source
// order it was split from — see the Split feature (dispatchalert_diff.php /
// dispatchalert_splitorder.php) and the shaded "Split from SO#…" rows below.
$res = mysqli_query($conn, "SELECT s.*, a.name AS custname, a.transport AS custtransport, a.packdtls AS custpackdtls,
                                    g.name AS godownname, sum(d.qty) as totqty
                             FROM `saleorder` s
                             LEFT JOIN `saleorderdtl` d ON s.vouchno = d.vouchno
                             LEFT JOIN `accmast` a ON a.accode = s.customer
                             LEFT JOIN `godown` g ON g.code = s.godown
                             $whereSql
                             GROUP BY s.vouchno
                             ORDER BY s.vouchno DESC") or die(mysqli_error($conn));
$orders = [];
while ($r = mysqli_fetch_assoc($res)) $orders[] = $r;

// Badge counts respect the same active date range as the list itself, so a
// tab never shows e.g. "(1)" while its filtered list is actually empty.
$_cntSalCond = ($_ut === 3 && $_ac > 0) ? " AND salesman='$_ac'" : '';
$cntAll        = (int)(mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(*) c FROM saleorder WHERE 1=1$_cntSalCond$dateCondPlain"))['c'] ?? 0);
$cntPending    = (int)(mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(*) c FROM saleorder WHERE (dispatchdate IS NULL OR dispatchdate='0000-00-00')$_cntSalCond$dateCondPlain"))['c'] ?? 0);
$cntDispatched = (int)(mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(*) c FROM saleorder WHERE (dispatchdate IS NOT NULL AND dispatchdate!='0000-00-00') AND (invoiceno IS NULL OR invoiceno=0)$_cntSalCond$dateCondPlain"))['c'] ?? 0);
$cntInvoiced   = (int)(mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(*) c FROM saleorder WHERE (invoiceno IS NOT NULL AND invoiceno>0)$_cntSalCond$dateCondPlain"))['c'] ?? 0);

function df($v) { return ($v && $v!='0000-00-00') ? date('d-m-Y', strtotime($v)) : ''; }

include("includes/linkshead.php");
?>
<style>
body { background:#f0f2f5; padding:10px 12px 90px; }
.pg-head { max-width:1650px; margin:0 auto 12px; display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:10px; }
.pg-head h2 { font-size:17px; font-weight:700; color:#1e293b; margin:0; }
.tabs { display:flex; gap:6px; max-width:1650px; margin:0 auto 12px; flex-wrap:wrap; }
.tab { padding:8px 16px; border-radius:20px; font-size:12.5px; font-weight:600; text-decoration:none; color:#475569; background:#fff; border:1px solid #e2e8f0; }
.tab.active { background:#2563eb; color:#fff; border-color:#2563eb; }
.tab .cnt { opacity:.8; margin-left:4px; }
.searchbar { max-width:1650px; margin:0 auto 14px; display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.searchbar input[type=text] { flex:1; min-width:180px; padding:10px 14px; border:1px solid #e2e8f0; border-radius:8px; font-size:13.5px; outline:none; background:#fff; }
.searchbar .dt-grp { display:flex; align-items:center; gap:6px; background:#fff; border:1px solid #e2e8f0; border-radius:8px; padding:0 10px; }
.searchbar .dt-grp span { font-size:11.5px; color:#94a3b8; font-weight:600; }
.searchbar input[type=date] { border:none; padding:10px 4px; font-size:13px; outline:none; background:transparent; color:#1e293b; }
.searchbar button { padding:10px 18px; border:none; border-radius:8px; background:#1e293b; color:#fff; font-weight:600; font-size:13px; cursor:pointer; }
.searchbar .clr { background:#f1f5f9; color:#475569; text-decoration:none; padding:10px 14px; border-radius:8px; font-size:12.5px; font-weight:600; display:inline-flex; align-items:center; }

.listwrap { max-width:1650px; margin:0 auto; background:#fff; border-radius:14px; box-shadow:0 1px 3px rgba(0,0,0,.07); overflow-x:auto; }
.list-tbl { width:100%; min-width:1250px; border-collapse:collapse; font-size:12.8px; }
.list-tbl thead th { text-align:left; padding:11px 14px; background:#f8fafc; color:#64748b; font-weight:700; font-size:11px; text-transform:uppercase; letter-spacing:.03em; border-bottom:1px solid #eef1f5; white-space:nowrap; }
.list-tbl tbody td { padding:12px 14px; border-bottom:1px solid #f1f5f9; color:#334155; vertical-align:middle; }
.list-tbl tbody tr { transition:background .12s; }
.list-tbl tbody tr:hover { background:#f8fafc; }
.list-tbl tbody tr:last-child td { border-bottom:none; }
.so-no { font-size:13px; font-weight:700; color:#1e293b; }
.so-cust { font-size:12px; color:#475569; }
.saleinvbadge { font-size:10.5px; font-weight:700; padding:4px 11px; border-radius:14px; white-space:nowrap; display:inline-block;  background: #dbeafe; color: #1d4ed8;  }
.badge { font-size:10.5px; font-weight:700; padding:4px 11px; border-radius:14px; white-space:nowrap; display:inline-block; }
.badge.pending { background:#fef3c7; color:#92400e; }
.badge.dispatched { background:#dcfce7; color:#166534; }
.muted { color:#94a3b8; }
.lr-box { font-size:11px; color:#64748b; line-height:1.5; max-width:230px; }
.lr-copy-row { display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
.lr-btn { display:inline-flex; align-items:center; gap:5px; padding:5px 10px; border:none; border-radius:6px; font-size:10.5px; font-weight:600; cursor:pointer; text-decoration:none; white-space:nowrap; }
.lr-btn-view { background:#dbeafe; color:#1d4ed8; }
.lr-btn-up { background:#16a34a; color:#fff; }
.cust-extra { font-size:10.5px; color:#94a3b8; line-height:1.5; margin-top:3px; }
.cust-extra div { white-space:normal; }
.cust-extra i { width:12px; text-align:center; margin-right:4px; }
.row-actions { display:flex; gap:6px; white-space:nowrap; }
.btn-disp { padding:7px 12px; border:none; border-radius:7px; background:#2563eb; color:#fff; font-size:12px; font-weight:600; cursor:pointer; white-space:nowrap; }
.btn-disp.edit { background:#f59e0b; }
.btn-disp.gen { background:#16a34a; }
.btn-disp.challan { background:#7f5539; }
.btn-disp.revert { background:#dc2626; }
.btn-disp.split { background:#7c3aed; }
.btn-view { padding:7px 10px; border-radius:7px; background:#f1f5f9; color:#475569; text-decoration:none; font-size:12.5px; }
.empty { text-align:center; padding:60px 20px; color:#94a3b8; max-width:1650px; margin:0 auto; }
tr.split-row { background:#faf5ff; }
tr.split-row:hover { background:#f3e8ff !important; }
.split-tag { font-size:10.5px; color:#7c3aed; font-weight:600; margin-top:3px; white-space:nowrap; }
.split-tag a { color:#7c3aed; text-decoration:underline; }


/* Modal */
#dispModal { display:none; position:fixed; inset:0; background:rgba(15,23,42,.55); z-index:9999; align-items:center; justify-content:center; padding:14px; }
#lrModal { display:none; position:fixed; inset:0; background:rgba(15,23,42,.55); z-index:9999; align-items:center; justify-content:center; padding:14px; }
#lrModal .modal-box { max-width:380px; }
#lrModal .modal-body input[type=file] { width:100%; box-sizing:border-box; padding:10px 12px; border:1px solid #e2e8f0; border-radius:8px; font-size:13px; }
#lrModal .modal-body .hint { font-size:11px; color:#94a3b8; margin-top:6px; }
#diffModal { display:none; position:fixed; inset:0; background:rgba(15,23,42,.55); z-index:9999; align-items:center; justify-content:center; padding:14px; }
#diffModal .modal-box { max-width:920px; }
#diffModal .modal-body { max-height:60vh; overflow:auto; }
.diff-hdr { font-size:12.5px; color:#64748b; margin-bottom:12px; }
.diff-hdr b { color:#1e293b; }
table.diff-tbl { width:100%; border-collapse:collapse; font-size:12px; }
table.diff-tbl th { background:#f8fafc; color:#64748b; font-weight:700; font-size:10.5px; text-transform:uppercase; padding:8px 6px; border-bottom:2px solid #e2e8f0; text-align:right; white-space:nowrap; }
table.diff-tbl th.lbl-col { text-align:left; }
table.diff-tbl td { padding:6px; border-bottom:1px solid #f1f5f9; text-align:right; vertical-align:middle; }
table.diff-tbl td.lbl-col { text-align:left; }
table.diff-tbl td.diffcell { font-weight:700; color:#dc2626; }
table.diff-tbl input.alloc-fld { width:72px; padding:5px 6px; border:1px solid #e2e8f0; border-radius:5px; font-size:12px; text-align:right; }
table.diff-tbl .gstock-hint { display:block; font-size:9.5px; color:#94a3b8; margin-top:2px; font-weight:400; }
.diff-empty { text-align:center; padding:30px; color:#94a3b8; }
.modal-box { background:#fff; border-radius:14px; width:100%; max-width:440px; max-height:92vh; overflow:auto; }
.modal-head { padding:16px 18px; border-bottom:1px solid #f1f5f9; display:flex; justify-content:space-between; align-items:center; }
.modal-head h3 { margin:0; font-size:15px; font-weight:700; color:#1e293b; }
.modal-head button { background:#f1f5f9; border:none; width:30px; height:30px; border-radius:7px; font-size:16px; color:#64748b; cursor:pointer; }
.modal-body { padding:16px 18px; }
.mfl { margin-bottom:13px; }
.mfl label { display:block; font-size:12.5px; font-weight:600; color:#374151; margin-bottom:5px; }
.mfl input, .mfl select { width:100%; box-sizing:border-box; padding:10px 12px; border:1px solid #e2e8f0; border-radius:8px; font-size:13.5px; outline:none; font-family:inherit; }
.mfl input:focus, .mfl select:focus { border-color:#3b82f6; }
.modal-foot { padding:14px 18px; border-top:1px solid #f1f5f9; display:flex; gap:8px; }
.modal-foot button { flex:1; padding:11px; border:none; border-radius:8px; font-size:13.5px; font-weight:700; cursor:pointer; }
.mbtn-save { background:#16a34a; color:#fff; }
.mbtn-cancel { background:#f1f5f9; color:#374151; }

@media (max-width:480px) {
    .pg-head h2 { font-size:15px; }
}
</style>
</head>
<body>

<div class="pg-head">
    <h2><i class="fa fa-truck-fast" style="color:#f59e0b;margin-right:8px;"></i><?php echo $formname; ?></h2>
    <a href="default.php" style="font-size:12.5px;color:#64748b;text-decoration:none;"><i class="fa fa-arrow-left"></i> Back</a>
</div>

<?php
// Tab links carry the currently active search/date filter forward as a
// querystring so switching tabs narrows the status without dropping the
// date range back to unfiltered.
$_tabQs = http_build_query(array_filter([
    'q'      => $search,
    'fromdt' => $fromDt,
    'todt'   => $toDt,
]));
$_tabQs = $_tabQs !== '' ? '&' . $_tabQs : '';
?>
<div class="tabs">
    <a class="tab <?php echo $filter=='pending'?'active':''; ?>"    href="?filter=pending<?php echo $_tabQs; ?>">Pending Dispatch <span class="cnt">(<?php echo $cntPending; ?>)</span></a>
    <a class="tab <?php echo $filter=='dispatched'?'active':''; ?>" href="?filter=dispatched<?php echo $_tabQs; ?>">Dispatched <span class="cnt">(<?php echo $cntDispatched; ?>)</span></a>
    <a class="tab <?php echo $filter=='invoiced'?'active':''; ?>"   href="?filter=invoiced<?php echo $_tabQs; ?>">Invoiced <span class="cnt">(<?php echo $cntInvoiced; ?>)</span></a>
    <a class="tab <?php echo $filter=='all'?'active':''; ?>"        href="?filter=all<?php echo $_tabQs; ?>">All <span class="cnt">(<?php echo $cntAll; ?>)</span></a>
</div>

<form class="searchbar" method="GET">
    <input type="hidden" name="filter" value="<?php echo htmlspecialchars($filter); ?>">
    <input type="text" name="q" placeholder="Search customer, SO#, LR no..." value="<?php echo htmlspecialchars($search); ?>">
    <div class="dt-grp"><span>From</span><input type="date" name="fromdt" value="<?php echo htmlspecialchars($fromDt); ?>"></div>
    <div class="dt-grp"><span>To</span><input type="date" name="todt" value="<?php echo htmlspecialchars($toDt); ?>"></div>
    <button type="submit"><i class="fa fa-search"></i></button>
    <?php if ($search !== '' || $fromDt !== date('Y-m-d') || $toDt !== date('Y-m-d')): ?>
    <a class="clr" href="?filter=<?php echo htmlspecialchars($filter); ?>">Clear</a>
    <?php endif; ?>
</form>

<?php if (!$orders): ?>
    <div class="empty"><i class="fa fa-inbox" style="font-size:34px;display:block;margin-bottom:10px;"></i>No sale orders found.</div>
<?php else: ?>
<div class="listwrap">
<table class="list-tbl">
    <thead>
        <tr>
            <th>SO#</th>
            <th>Customer</th>
            <th>Order Date</th>
            <th>Godown</th>
            <th style="text-align:right">Qty</th>
            <th style="text-align:right">Net Amount</th>
            <th>Status</th>
            <th>Dispatch Info</th>
            <th>Invoice</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
    <?php foreach ($orders as $o):
        $isDispatched = !empty($o['dispatchdate']) && $o['dispatchdate'] != '0000-00-00';
        $isSplit      = (int)($o['parentso'] ?? 0) > 0;
    ?>
        <tr<?php echo $isSplit ? ' class="split-row"' : ''; ?>>
            <td>
                <span class="so-no">SO#<?php echo (int)$o['vouchno']; ?></span>
                <?php if ($isSplit): ?>
                <div class="split-tag"><i class="fa fa-code-branch"></i> Split from <a href="saleorder.php?mode=edit&vouchno=<?php echo (int)$o['parentso']; ?>">SO#<?php echo (int)$o['parentso']; ?></a></div>
                <?php endif; ?>
            </td>
            <td>
                <span class="so-cust"><?php echo htmlspecialchars($o['custname'] ?? ''); ?></span>
                <?php if (!empty($o['custtransport']) || !empty($o['custpackdtls'])): ?>
                <div class="cust-extra">
                    <?php if (!empty($o['custtransport'])): ?><div><i class="fa fa-truck"></i><?php echo htmlspecialchars($o['custtransport']); ?><?php endif; ?>
                    <?php if (!empty($o['custpackdtls'])): ?><div><i class="fa fa-box"></i><?php echo htmlspecialchars($o['custpackdtls']); ?><?php endif; ?>
                </div>
                <?php endif; ?>
            </td>
            <td><?php echo df($o['vouchdt']); ?></td>
            <td><?php echo !empty($o['godownname']) ? htmlspecialchars($o['godownname']) : '<span class="muted">—</span>'; ?></td>
            <td class="text-right"><?php echo (float)$o['totqty']; ?></td>
            <td class="text-right"><?php echo number_format((float)$o['netamount'],0); ?></td>
            <td><span class="badge <?php echo $isDispatched?'dispatched':'pending'; ?>"><?php echo $isDispatched?'Dispatched':'Pending'; ?></span></td>
            <td>
                <?php if ($isDispatched): ?>
                <div class="lr-box">
                    <div><?php echo df($o['dispatchdate']); ?> by <?php echo htmlspecialchars($o['dispatchby']); ?></div>
                    <?php if ($o['lrno']): ?><div>LR: <?php echo htmlspecialchars($o['lrno']); ?></div><?php endif; ?>
                    <?php if ($o['lrdate'] != "0000-00-00"): ?><div>DT: <?php echo df($o['lrdate']); ?></div><?php endif; ?>
                    <?php if ($o['transporter']): ?><div><?php echo htmlspecialchars($o['transporter']); ?><?php echo $o['transportmode'] ? ' — '.htmlspecialchars($o['transportmode']) : ''; ?></div><?php endif; ?>
                    <div class="lr-copy-row">
                        <?php if (!empty($o['lrimage'])): ?>
                        <a href="<?php echo htmlspecialchars($uploadurlSO.$o['lrimage']); ?>" target="_blank" class="lr-btn lr-btn-view"><i class="fa fa-eye"></i> View LR Copy</a>
                        <?php endif; ?>
                        <button type="button" class="lr-btn lr-btn-up" onclick="openLrModal(<?php echo (int)$o['vouchno']; ?>)"><i class="fa fa-upload"></i> <?php echo !empty($o['lrimage']) ? 'Replace' : 'Upload'; ?> LR Copy</button>
                    </div>
                </div>
                <?php else: ?><span class="muted">—</span><?php endif; ?>
            </td>
            <td><span class="saleinvbadge">
                    <?php if ($o['invoiceno'] > 0): ?>
                    <a href="sale.php?mode=edit&vouchno=<?php echo (int)$o['invoiceno']; ?>"> <?php echo ((int)($o['invoiceno'] ?? 0) > 0) ? 'SAL#'.(int)$o['invoiceno'] : '<span class="muted">—</span>'; ?> </a>
                    <?php endif; ?>
                </span>
            </td>
            <td>
                <div class="row-actions">
                    <button type="button" class="btn-disp <?php echo $isDispatched?'edit':''; ?>"
                        onclick='openDispModal(<?php echo json_encode($o); ?>)'>
                        <i class="fa fa-truck"></i> <?php echo $isDispatched?'Update':'Dispatch'; ?>
                    </button>
                    <?php if ($isDispatched && (int)($o['invoiceno'] ?? 0) === 0): ?>
                    <button type="button" class="btn-disp gen" onclick="genInvoice(<?php echo (int)$o['vouchno']; ?>)">
                        <i class="fa fa-bolt"></i> Generate Invoice
                    </button>
                    <button type="button" class="btn-disp revert" onclick="movetoPending(<?php echo (int)$o['vouchno']; ?>)">
                        <i class="fa fa-rotate-left"></i> Cancel Dispatch
                    </button>
                    <?php endif; ?>
                    <?php if ((int)($o['invoiceno'] ?? 0) > 0): ?>
                    <button type="button" class="btn-disp challan" onclick="window.open('delivery_challan_print.php?vouchno=<?php echo (int)$o['vouchno']; ?>','_blank')">
                        <i class="fa fa-file-lines"></i> Delivery Challan
                    </button>
                    <?php endif; ?>
                    <?php if ((int)($o['invoiceno'] ?? 0) === 0): ?>
                    <button type="button" class="btn-disp split" onclick="openDiffModal(<?php echo (int)$o['vouchno']; ?>)" title="Split this order's qty across other godowns">
                        <i class="fa fa-code-branch"></i> Split
                    </button>
                    <?php endif; ?>
                    <a href="saleorder.php?mode=edit&vouchno=<?php echo (int)$o['vouchno']; ?>" class="btn-view"><i class="fa fa-eye"></i></a>
                </div>
            </td>
        </tr>
    <?php endforeach; ?>
    </tbody>
</table>
</div>
<?php endif; ?>

<!-- Dispatch Update Modal -->
<div id="dispModal">
    <div class="modal-box">
        <div class="modal-head">
            <h3 id="dmTitle">Update Dispatch</h3>
            <button type="button" onclick="closeDispModal()">&times;</button>
        </div>
        <div class="modal-body">
            <input type="hidden" id="dm_vouchno">
            <div class="mfl"><label>Dispatch Date</label><input type="date" id="dm_dispatchdate"></div>
            <div class="mfl"><label>Dispatched By</label><input type="text" id="dm_dispatchby" placeholder="Staff name"></div>
            <div class="mfl"><label>LR No.</label><input type="text" id="dm_lrno" placeholder="LR / Bilty No."></div>
            <div class="mfl"><label>LR Date</label><input type="date" id="dm_lrdate"></div>
            <div class="mfl"><label>Mode of Transport</label>
                <select id="dm_transportmode" onchange="document.getElementById('dm_modeother').style.display=(this.value=='Other')?'block':'none';">
                    <option value="">-- Select --</option>
                    <option>By Road</option><option>By Rail</option><option>By Air</option><option>By Sea</option><option>Courier</option><option>Self Pickup</option><option value="Other">Other</option>
                </select>
                <input type="text" id="dm_modeother" placeholder="Specify mode" style="display:none;margin-top:7px;">
            </div>
            <div class="mfl"><label>Transporter</label><input type="text" id="dm_transporter" placeholder="Transporter name"></div>
        </div>
        <div class="modal-foot">
            <button type="button" class="mbtn-cancel" onclick="closeDispModal()">Cancel</button>
            <button type="button" class="mbtn-save" onclick="saveDispatch()">Save</button>
        </div>
    </div>
</div>

<!-- LR Copy Upload Modal (same feature as Sale Invoice's LR Copy) -->
<div id="lrModal">
    <div class="modal-box">
        <div class="modal-head">
            <h3>Upload LR Copy</h3>
            <button type="button" onclick="closeLrModal()">&times;</button>
        </div>
        <div class="modal-body">
            <input type="hidden" id="lr_vouchno">
            <input type="file" id="lr_file" accept=".jpg,.jpeg,.png,.gif,.webp">
            <div class="hint">Max size 2 MB. JPG, PNG, GIF or WEBP.</div>
        </div>
        <div class="modal-foot">
            <button type="button" class="mbtn-cancel" onclick="closeLrModal()">Cancel</button>
            <button type="button" class="mbtn-save" onclick="saveLrImage()">Save</button>
        </div>
    </div>
</div>

<!-- Difference Qty split modal: source shortfall qty from other godowns -->
<div id="diffModal">
    <div class="modal-box">
        <div class="modal-head">
            <h3 id="diffTitle">Split Remaining Qty</h3>
            <button type="button" onclick="closeDiffModal()">&times;</button>
        </div>
        <div class="modal-body">
            <div id="diffBody"><div class="diff-empty">Loading…</div></div>
        </div>
        <div class="modal-foot">
            <button type="button" class="mbtn-cancel" onclick="closeDiffModal()">Cancel</button>
            <button type="button" class="mbtn-save" onclick="createSplitOrders()">Create</button>
        </div>
    </div>
</div>

<?php include("includes/linksfoot.php"); ?>
<script>
var CURRENT_USER = <?php echo json_encode($audituser); ?>;

function openDispModal(o) {
    document.getElementById('dm_vouchno').value = o.vouchno;
    document.getElementById('dmTitle').textContent = 'Dispatch — SO#' + o.vouchno;
    document.getElementById('dm_dispatchdate').value = (o.dispatchdate && o.dispatchdate!='0000-00-00') ? o.dispatchdate : new Date().toISOString().slice(0,10);
    document.getElementById('dm_dispatchby').value = o.dispatchby || CURRENT_USER || '';
    document.getElementById('dm_lrno').value = o.lrno || '';
    document.getElementById('dm_lrdate').value = (o.lrdate && o.lrdate!='0000-00-00') ? o.lrdate : '';
    // Default to the order's own saved transporter; if it doesn't have one
    // yet, fall back to the customer master's Transport field. Either way
    // the input stays a normal editable text field — this is just the
    // starting value.
    document.getElementById('dm_transporter').value = o.transporter || o.custtransport || '';
    var modeSel = document.getElementById('dm_transportmode');
    var modeOther = document.getElementById('dm_modeother');
    var stdModes = ['By Road','By Rail','By Air','By Sea','Courier','Self Pickup'];
    if (o.transportmode && stdModes.indexOf(o.transportmode) === -1) {
        modeSel.value = 'Other'; modeOther.style.display='block'; modeOther.value = o.transportmode;
    } else {
        modeSel.value = o.transportmode || ''; modeOther.style.display='none'; modeOther.value='';
    }
    document.getElementById('dispModal').style.display = 'flex';
}
function closeDispModal() { document.getElementById('dispModal').style.display = 'none'; }
document.getElementById('dispModal').addEventListener('click', function(e){ if (e.target === this) closeDispModal(); });

function saveDispatch() {
    var modeVal = document.getElementById('dm_transportmode').value;
    if (modeVal === 'Other') modeVal = document.getElementById('dm_modeother').value.trim();
    var payload = {
        vouchno: document.getElementById('dm_vouchno').value,
        dispatchdate: document.getElementById('dm_dispatchdate').value,
        dispatchby: document.getElementById('dm_dispatchby').value,
        transportmode: modeVal,
        lrno: document.getElementById('dm_lrno').value,
        lrdate: document.getElementById('dm_lrdate').value,
        transporter: document.getElementById('dm_transporter').value
    };
    if (!payload.dispatchdate) {
        Swal.fire({icon:'warning',title:'Dispatch date is required',confirmButtonColor:'#2563eb'});
        return;
    }
    $.post('includes/dispatchalert_update.php', payload, function(resp) {
        if (resp && resp.success) {
            closeDispModal();
            Swal.fire({icon:'success',title:'Saved!',text:'Dispatch details updated.',timer:1400,showConfirmButton:false}).then(function(){
                window.location.reload();
            });
        } else {
            Swal.fire({icon:'error',title:'Error',text:(resp && resp.message) ? resp.message : 'Could not save.',confirmButtonColor:'#2563eb'});
        }
    }, 'json').fail(function(){
        Swal.fire({icon:'error',title:'Error',text:'Request failed.',confirmButtonColor:'#2563eb'});
    });
}

// ── LR Copy upload — same feature as Sale Invoice's LR Copy, just against
// this sale order directly (so it's available as soon as it's dispatched).
function openLrModal(vouchno) {
    document.getElementById('lr_vouchno').value = vouchno;
    document.getElementById('lr_file').value = '';
    document.getElementById('lrModal').style.display = 'flex';
}
function closeLrModal() { document.getElementById('lrModal').style.display = 'none'; }
document.getElementById('lrModal') && document.getElementById('lrModal').addEventListener('click', function(e){ if (e.target === this) closeLrModal(); });

function saveLrImage() {
    var fileInp = document.getElementById('lr_file');
    if (!fileInp.files.length) {
        Swal.fire({icon:'warning',title:'Choose a file first',confirmButtonColor:'#2563eb'});
        return;
    }
    if (fileInp.files[0].size > 2 * 1024 * 1024) {
        Swal.fire({icon:'warning',title:'File too large',text:'Max size is 2 MB.',confirmButtonColor:'#2563eb'});
        return;
    }
    var fd = new FormData();
    fd.append('vouchno', document.getElementById('lr_vouchno').value);
    fd.append('lrimage', fileInp.files[0]);
    $.ajax({
        url: 'includes/saleorder_lrimage_upload.php',
        type: 'POST',
        data: fd,
        contentType: false,
        processData: false,
        dataType: 'json'
    }).done(function(resp) {
        if (resp && resp.success) {
            closeLrModal();
            Swal.fire({icon:'success',title:'Uploaded!',timer:1200,showConfirmButton:false}).then(function(){
                window.location.reload();
            });
        } else {
            Swal.fire({icon:'error',title:'Error',text:(resp && resp.message) ? resp.message : 'Could not upload.',confirmButtonColor:'#2563eb'});
        }
    }).fail(function(){
        Swal.fire({icon:'error',title:'Error',text:'Request failed.',confirmButtonColor:'#2563eb'});
    });
}

// ── Move to Pending: reverts a dispatched (not yet invoiced) sale order back
// to Pending Dispatch — clears its dispatch/LR/transporter details and undoes
// the stock-OUT and accounting entries that were posted on dispatch.
function movetoPending(vouchno) {
    Swal.fire({
        title: 'Move back to Pending?',
        text: 'This will clear the dispatch details for SO#' + vouchno + ' and move it back to Pending Dispatch.',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonText: 'Yes, Move to Pending',
        confirmButtonColor: '#dc2626',
        cancelButtonColor: '#64748b'
    }).then(function(result) {
        if (!result.isConfirmed) return;
        $.post('includes/dispatchalert_revert.php', { vouchno: vouchno }, function(resp) {
            if (resp && resp.success) {
                Swal.fire({icon:'success',title:'Moved!',text:'SO#'+vouchno+' is back in Pending Dispatch.',timer:1400,showConfirmButton:false}).then(function(){
                    window.location.reload();
                });
            } else {
                Swal.fire({icon:'error',title:'Error',text:(resp && resp.message) ? resp.message : 'Could not revert dispatch.',confirmButtonColor:'#2563eb'});
            }
        }, 'json').fail(function(){
            Swal.fire({icon:'error',title:'Error',text:'Request failed.',confirmButtonColor:'#2563eb'});
        });
    });
}

// ── Difference Qty split modal: fetch the order's product lines + every
// other godown, let the user type how much to source from each, then create
// one new sale order per godown that got an allocation.
var DIFF_VOUCHNO = 0;
function openDiffModal(vouchno) {
    DIFF_VOUCHNO = vouchno;
    document.getElementById('diffTitle').textContent = 'Split Qty — SO#' + vouchno;
    document.getElementById('diffBody').innerHTML = '<div class="diff-empty">Loading…</div>';
    document.getElementById('diffModal').style.display = 'flex';
    $.getJSON('includes/dispatchalert_diff.php', { vouchno: vouchno }, function(resp) {
        if (!resp || !resp.success) {
            document.getElementById('diffBody').innerHTML = '<div class="diff-empty">' + escapeHtmlDiff((resp && resp.message) ? resp.message : 'Could not load.') + '</div>';
            return;
        }
        renderDiffModal(resp);
    }).fail(function(){
        document.getElementById('diffBody').innerHTML = '<div class="diff-empty">Request failed.</div>';
    });
}
function closeDiffModal() { document.getElementById('diffModal').style.display = 'none'; }
document.getElementById('diffModal').addEventListener('click', function(e){ if (e.target === this) closeDiffModal(); });

function escapeHtmlDiff(s) {
    return String(s == null ? '' : s).replace(/[&<>"']/g, function(c) {
        return { '&':'&amp;', '<':'&lt;', '>':'&gt;', '"':'&quot;', "'":'&#39;' }[c];
    });
}

function renderDiffModal(resp) {
    var so = resp.so, lines = resp.lines, godowns = resp.godowns;
    var html = '<div class="diff-hdr">SO#' + so.vouchno + ' — Godown: <b>' + escapeHtmlDiff(so.godownname || '—') + '</b> — Customer: <b>' + escapeHtmlDiff(so.custname || '') + '</b></div>';

    if (!lines.length) {
        html += '<div class="diff-empty">No line items.</div>';
        document.getElementById('diffBody').innerHTML = html;
        return;
    }
    if (!godowns.length) {
        html += '<div class="diff-empty">No other godowns exist to split into.</div>';
        document.getElementById('diffBody').innerHTML = html;
        return;
    }

    html += '<table class="diff-tbl"><thead><tr>' +
        '<th class="lbl-col">Sr</th><th class="lbl-col">Product</th>' +
        '<th>Qty</th>';
    godowns.forEach(function(g) { html += '<th>' + escapeHtmlDiff(g.name) + '</th>'; });
    html += '</tr></thead><tbody>';

    lines.forEach(function(ln, i) {
        html += '<tr data-product="' + ln.product + '" data-qty="' + ln.qty + '">' +
            '<td class="lbl-col">' + (i + 1) + '</td>' +
            '<td class="lbl-col">' + escapeHtmlDiff(ln.prodname) + '</td>' +
            '<td>' + ln.qty + '</td>';
        godowns.forEach(function(g) {
            var stk = (ln.godownstock && ln.godownstock[g.code] !== undefined) ? ln.godownstock[g.code] : 0;
            html += '<td><input type="number" step="any" min="0" class="alloc-fld" data-godown="' + g.code + '" value="">' +
                '<span class="gstock-hint">stock: ' + stk + '</span></td>';
        });
        html += '</tr>';
    });
    html += '</tbody></table>';
    document.getElementById('diffBody').innerHTML = html;
}

function createSplitOrders() {
    var rows = document.querySelectorAll('#diffBody table.diff-tbl tbody tr');
    if (!rows.length) return;
    var allocations = [];
    var overLimit = [];
    rows.forEach(function(tr) {
        var product = tr.getAttribute('data-product');
        var qtyCap = parseFloat(tr.getAttribute('data-qty')) || 0;
        var rowTotal = 0;
        tr.querySelectorAll('input.alloc-fld').forEach(function(inp) {
            var v = parseFloat(inp.value) || 0;
            if (v > 0) {
                rowTotal += v;
                allocations.push({ product: product, godown: inp.getAttribute('data-godown'), qty: v });
            }
        });
        if (rowTotal > qtyCap + 1e-9) overLimit.push(tr.querySelector('.lbl-col:nth-child(2)').textContent);
    });
    if (overLimit.length) {
        Swal.fire({ icon:'warning', title:'Over the Qty', text: 'These products have more allocated across godowns than their Qty: ' + overLimit.join(', '), confirmButtonColor:'#2563eb' });
        return;
    }
    if (!allocations.length) {
        Swal.fire({ icon:'warning', title:'Nothing entered', text:'Enter a qty in at least one godown column.', confirmButtonColor:'#2563eb' });
        return;
    }
    Swal.fire({
        title: 'Create split sale order(s)?',
        text: 'This will create a new sale order for each godown you entered a qty for.',
        icon: 'question',
        showCancelButton: true,
        confirmButtonText: 'Yes, Create',
        confirmButtonColor: '#16a34a',
        cancelButtonColor: '#64748b'
    }).then(function(result) {
        if (!result.isConfirmed) return;
        $.post('includes/dispatchalert_splitorder.php', { vouchno: DIFF_VOUCHNO, allocations: JSON.stringify(allocations) }, function(resp) {
            if (resp && resp.success) {
                var list = (resp.created || []).map(function(c){ return 'SO#' + c.vouchno + ' (' + c.godownname + ')'; }).join(', ');
                closeDiffModal();
                Swal.fire({icon:'success',title:'Created!',text: list ? ('Created: ' + list) : 'Split orders created.',confirmButtonColor:'#16a34a'}).then(function(){
                    window.location.reload();
                });
            } else {
                Swal.fire({icon:'error',title:'Error',text:(resp && resp.message) ? resp.message : 'Could not create split orders.',confirmButtonColor:'#2563eb'});
            }
        }, 'json').fail(function(){
            Swal.fire({icon:'error',title:'Error',text:'Request failed.',confirmButtonColor:'#2563eb'});
        });
    });
}

// ── Generate Invoice: creates a Sale Invoice directly from this dispatched
// sale order (reuses the same generator endpoint the Pending Invoice page
// uses, just with a single vouchno).
function genInvoice(vouchno) {
    Swal.fire({
        title: 'Generate Invoice?',
        text: 'This will create a Sale invoice for SO#' + vouchno + '.',
        icon: 'question',
        showCancelButton: true,
        confirmButtonText: 'Yes, Generate',
        confirmButtonColor: '#16a34a',
        cancelButtonColor: '#64748b'
    }).then(function(result) {
        if (!result.isConfirmed) return;
        $.post('includes/pendinginvoice_geninvoice.php', { vouchnos: [vouchno] }, function(resp) {
            if (resp && resp.success) {
                Swal.fire({icon:'success',title:'Invoice Generated!',text:'Sale invoice SAL#'+resp.invoiceno+' created.',confirmButtonColor:'#16a34a'}).then(function(){
                    window.location.href = 'sale.php?mode=edit&vouchno=' + resp.invoiceno;
                });
            } else {
                Swal.fire({icon:'error',title:'Error',text:(resp && resp.message) ? resp.message : 'Could not generate invoice.',confirmButtonColor:'#2563eb'});
            }
        }, 'json').fail(function(){
            Swal.fire({icon:'error',title:'Error',text:'Request failed.',confirmButtonColor:'#2563eb'});
        });
    });
}
</script>
</body>
</html>
