<?php
/**
 * POST /api/orders/checkout.php
 * Converts the caller's entire cart into a PENDING order - this reserves
 * the stock (so nobody else can also buy the last unit) but is NOT a
 * completed sale. No payment gateway (per MVP scope) - buyer and seller
 * meet in person, and the sale only becomes final when the seller marks
 * each item "fulfilled" via api/orders/fulfill_item.php after actually
 * receiving payment and handing over the goods. Loyalty points, the
 * "sold" notification to sellers, and business dashboard "sold" stats all
 * happen at fulfillment time, not here - see fulfill_item.php.
 *
 * If ANY cart line is unavailable or over stock, the whole checkout is
 * rejected with the list of problem items so the user can fix their cart
 * and retry — partial orders would be confusing for a food-pickup flow.
 */

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/response.php';
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/notifications.php';

only_post_allowed();
$userId = require_login();

$pdo = Database::connect();

try {
    $pdo->beginTransaction();

    // Lock the relevant product rows for the duration of this transaction
    // to prevent two buyers from overselling the same stock simultaneously.
    $stmt = $pdo->prepare('
        SELECT ci.id AS cart_item_id, ci.quantity AS cart_quantity,
               p.id AS product_id, p.owner_id, p.selling_price, p.quantity AS stock, p.status
        FROM cart_items ci
        JOIN products p ON p.id = ci.product_id
        WHERE ci.user_id = ?
        FOR UPDATE
    ');
    $stmt->execute([$userId]);
    $lines = $stmt->fetchAll();

    if (!$lines) {
        $pdo->rollBack();
        send_error('Your cart is empty.', 400);
    }

    $problems = [];
    foreach ($lines as $line) {
        if ($line['status'] !== 'active') {
            $problems[] = ['product_id' => (int) $line['product_id'], 'reason' => 'no longer available'];
        } elseif ((int) $line['cart_quantity'] > (int) $line['stock']) {
            $problems[] = ['product_id' => (int) $line['product_id'], 'reason' => 'not enough stock remaining'];
        }
    }

    if ($problems) {
        $pdo->rollBack();
        send_error('Some items in your cart changed and need your attention before checkout.', 409, $problems);
    }

    $total = 0;
    foreach ($lines as $line) {
        $total += (float) $line['selling_price'] * (int) $line['cart_quantity'];
    }

    $stmt = $pdo->prepare('INSERT INTO orders (buyer_id, total_amount, status) VALUES (?, ?, "pending")');
    $stmt->execute([$userId, round($total, 2)]);
    $orderId = (int) $pdo->lastInsertId();

    $sellerTotals = []; // seller_id => ['amount' => float, 'items' => int]

    foreach ($lines as $line) {
        // Stock is reserved now (so the item can't be double-sold), even
        // though the sale itself is still pending - status defaults to
        // 'pending' on order_items until the seller confirms fulfillment.
        $stmt = $pdo->prepare(
            'INSERT INTO order_items (order_id, product_id, seller_id, quantity, unit_price) VALUES (?, ?, ?, ?, ?)'
        );
        $stmt->execute([
            $orderId, $line['product_id'], $line['owner_id'], $line['cart_quantity'], $line['selling_price'],
        ]);

        $remaining = (int) $line['stock'] - (int) $line['cart_quantity'];
        $stmt = $pdo->prepare('UPDATE products SET quantity = ?, status = ? WHERE id = ?');
        $stmt->execute([$remaining, $remaining <= 0 ? 'sold' : 'active', $line['product_id']]);

        $sellerId = (int) $line['owner_id'];
        $lineAmount = (float) $line['selling_price'] * (int) $line['cart_quantity'];
        $sellerTotals[$sellerId]['amount'] = ($sellerTotals[$sellerId]['amount'] ?? 0) + $lineAmount;
        $sellerTotals[$sellerId]['items'] = ($sellerTotals[$sellerId]['items'] ?? 0) + (int) $line['cart_quantity'];
    }

    $stmt = $pdo->prepare('DELETE FROM cart_items WHERE user_id = ?');
    $stmt->execute([$userId]);

    create_notification(
        $pdo, $userId, 'order_placed',
        "Order #$orderId placed - $" . number_format($total, 2) . ". Arrange pickup with the seller(s) - your order completes once they confirm you've paid and collected it."
    );

    foreach ($sellerTotals as $sellerId => $summary) {
        create_notification(
            $pdo, $sellerId, 'order_pending',
            "New order: {$summary['items']} item(s) for $" . number_format($summary['amount'], 2) . " in order #$orderId. " .
            "Confirm it in My Sales once you've received payment and handed over the item(s)."
        );
    }

    $pdo->commit();
} catch (Throwable $e) {
    $pdo->rollBack();
    send_error('Checkout failed. Please try again.', 500, APP_ENV === 'local' ? [$e->getMessage()] : []);
}

send_json(true, 'Order placed - complete pickup with the seller to finish the sale.', [
    'order' => ['id' => $orderId, 'total' => round($total, 2), 'item_count' => count($lines)],
], 201);
