<?php
if (session_status() === PHP_SESSION_NONE) { session_start(); }
require_once dirname(__DIR__, 2) . '/includes/db.php';

// Auto-patch DB ENUM
$conn->query("ALTER TABLE opening_allocations MODIFY COLUMN location_type ENUM('Store', 'Department', 'Dispensary') NOT NULL");
// CRITICAL FIX: Drop strict foreign key on inventory_batches to allow 0 variant_id for service_catalog items
try { $conn->query("ALTER TABLE inventory_batches DROP FOREIGN KEY inventory_batches_ibfk_2"); } catch(Exception $e) {}

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

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $conn->begin_transaction();
    try {
        $loc_type = $_POST['location_type'] ?? '';
        $loc_id   = (int)($_POST['location_id'] ?? 0);
        $date     = $_POST['allocation_date'] ?? date('Y-m-d');
        $remarks  = trim($conn->real_escape_string($_POST['remarks'] ?? ''));
        
        $staff_id = isset($_SESSION['staff_id']) ? (int)$_SESSION['staff_id'] : 0;
        if ($staff_id <= 0) {
            $fallback_res = $conn->query("SELECT staff_id FROM staff WHERE is_active = 1 LIMIT 1");
            if ($fallback_res && $fallback_res->num_rows > 0) {
                $staff_id = (int)$fallback_res->fetch_assoc()['staff_id'];
            } else {
                throw new Exception("Operational Constraint: No active staff members found to authorize entry.");
            }
        }

        if (empty($loc_type) || $loc_id <= 0 || empty($_POST['product_id'])) {
            throw new Exception("Critical routing data or payload items missing.");
        }

        $ref_query = $conn->query("SELECT COUNT(id) as total FROM opening_allocations");
        $count = $ref_query->fetch_assoc()['total'] + 1;
        $ref_number = "OIA-" . date('Y') . "-" . str_pad($count, 6, '0', STR_PAD_LEFT);

        $stmtHeader = $conn->prepare("INSERT INTO opening_allocations (reference_number, location_type, location_id, allocation_date, effective_date, remarks, status, created_by) VALUES (?, ?, ?, ?, ?, ?, 'Posted', ?)");
        $stmtHeader->bind_param("ssisssi", $ref_number, $loc_type, $loc_id, $date, $date, $remarks, $staff_id);
        if (!$stmtHeader->execute()) throw new Exception("Header fault: " . $stmtHeader->error);
        $allocation_id = $conn->insert_id;
        $stmtHeader->close();

        $stmtItem = $conn->prepare("INSERT INTO opening_allocation_items (allocation_id, product_id, variant_id, batch_number, manufacture_date, expiry_date, quantity, unit_cost, selling_price) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
        
        $stmtBatchCheck = $conn->prepare("SELECT id FROM inventory_batches WHERE store_id = ? AND variant_id = ? AND batch_number = ?");
        $stmtBatchInsert = $conn->prepare("INSERT INTO inventory_batches (store_id, variant_id, batch_number, quantity_on_hand, cost_price, selling_price, manufacture_date, expiry_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
        $stmtBatchUpdate = $conn->prepare("UPDATE inventory_batches SET quantity_on_hand = quantity_on_hand + ? WHERE id = ?");
        $stmtLedger = $conn->prepare("INSERT INTO stock_movements (batch_id, dest_store_id, transaction_type, quantity, reference_id, performed_by) VALUES (?, ?, 'Opening Allocation', ?, ?, ?)");

        $stmtStockCheck = $conn->prepare("SELECT id FROM inventory_stock WHERE location_id = ? AND service_id = ?");
        $stmtStockInsert = $conn->prepare("INSERT INTO inventory_stock (service_id, location_id, quantity) VALUES (?, ?, ?)");
        $stmtStockUpdate = $conn->prepare("UPDATE inventory_stock SET quantity = quantity + ? WHERE location_id = ? AND service_id = ?");
        $stmtTransactInsert = $conn->prepare("INSERT INTO inventory_transactions (service_id, location_id, transaction_type, quantity_changed, batch_number, expiry_date, unit_cost, reference_id, performed_by) VALUES (?, ?, 'Receive Goods', ?, ?, ?, ?, ?, ?)");

        foreach ($_POST['product_id'] as $index => $pid) {
            $p_id = (int)$pid;
            // CRITICAL FIX: Gracefully handles 0 if variant was omitted
            $v_id = !empty($_POST['variant_id'][$index]) ? (int)$_POST['variant_id'][$index] : 0; 
            
            $batch = trim($_POST['batch_number'][$index] ?? '');
            if (empty($batch)) {
                $batch = "OIA-" . strtoupper(substr(md5(uniqid()), 0, 6));
            }
            
            $mfg = !empty($_POST['mfg_date'][$index]) ? $_POST['mfg_date'][$index] : null;
            $exp = !empty($_POST['exp_date'][$index]) ? $_POST['exp_date'][$index] : '2099-12-31';
            $qty = (int)($_POST['quantity'][$index] ?? 0);
            $cost = (float)($_POST['unit_cost'][$index] ?? 0.00);
            $sell = (float)($_POST['selling_price'][$index] ?? 0.00);

            if ($p_id <= 0 || $qty <= 0) continue; 

            $stmtItem->bind_param("iiisssidd", $allocation_id, $p_id, $v_id, $batch, $mfg, $exp, $qty, $cost, $sell);
            if (!$stmtItem->execute()) throw new Exception("Line Item error: " . $stmtItem->error);

            if ($loc_type === 'Store') {
                $stmtBatchCheck->bind_param("iis", $loc_id, $v_id, $batch);
                $stmtBatchCheck->execute();
                $b_result = $stmtBatchCheck->get_result();

                if ($b_result->num_rows > 0) {
                    $batch_db_id = $b_result->fetch_assoc()['id'];
                    $stmtBatchUpdate->bind_param("ii", $qty, $batch_db_id);
                    if (!$stmtBatchUpdate->execute()) throw new Exception("Batch Update Error");
                } else {
                    $stmtBatchInsert->bind_param("iisiddss", $loc_id, $v_id, $batch, $qty, $cost, $sell, $mfg, $exp);
                    if (!$stmtBatchInsert->execute()) throw new Exception("Batch Insert Error");
                    $batch_db_id = $conn->insert_id;
                }
                $stmtLedger->bind_param("iiisi", $batch_db_id, $loc_id, $qty, $ref_number, $staff_id);
                if (!$stmtLedger->execute()) throw new Exception("Stock Movement Error");
                
            } elseif ($loc_type === 'Dispensary' || $loc_type === 'Department') {
                $stmtStockCheck->bind_param("ii", $loc_id, $p_id);
                $stmtStockCheck->execute();
                $s_result = $stmtStockCheck->get_result();
                
                if ($s_result->num_rows > 0) {
                    $stmtStockUpdate->bind_param("iii", $qty, $loc_id, $p_id);
                    if (!$stmtStockUpdate->execute()) throw new Exception("Stock Update Error");
                } else {
                    $stmtStockInsert->bind_param("iii", $p_id, $loc_id, $qty);
                    if (!$stmtStockInsert->execute()) throw new Exception("Stock Insert Error");
                }
                $stmtTransactInsert->bind_param("iiisssdi", $p_id, $loc_id, $qty, $batch, $exp, $cost, $allocation_id, $staff_id);
                if (!$stmtTransactInsert->execute()) throw new Exception("Transaction Movement Error");
            }
        }

        $conn->commit();
        ob_end_clean();
        echo json_encode(['status' => 'success', 'message' => "Opening Allocation Posted. Ledger Updated.<br><small>Ref: {$ref_number}</small>"]);

    } catch (Exception $e) {
        $conn->rollback();
        ob_end_clean();
        echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
    }
}
?>