<?php
require_once '../includes/auth.php';
require_once '../db.php';
require_once '../includes/invoice_number.php';

requirePermission('master_sales', 'create', BASE_URL . '/dashboard.php');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') die('Invalid Request');

$master_no    = 'MST/' . date('YmdHis');
$invoice_date = $_POST['invoice_date'] ?? date('Y-m-d');
$client_id    = (int)$_POST['client_id'];
$action       = $_POST['action']; // save | final

$product_ids      = $_POST['product_id']      ?? [];
$batch_ids        = $_POST['purchase_item_id'] ?? [];
$item_company_ids = $_POST['item_company_id']  ?? [];
$qtys             = $_POST['qty']              ?? [];
$sell_prices      = $_POST['sell_price']       ?? [];
$disc_types       = $_POST['disc_type']        ?? [];
$disc_vals        = $_POST['disc_value']        ?? [];
$descriptions     = $_POST['description']      ?? [];
$mrp_inputs       = $_POST['mrp']              ?? [];

$overall_disc_type = $_POST['overall_discount_type']  ?? null;
$overall_disc_val  = floatval($_POST['overall_discount_value'] ?? 0);
$received_amount   = floatval($_POST['received_amount'] ?? 0);
$payment_mode      = $_POST['payment_mode'] ?? 'Cash';

if ($client_id <= 0) die('Client is required.');

// ── Group line items by company_id ──────────────────────────────────────────
// For each item, resolve company_id from purchase_items → purchase_orders
$groups = []; // company_id => [ [...item data...], ... ]
$masterGross = 0;

foreach ($batch_ids as $i => $purchase_item_id) {
    $purchase_item_id = (int)$purchase_item_id;
    if ($purchase_item_id <= 0) continue;
    $qty = floatval($qtys[$i] ?? 0);
    if ($qty <= 0) continue;

    // Trust the posted company_id but verify via DB
    $pi = $conn->query("
        SELECT pi.*, po.company_id, p.id AS prod_id
        FROM purchase_items pi
        JOIN purchase_orders po ON po.id = pi.purchase_order_id
        JOIN products p ON p.id = pi.product_id
        WHERE pi.id = $purchase_item_id
    ")->fetch_assoc();
    if (!$pi) continue;

    $company_id = (int)$pi['company_id'];

    if (!isset($groups[$company_id])) $groups[$company_id] = [];

    $sell_price_incl = floatval($sell_prices[$i] ?? 0);
    $disc_type = $disc_types[$i] ?? null;
    $disc_val  = floatval($disc_vals[$i] ?? 0);
    $description = $descriptions[$i] ?? '';

    $final_unit_incl = $sell_price_incl;
    if ($disc_type === 'percent') $final_unit_incl -= ($sell_price_incl * $disc_val / 100);
    elseif ($disc_type === 'amount') $final_unit_incl -= $disc_val;
    if ($final_unit_incl < 0) $final_unit_incl = 0;

    $line_total = $final_unit_incl * $qty;
    $masterGross += $line_total;

    $groups[$company_id][] = [
        'purchase_item_id' => $purchase_item_id,
        'product_id'       => (int)$pi['prod_id'],
        'batch_no'         => $pi['batch_no'],
        'qty'              => $qty,
        'sell_price_incl'  => $sell_price_incl,
        'disc_type'        => $disc_type,
        'disc_val'         => $disc_val,
        'description'      => $description,
        'mrp'              => floatval($mrp_inputs[$i] ?? 0),
        'gst_percent'      => floatval($pi['gst_percent']),
        'purchase_price'   => floatval($pi['purchase_price']),
        'available_qty'    => floatval($pi['available_qty']),
        'final_unit_incl'  => $final_unit_incl,
        'line_total'       => $line_total,
    ];
}

if (empty($groups)) die('No valid items found.');

// Calculate master discount ratio
$masterNet = $masterGross;
if ($overall_disc_type === 'percent') $masterNet = $masterGross - ($masterGross * $overall_disc_val / 100);
elseif ($overall_disc_type === 'amount') $masterNet = $masterGross - $overall_disc_val;
if ($masterNet < 0) $masterNet = 0;
$discountRatio = ($masterGross > 0) ? ($masterNet / $masterGross) : 1;

$conn->begin_transaction();

try {
    // ── Validate stock if finalizing ─────────────────────────────────────────
    if ($action === 'final') {
        foreach ($groups as $company_id => $items) {
            foreach ($items as $item) {
                if ($item['qty'] > $item['available_qty']) {
                    throw new Exception("Insufficient stock for batch {$item['batch_no']} (need {$item['qty']}, available {$item['available_qty']}).");
                }
            }
        }
    }

    // ── Insert master invoice header ─────────────────────────────────────────
    $status = ($action === 'final') ? 'final' : 'draft';
    $userId = (int)($_SESSION['user_id'] ?? 0);

    $stmtM = $conn->prepare("
        INSERT INTO master_invoices
        (master_no, invoice_date, client_id, status, overall_discount_type,
         overall_discount_value, received_amount, payment_mode, created_by)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    $stmtM->bind_param("ssissddsi",
        $master_no, $invoice_date, $client_id, $status,
        $overall_disc_type, $overall_disc_val,
        $received_amount, $payment_mode, $userId
    );
    $stmtM->execute();
    $master_invoice_id = $stmtM->insert_id;

    // ── Proportionate received amount split ──────────────────────────────────
    // Distribute received_amount across companies proportionate to their sub-totals
    $companySubtotals = [];
    foreach ($groups as $company_id => $items) {
        $sub = array_sum(array_column($items, 'line_total')) * $discountRatio;
        $companySubtotals[$company_id] = $sub;
    }

    // ── Create one sales_invoice per company ─────────────────────────────────
    foreach ($groups as $company_id => $items) {
        $invoice_no = 'QTY/' . date('YmdHis') . rand(10,99);

        if ($action === 'final') {
            $invoice_no = generateFinalInvoiceNo($client_id, $conn, $company_id);
        }

        $gross_total   = 0;
        $total_taxable = 0;
        $total_gst     = 0;

        // Insert invoice header (draft first, update totals after items)
        $stmtInv = $conn->prepare("
            INSERT INTO sales_invoices
            (invoice_no, invoice_date, client_id, status, company_id, master_invoice_id)
            VALUES (?, ?, ?, ?, ?, ?)
        ");
        $stmtInv->bind_param("ssisii",
            $invoice_no, $invoice_date, $client_id, $status, $company_id, $master_invoice_id
        );
        $stmtInv->execute();
        $sales_invoice_id = $stmtInv->insert_id;

        // Insert items
        foreach ($items as $item) {
            $final_unit_excl = $item['final_unit_incl'] / (1 + $item['gst_percent'] / 100);
            $gst_unit        = $item['final_unit_incl'] - $final_unit_excl;
            $taxable         = $final_unit_excl * $item['qty'];
            $gst_amt         = $gst_unit * $item['qty'];
            $line_total      = $item['final_unit_incl'] * $item['qty'];

            $gross_total   += $line_total;
            $total_taxable += $taxable;
            $total_gst     += $gst_amt;

            $stmtItem = $conn->prepare("
                INSERT INTO sales_items
                (sales_invoice_id, purchase_item_id, product_id, description, batch_no,
                 sold_qty, selling_price_incl, selling_price_excl,
                 discount_type, discount_value, purchase_price, gst_percent,
                 taxable_amount, gst_amount, total_amount)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ");
            $stmtItem->bind_param("iiissdddsdsdddd",
                $sales_invoice_id,
                $item['purchase_item_id'],
                $item['product_id'],
                $item['description'],
                $item['batch_no'],
                $item['qty'],
                $item['final_unit_incl'],
                $final_unit_excl,
                $item['disc_type'],
                $item['disc_val'],
                $item['purchase_price'],
                $item['gst_percent'],
                $taxable,
                $gst_amt,
                $line_total
            );
            $stmtItem->execute();

            if ($item['mrp'] > 0) {
                $stmtMrp = $conn->prepare("UPDATE purchase_items SET mrp = ? WHERE id = ?");
                $stmtMrp->bind_param("di", $item['mrp'], $item['purchase_item_id']);
                $stmtMrp->execute();
            }

            if ($action === 'final') {
                $pid  = $item['purchase_item_id'];
                $qty  = $item['qty'];
                $conn->query("UPDATE purchase_items SET available_qty = available_qty - $qty WHERE id = $pid");

                $stmtMov = $conn->prepare("
                    INSERT INTO stock_movements
                    (product_id, purchase_item_id, type, quantity, reference_id, reference_type)
                    VALUES (?, ?, 'OUT', ?, ?, 'sale')
                ");
                $stmtMov->bind_param("iiid", $item['product_id'], $pid, $qty, $sales_invoice_id);
                $stmtMov->execute();
            }
        }

        // Apply proportionate discount to this company's sub-total
        $net_total = $gross_total * $discountRatio;
        $total_taxable *= $discountRatio;
        $total_gst     *= $discountRatio;

        // Proportionate received amount for this company
        $coReceived = ($masterNet > 0 && isset($companySubtotals[$company_id]))
            ? round($received_amount * ($companySubtotals[$company_id] / $masterNet), 2) : 0;
        $balance = max(0, $net_total - $coReceived);

        // Proportionate overall discount value for this company's invoice
        $coDiscVal = ($masterGross > 0)
            ? round($overall_disc_val * ($gross_total / $masterGross), 2) : 0;

        $stmtUpd = $conn->prepare("
            UPDATE sales_invoices
            SET invoice_no=?, gross_total=?, overall_discount_type=?, overall_discount_value=?,
                total_taxable=?, total_gst=?, net_total=?,
                received_amount=?, balance_amount=?, payment_mode=?
            WHERE id=?
        ");
        $stmtUpd->bind_param("sdsddddddsi",
            $invoice_no,
            $gross_total,
            $overall_disc_type,
            $coDiscVal,
            $total_taxable,
            $total_gst,
            $net_total,
            $coReceived,
            $balance,
            $payment_mode,
            $sales_invoice_id
        );
        $stmtUpd->execute();

        // Record initial proportionate payment in ledger
        if ($coReceived > 0) {
            $userId = (int)($_SESSION['user_id'] ?? 0);
            $stmtPay = $conn->prepare("
                INSERT INTO invoice_payments (sales_invoice_id, amount, payment_mode, payment_date, created_by)
                VALUES (?, ?, ?, ?, ?)
            ");
            $stmtPay->bind_param("idssi", $sales_invoice_id, $coReceived, $payment_mode, $invoice_date, $userId);
            $stmtPay->execute();
        }
    }

    $conn->commit();

    header("Location: view.php?id=$master_invoice_id");
    exit;

} catch (Exception $e) {
    $conn->rollback();
    die("Master Invoice Save Failed: " . $e->getMessage());
}
