<?php
// Always return JSON and avoid leaking notices that break JSON
header('Content-Type: application/json');
ini_set('display_errors', 0);
error_reporting(E_ALL);

session_start();
include_once('../includes/config.php');

// Auth check
if (!isset($_SESSION['uid'])) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit();
}

try {
    // Get JSON input
    $input = file_get_contents('php://input');
    $data = json_decode($input, true);

    if (!is_array($data)) {
        throw new Exception('Invalid JSON data');
    }

    // Validate required fields
    $saleId = isset($data['sale_id']) ? (int)$data['sale_id'] : 0;
    $customerId = isset($data['customer_id']) ? (int)$data['customer_id'] : 0;
    $paymentMethod = $data['payment_method'] ?? 'Cash';
    $amountReceived = isset($data['amount_received']) ? (float)$data['amount_received'] : 0.0;
    $cartItems = $data['cart_items'] ?? [];

    if ($saleId <= 0 || $customerId <= 0 || empty($cartItems)) {
        throw new Exception('Sale ID, customer ID, and cart items are required');
    }

    // Basic cart validation
    foreach ($cartItems as $idx => $item) {
        if (!isset($item['product_id'], $item['quantity'], $item['rate'])) {
            throw new Exception('Invalid cart item at index ' . $idx);
        }
        if ($item['quantity'] <= 0 || $item['rate'] <= 0) {
            throw new Exception('Quantity and rate must be positive for product ' . $item['product_id']);
        }
    }

    $userId = (int)($_SESSION['uid']);

    // Start transaction
    $dbh->beginTransaction();

    // Calculate totals (using bag pricing)
    $subtotal = 0.0;
    foreach ($cartItems as $item) {
        $ratePerKg = (float)$item['rate'];
        $quantity = (float)$item['quantity'];
        $bagKg = isset($item['bag_kg']) ? (float)$item['bag_kg'] : 1.0;
        
        // Calculate per bag price and total
        $bagPrice = $ratePerKg * $bagKg;
        $subtotal += $bagPrice * $quantity;
    }

    $discountAmount = isset($data['discount_amount']) ? (float)$data['discount_amount'] : 0.0;
    $totalAmount = max(0, $subtotal - $discountAmount);
    $paidAmount = max(0, $amountReceived);
    $balanceAmount = max(0, $totalAmount - $paidAmount);
    $changeAmount = max(0, $paidAmount - $totalAmount);

    // Determine payment status
    if ($paidAmount >= $totalAmount) {
        $paymentStatus = 'Paid';
    } elseif ($paidAmount > 0) {
        $paymentStatus = 'Partial';
    } else {
        $paymentStatus = 'Pending';
    }

    // First, restore stock for the original items (both kg and bags)
    $originalItemsQuery = "SELECT si.ProductID, si.Quantity, rb.BagKg 
                          FROM tblpossaleitems si 
                          JOIN tblricebags rb ON si.ProductID = rb.ID 
                          WHERE si.SaleID = ?";
    $stmt = $dbh->prepare($originalItemsQuery);
    $stmt->execute([$saleId]);
    $originalItems = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach ($originalItems as $item) {
        $quantityInBags = (float)$item['Quantity'];
        $bagKg = (float)$item['BagKg'];
        $quantityInKg = $quantityInBags * $bagKg;
        
        // Restore both kg and bag stock
        $stmt = $dbh->prepare("UPDATE tblricebags SET CurrentStock = CurrentStock + ?, StockInBags = StockInBags + ? WHERE ID = ?");
        $stmt->execute([$quantityInKg, $quantityInBags, (int)$item['ProductID']]);
    }

    // Update the main sale record
    $stmt = $dbh->prepare(
        "UPDATE tblpossales SET
            CustomerID = ?,
            SubTotal = ?,
            DiscountAmount = ?,
            TotalAmount = ?,
            PaidAmount = ?,
            BalanceAmount = ?,
            ChangeAmount = ?,
            PaymentMethod = ?,
            ReferenceNumber = ?,
            Notes = ?,
            PaymentStatus = ?,
            UpdatedAt = CURRENT_TIMESTAMP
        WHERE ID = ?"
    );

    $stmt->execute([
        $customerId,
        $subtotal,
        $discountAmount,
        $totalAmount,
        $paidAmount,
        $balanceAmount,
        $changeAmount,
        $paymentMethod,
        $data['reference_number'] ?? '',
        $data['notes'] ?? '',
        $paymentStatus,
        $saleId
    ]);

    // Delete old sale items
    $stmt = $dbh->prepare("DELETE FROM tblpossaleitems WHERE SaleID = ?");
    $stmt->execute([$saleId]);

    // Insert new sale items and update stock
    foreach ($cartItems as $item) {
        $productId = (int)$item['product_id'];
        $quantityInBags = (float)$item['quantity'];
        $ratePerKg = (float)$item['rate'];
        $bagKg = isset($item['bag_kg']) ? (float)$item['bag_kg'] : 1.0;

        // Get product details and current stock
        $stmt = $dbh->prepare("SELECT RiceBagName, Brand, CurrentStock, StockInBags FROM tblricebags WHERE ID = ?");
        $stmt->execute([$productId]);
        $product = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$product) {
            throw new Exception('Product not found: ' . $productId);
        }

        if ((int)$product['StockInBags'] < $quantityInBags) {
            throw new Exception('Insufficient stock for product: ' . $product['RiceBagName'] . '. Available: ' . $product['StockInBags'] . ' bags');
        }

        $bagPrice = $ratePerKg * $bagKg;
        $lineTotal = $bagPrice * $quantityInBags;

        // Insert sale item
        $stmt = $dbh->prepare("INSERT INTO tblpossaleitems (SaleID, ProductID, ProductName, ProductCode, Quantity, UnitPrice, LineTotal, DiscountAmount, TaxAmount)
                               VALUES (?, ?, ?, ?, ?, ?, ?, 0, 0)");
        $stmt->execute([
            $saleId,
            $productId,
            $product['RiceBagName'] . ' (' . $quantityInBags . ' bags)',
            $product['Brand'] ?? ('RICE-' . $productId),
            $quantityInBags,
            $bagPrice,
            $lineTotal
        ]);

        // Update stock (both kg and bags)
        $quantityInKg = $quantityInBags * $bagKg;
        $newStockKg = ((float)$product['CurrentStock']) - $quantityInKg;
        $newStockBags = ((int)$product['StockInBags']) - $quantityInBags;
        
        $stmt = $dbh->prepare("UPDATE tblricebags SET CurrentStock = ?, StockInBags = ? WHERE ID = ?");
        $stmt->execute([$newStockKg, $newStockBags, $productId]);

        // Optional: stock adjustment entry could be added here
    }

    // Replace payment record
    $stmt = $dbh->prepare("DELETE FROM tblpospayments WHERE SaleID = ?");
    $stmt->execute([$saleId]);

    if ($paidAmount > 0) {
        $stmt = $dbh->prepare("INSERT INTO tblpospayments (SaleID, PaymentMethod, Amount, ReferenceNumber, PaymentDate, Status, Notes, CreatedBy, CreatedAt)
                               VALUES (?, ?, ?, ?, NOW(), 'Completed', ?, ?, CURRENT_TIMESTAMP)");
        $stmt->execute([
            $saleId,
            $paymentMethod,
            $paidAmount,
            $data['reference_number'] ?? '',
            'Payment update for sale #' . $saleId,
            $userId
        ]);
    }

    // Get updated sale details
    $stmt = $dbh->prepare("SELECT SaleNumber, SaleDate, TotalAmount, PaidAmount, BalanceAmount, ChangeAmount, PaymentStatus FROM tblpossales WHERE ID = ?");
    $stmt->execute([$saleId]);
    $saleInfo = $stmt->fetch(PDO::FETCH_ASSOC);

    // Sync customer payments table to reflect updated sale
    if ($saleInfo && isset($saleInfo['SaleNumber'])) {
        $saleNumber = $saleInfo['SaleNumber'];
        $saleDate = $saleInfo['SaleDate'];

        // Remove existing customer payments linked to this sale number (common pattern in create flow)
        $stmt = $dbh->prepare("DELETE FROM tblcustomerpayments WHERE ReferenceNumber = ? OR Description LIKE ?");
        $stmt->execute([$saleNumber, '%'.$saleNumber.'%']);

        // Insert fresh debit entry for total sale amount
        $stmt = $dbh->prepare("INSERT INTO tblcustomerpayments (CustomerID, TransactionType, Amount, PaymentMethod, ReferenceNumber, TransactionDate, Description, Status, CreatedBy, CreatedDate)
                               VALUES (?, 'Debit', ?, ?, ?, ?, ?, 'Completed', ?, NOW())");
        $stmt->execute([
            $customerId,
            $totalAmount,
            $paymentMethod,
            $saleNumber,
            $saleDate,
            'POS Sale - ' . $saleNumber . (!empty($data['notes']) ? (' - ' . $data['notes']) : ''),
            $userId
        ]);

        // Insert credit entry for paid amount if any
        if ($paidAmount > 0) {
            $stmt = $dbh->prepare("INSERT INTO tblcustomerpayments (CustomerID, TransactionType, Amount, PaymentMethod, ReferenceNumber, TransactionDate, Description, Status, CreatedBy, CreatedDate)
                                   VALUES (?, 'Credit', ?, ?, ?, ?, ?, 'Completed', ?, NOW())");
            $stmt->execute([
                $customerId,
                $paidAmount,
                $paymentMethod,
                $saleNumber,
                $saleDate,
                'Payment Received - ' . $saleNumber,
                $userId
            ]);
        }
    }

    // Commit transaction
    $dbh->commit();

    echo json_encode([
        'success' => true,
        'message' => 'Sale updated successfully',
        'data' => [
            'sale_id' => $saleId,
            'sale_number' => $saleInfo['SaleNumber'] ?? '',
            'sale_date' => $saleInfo['SaleDate'] ?? '',
            'total_amount' => (float)($saleInfo['TotalAmount'] ?? 0),
            'paid_amount' => (float)($saleInfo['PaidAmount'] ?? 0),
            'balance_amount' => (float)($saleInfo['BalanceAmount'] ?? 0),
            'change_amount' => (float)($saleInfo['ChangeAmount'] ?? 0),
            'payment_status' => $saleInfo['PaymentStatus'] ?? 'Pending'
        ]
    ]);

} catch (PDOException $e) {
    if (isset($dbh) && $dbh->inTransaction()) {
        $dbh->rollBack();
    }
    echo json_encode([
        'success' => false,
        'message' => 'Database error: ' . $e->getMessage()
    ]);
} catch (Exception $e) {
    if (isset($dbh) && $dbh->inTransaction()) {
        $dbh->rollBack();
    }
    echo json_encode([
        'success' => false,
        'message' => $e->getMessage()
    ]);
}
?>
