<?php
declare(strict_types=1);
require_once __DIR__ . '/../helpers.php';
require_post();
$userId = as_int(get_post('user_id'));
$user = require_write_user($userId);
$cartJson = get_post('cart_json');
$paymentAmount = as_float(get_post('payment_amount', '0'));
$notes = get_post('notes');
$cart = json_decode($cartJson, true);
if (!is_array($cart) || count($cart) === 0) respond(['success' => false, 'message' => 'Cart is empty'], 400);

$conn = db();
$conn->begin_transaction();
try {
    $receiptNo = 'RCPT-' . date('YmdHis');
    $totalAmount = 0.0;
    $lines = [];

    foreach ($cart as $line) {
        $itemId = (int)($line['item_id'] ?? 0);
        $qty = (int)($line['quantity'] ?? 0);
        if ($itemId <= 0 || $qty <= 0) throw new Exception('Invalid cart item');
        $stmt = $conn->prepare('SELECT id, item_type, name, sku, price, quantity FROM items WHERE id = ? FOR UPDATE');
        $stmt->bind_param('i', $itemId);
        $stmt->execute();
        $item = $stmt->get_result()->fetch_assoc();
        if (!$item) throw new Exception('Item not found');
        if (($item['item_type'] ?? 'sale') !== 'sale') throw new Exception($item['name'] . ' is not a sale item');
        if ((int)$item['quantity'] < $qty) throw new Exception('Insufficient stock for ' . $item['name']);
        $lineTotal = (float)$item['price'] * $qty;
        $totalAmount += $lineTotal;
        $lines[] = [
            'item_id' => $itemId,
            'name' => $item['name'],
            'price' => (float)$item['price'],
            'quantity' => $qty,
            'line_total' => $lineTotal,
            'sku' => $item['sku'],
            'new_qty' => (int)$item['quantity'] - $qty,
        ];
    }

    if ($paymentAmount < $totalAmount) throw new Exception('Payment amount is less than total amount');

    $saleStmt = $conn->prepare('INSERT INTO sales (receipt_no, cashier_user_id, cashier_name, total_amount, payment_amount, change_amount, notes, sale_datetime) VALUES (?, ?, ?, ?, ?, ?, ?, NOW())');
    $changeAmount = $paymentAmount - $totalAmount;
    $cashierName = $user['full_name'];
    $saleStmt->bind_param('sisddds', $receiptNo, $userId, $cashierName, $totalAmount, $paymentAmount, $changeAmount, $notes);
    $saleStmt->execute();
    $saleId = (int)$conn->insert_id;

    foreach ($lines as $line) {
        $detail = $conn->prepare('INSERT INTO sale_items (sale_id, item_id, item_name, sku, price, quantity, line_total) VALUES (?, ?, ?, ?, ?, ?, ?)');
        $detail->bind_param('iissdid', $saleId, $line['item_id'], $line['name'], $line['sku'], $line['price'], $line['quantity'], $line['line_total']);
        $detail->execute();
        $stock = $conn->prepare('UPDATE items SET quantity = ?, updated_at = NOW() WHERE id = ?');
        $stock->bind_param('ii', $line['new_qty'], $line['item_id']);
        $stock->execute();
    }

    $conn->commit();
    log_activity($userId, 'CHECKOUT_SALE', "Sale {$receiptNo} total {$totalAmount}");
    respond(['success' => true, 'message' => 'Checkout completed', 'sale' => [
        'sale_id' => $saleId,
        'receipt_no' => $receiptNo,
        'total_amount' => $totalAmount,
        'payment_amount' => $paymentAmount,
        'change_amount' => $changeAmount,
        'sale_datetime' => date('Y-m-d H:i:s'),
        'cashier_name' => $cashierName,
        'notes' => $notes,
        'items' => array_map(static fn($line) => [
            'item_id' => $line['item_id'],
            'sku' => $line['sku'],
            'name' => $line['name'],
            'price' => $line['price'],
            'quantity' => $line['quantity'],
            'line_total' => $line['line_total'],
        ], $lines),
    ]]);
} catch (Throwable $e) {
    $conn->rollback();
    respond(['success' => false, 'message' => $e->getMessage()], 400);
}
