<?php
ob_start();
require("dbconnect.php");
require("config.php");
require("function.php");

header('Content-Type: application/json');

if (function_exists('mysqli_report')) { mysqli_report(MYSQLI_REPORT_OFF); }

if (!isset($_SESSION["username_".$dbname])) {
    echo json_encode(['success'=>false,'message'=>'Session expired. Please re-login.']);
    exit;
}

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

// ── Defensive auto-migrate (keep in sync with saleorder.php / dispatchalert.php) ──
foreach ([
    'parentso'          => "INT(11) NOT NULL DEFAULT 0",
    'godown'            => "INT(11) NOT NULL DEFAULT 0",
    'salesman'          => "INT(11) NOT NULL DEFAULT 0",
    'transport_charges' => "DOUBLE NOT NULL DEFAULT 0",
    'other_charges'     => "DOUBLE 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");
}
$chk = mysqli_query($conn, "SHOW COLUMNS FROM `saleorderdtl` LIKE 'stockqty'");
if ($chk && mysqli_num_rows($chk) == 0)
    mysqli_query($conn, "ALTER TABLE `saleorderdtl` ADD COLUMN `stockqty` DOUBLE NOT NULL DEFAULT 0");
// orderqty is legacy (kept in sync with qty by saleorder.php) — still written
// on the child rows below so nothing reading it is left with a stale 0.
$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, "CREATE TABLE IF NOT EXISTS `notifications` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `vouchno` INT(11) NOT NULL DEFAULT 0,
    `reftype` VARCHAR(20) NOT NULL DEFAULT '',
    `audience` VARCHAR(30) NOT NULL DEFAULT '',
    `action` VARCHAR(20) NOT NULL DEFAULT '',
    `message` VARCHAR(255) NOT NULL DEFAULT '',
    `readflag` VARCHAR(1) NOT NULL DEFAULT '',
    `createduser` VARCHAR(50) NOT NULL DEFAULT '',
    `createddate` DATE NULL,
    `createdtime` TIME NULL,
    PRIMARY KEY (`id`),
    KEY `audience` (`audience`),
    KEY `vouchno` (`vouchno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

try {

$vouchno = isset($_POST['vouchno']) ? (int)$_POST['vouchno'] : 0;
$allocRaw = isset($_POST['allocations']) ? json_decode($_POST['allocations'], true) : null;

if ($vouchno <= 0) {
    echo json_encode(['success'=>false,'message'=>'Invalid sale order.']);
    exit;
}
if (!is_array($allocRaw) || !$allocRaw) {
    echo json_encode(['success'=>false,'message'=>'No allocations submitted.']);
    exit;
}

$parentRes = mysqli_query($conn, "SELECT * FROM `saleorder` WHERE `vouchno`='$vouchno'");
$parent    = $parentRes ? mysqli_fetch_assoc($parentRes) : null;
if (!$parent) {
    echo json_encode(['success'=>false,'message'=>'Sale order not found.']);
    exit;
}

// ── This order's own raw line rows (srl-level, so we can deduct from them
//    one at a time below) + a per-product qty total used as the allocation cap ──
$rowRes = mysqli_query($conn, "SELECT `srl`,`product`,`brand`,`cost`,`qty` FROM `saleorderdtl` WHERE `vouchno`='$vouchno' ORDER BY `srl`");
$rawRows = [];
$byProduct = []; // product => ['brand'=>, 'cost'=>, 'qty'=>total]
if ($rowRes) while ($r = mysqli_fetch_assoc($rowRes)) {
    $p = (int)$r['product'];
    $rawRows[] = $r;
    if (!isset($byProduct[$p])) $byProduct[$p] = ['brand'=>(int)$r['brand'], 'cost'=>(float)$r['cost'], 'qty'=>0];
    $byProduct[$p]['qty'] += (float)$r['qty'];
}

// ── Validate + group submitted allocations by godown, re-deriving cost/brand
//    server-side so a tampered request can't inject arbitrary pricing ───────
$godownList = [];
$gRes = mysqli_query($conn, "SELECT `code`,`name` FROM `godown`");
if ($gRes) while ($r = mysqli_fetch_assoc($gRes)) $godownList[(int)$r['code']] = $r['name'];

$allocByProduct = []; // running total per product, to validate against Qty
$grouped = [];        // [godowncode][product] = qty
foreach ($allocRaw as $a) {
    $prod   = isset($a['product']) ? (int)$a['product'] : 0;
    $godown = isset($a['godown'])  ? (int)$a['godown']  : 0;
    $qty    = isset($a['qty'])     ? (float)$a['qty']   : 0;
    if ($prod <= 0 || $godown <= 0 || $qty <= 0) continue;
    if (!isset($byProduct[$prod])) continue; // not a line on this order
    if (!isset($godownList[$godown])) continue; // unknown godown
    if ($godown == (int)($parent['godown'] ?? 0)) continue; // must be an "other" godown

    $allocByProduct[$prod] = ($allocByProduct[$prod] ?? 0) + $qty;
    $grouped[$godown][$prod] = ($grouped[$godown][$prod] ?? 0) + $qty;
}

// Cap check: allocated qty for a product can never exceed that product's
// current Qty on this order (Qty IS the line's committed amount now).
foreach ($allocByProduct as $prod => $totalAlloc) {
    $cap = $byProduct[$prod]['qty'];
    if ($totalAlloc > $cap + 1e-9) {
        echo json_encode(['success'=>false,'message'=>'Allocated qty exceeds this order\'s Qty for one of the products. Please refresh and try again.']);
        exit;
    }
}

if (!$grouped) {
    echo json_encode(['success'=>false,'message'=>'No valid allocations submitted.']);
    exit;
}

$audituser = audituser();
$vd        = date('Y-m-d');
$customer  = (int)$parent['customer'];
$salesman  = (int)($parent['salesman'] ?? 0);
$created   = [];

foreach ($grouped as $godown => $prodQtys) {
    $lines = []; $subtotal = 0;
    foreach ($prodQtys as $prod => $qty) {
        $cost = $byProduct[$prod]['cost'];
        $brand = $byProduct[$prod]['brand'];
        $amt  = $qty * $cost;
        // Stock-at-entry snapshot for this godown, same convention as saleorder.php
        $sqRow = mysqli_fetch_assoc(mysqli_query($conn, "SELECT COALESCE(SUM(`qty`),0) AS q FROM `transacn` WHERE `product`='$prod' AND `godown`='$godown'"));
        $stockqty = $sqRow ? (float)$sqRow['q'] : 0;
        $lines[] = ['product'=>$prod, 'brand'=>$brand, 'qty'=>$qty, 'cost'=>$cost, 'amount'=>$amt, 'stockqty'=>$stockqty];
        $subtotal += $amt;
    }
    if (!$lines) continue;

    $gen1   = mysqli_query($conn, "SELECT MAX(`vouchno`) AS maxcode FROM `saleorder` LIMIT 1");
    $vvouch = mysqli_fetch_assoc($gen1);
    $newVouch = ($vvouch && $vvouch["maxcode"] > 0) ? $vvouch["maxcode"] + 1 : 1;

    $remarks = mysqli_real_escape_string($conn, 'Split from SO#' . $vouchno);

    mysqli_query($conn, "INSERT INTO `saleorder`
        (`vouchno`,`vouchdt`,`customer`,`godown`,`salesman`,`remarks`,`subtotal`,`packingcharges`,`transport_charges`,`other_charges`,`netamount`,`parentso`,
         `adduser`,`adddate`,`addtime`)
        VALUES
        ('$newVouch','$vd','$customer','$godown','$salesman','$remarks','$subtotal','0','0','0','$subtotal','$vouchno',
         '$audituser',CURDATE(),CURTIME())")
    or die(json_encode(['success'=>false,'message'=>mysqli_error($conn)]));

    foreach ($lines as $ln) {
        mysqli_query($conn, "INSERT INTO `saleorderdtl`
            (`vouchno`,`product`,`brand`,`qty`,`cost`,`amount`,`stockqty`,`orderqty`)
            VALUES ('$newVouch','{$ln['product']}','{$ln['brand']}','{$ln['qty']}','{$ln['cost']}','{$ln['amount']}','{$ln['stockqty']}','{$ln['qty']}')")
        or die(json_encode(['success'=>false,'message'=>mysqli_error($conn)]));
    }

    $godownname = $godownList[$godown] ?? ('Godown #'.$godown);
    $created[] = ['vouchno'=>$newVouch, 'godown'=>$godown, 'godownname'=>$godownname];

    $custNameRow = mysqli_fetch_assoc(mysqli_query($conn, "SELECT `name` FROM `accmast` WHERE `accode`='$customer'"));
    $custName    = $custNameRow['name'] ?? '';
    $msg = mysqli_real_escape_string($conn,
        "Sale Order #$newVouch" . ($custName ? " ($custName)" : '') . " created from SO#$vouchno for $godownname by $audituser.");
    mysqli_query($conn, "INSERT INTO `notifications`
        (`vouchno`,`reftype`,`audience`,`action`,`message`,`createduser`,`createddate`,`createdtime`)
        VALUES ('$newVouch','saleorder','admin','info','$msg','$audituser',CURDATE(),CURTIME())");
    if ($salesman > 0) {
        mysqli_query($conn, "INSERT INTO `notifications`
            (`vouchno`,`reftype`,`audience`,`action`,`message`,`createduser`,`createddate`,`createdtime`)
            VALUES ('$newVouch','saleorder','salesman_$salesman','info','$msg','$audituser',CURDATE(),CURTIME())");
    }
}

if (!$created) {
    echo json_encode(['success'=>false,'message'=>'Could not create any split orders.']);
    exit;
}

// ── Deduct the allocated qty from the SOURCE order's own lines, srl by srl,
//    so its Qty (and Amount) reflect what's actually still left on its own
//    godown after the split — e.g. Qty 100, split 50 out → source becomes 50. ──
foreach ($allocByProduct as $prod => $totalAlloc) {
    $remaining = $totalAlloc;
    foreach ($rawRows as $row) {
        if ($remaining <= 1e-9) break;
        if ((int)$row['product'] !== $prod) continue;
        $rowQty = (float)$row['qty'];
        if ($rowQty <= 0) continue;
        $take = min($rowQty, $remaining);
        $newQty = $rowQty - $take;
        $newAmt = $newQty * (float)$row['cost'];
        mysqli_query($conn, "UPDATE `saleorderdtl` SET `qty`='$newQty', `amount`='$newAmt', `orderqty`='$newQty' WHERE `srl`='{$row['srl']}'")
        or die(json_encode(['success'=>false,'message'=>mysqli_error($conn)]));
        $remaining -= $take;
    }
}

// ── Recompute the source order's Subtotal / Net Amount from its (now reduced) lines ──
$sumRow = mysqli_fetch_assoc(mysqli_query($conn, "SELECT COALESCE(SUM(`amount`),0) AS s FROM `saleorderdtl` WHERE `vouchno`='$vouchno'"));
$newSubtotal = $sumRow ? (float)$sumRow['s'] : 0;
$newNet = $newSubtotal + (float)($parent['packingcharges'] ?? 0) + (float)($parent['transport_charges'] ?? 0) + (float)($parent['other_charges'] ?? 0);
mysqli_query($conn, "UPDATE `saleorder` SET `subtotal`='$newSubtotal', `netamount`='$newNet',
    `edituser`='$audituser', `editdate`=CURDATE(), `edittime`=CURTIME() WHERE `vouchno`='$vouchno'")
or die(json_encode(['success'=>false,'message'=>mysqli_error($conn)]));

if (ob_get_level() > 0) { ob_clean(); }
echo json_encode(['success'=>true, 'created'=>$created]);

} catch (\Throwable $e) {
    if (ob_get_level() > 0) { ob_clean(); }
    echo json_encode(['success'=>false, 'message'=>$e->getMessage()]);
}
