<?php
// ============================================================
//  MediCore — Customer Advance API
//  File: api/advance.php
// ============================================================
require_once '../includes/db.php';
require_once '../includes/auth.php';
require_login();

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

ensure_sync_tables();

$body   = json_decode(file_get_contents('php://input'), true) ?? [];
$action = trim($body['action'] ?? '');

try {
    match($action) {
        'add'    => api_add($body),
        'ledger' => api_ledger($body),
        'adjust' => api_adjust($body),
        default  => fail('Unknown action')
    };
} catch (Throwable $e) {
    fail($e->getMessage());
}

// ── Add advance payment ───────────────────────────────────────
function api_add(array $b): void {
    $custId  = (int)($b['customer_id'] ?? 0);
    $amount  = (float)($b['amount']    ?? 0);
    $account = trim($b['account']      ?? 'Cash');
    $note    = trim($b['note']         ?? '');

    if (!$custId)     fail('Missing customer');
    if ($amount <= 0) fail('Amount must be greater than zero');

    $cus = db_row("SELECT * FROM customers WHERE id = ?", [$custId]);
    if (!$cus) fail('Customer not found');

    db()->beginTransaction();
    try {
        // Add to customer advance balance
        db_run(
            "UPDATE customers SET advance = advance + ? WHERE id = ?",
            [$amount, $custId]
        );

        // Record in cash ledger (money coming in — a receipt)
        $ref = 'ADV-' . $custId . '-' . date('YmdHis');
        $ledgerId = db_insert(
            "INSERT INTO cash_ledger (date,description,account,type,amount,ref)
             VALUES (?,?,?,'in',?,?)",
            [
                date('Y-m-d'),
                "Advance received — {$cus['name']}" . ($note ? " ($note)" : ''),
                $account,
                $amount,
                $ref,
            ]
        );
        enqueue_sync('cash_ledger', $ledgerId, 'INSERT',
            db_row("SELECT * FROM cash_ledger WHERE id = ?", [$ledgerId]));
        enqueue_sync('customers', $custId, 'UPDATE', db_row("SELECT * FROM customers WHERE id = ?", [$custId]));

        db()->commit();
        ok(['msg' => 'Advance recorded', 'ref' => $ref,
            'new_advance' => (float)$cus['advance'] + $amount]);

    } catch (Throwable $e) {
        db()->rollBack();
        fail('Save failed: ' . $e->getMessage());
    }
}

// ── Advance ledger for a customer ────────────────────────────
function api_ledger(array $b): void {
    $custId = (int)($b['customer_id'] ?? 0);
    if (!$custId) fail('Missing customer');

    $cus = db_row(
        "SELECT id,name,advance,due FROM customers WHERE id = ?", [$custId]
    );
    if (!$cus) fail('Customer not found');

    // Get all advance-related cash ledger entries
    $txns = db_rows(
        "SELECT * FROM cash_ledger
          WHERE ref LIKE ?
          ORDER BY date DESC, id DESC",
        ['ADV-' . $custId . '-%']
    );

    // Get invoices where advance was used
    $adjustments = db_rows(
        "SELECT id, invoice, date, advance_used, final_price, customer_name
           FROM sales
          WHERE customer_id = ? AND advance_used > 0
          ORDER BY date DESC",
        [$custId]
    );

    ok([
        'customer'    => $cus,
        'txns'        => $txns,
        'adjustments' => $adjustments,
    ]);
}

// ── Adjust advance against an existing invoice ───────────────
function api_adjust(array $b): void {
    $saleId = (int)($b['sale_id'] ?? 0);
    $amount = (float)($b['amount'] ?? 0);

    if (!$saleId)     fail('Missing sale id');
    if ($amount <= 0) fail('Amount must be greater than zero');

    $sale = db_row("SELECT * FROM sales WHERE id = ?", [$saleId]);
    if (!$sale) fail('Sale not found');

    $custId = (int)$sale['customer_id'];
    if ($custId <= 1) fail('Cannot adjust advance for walk-in customer');

    $cus = db_row("SELECT * FROM customers WHERE id = ?", [$custId]);
    if (!$cus) fail('Customer not found');

    $available = (float)$cus['advance'];
    if ($amount > $available + 0.001)
        fail("Only {$available} advance available");
    if ($amount > (float)$sale['due'] + 0.001)
        fail("Amount exceeds invoice due ({$sale['due']})");

    db()->beginTransaction();
    try {
        $newDue       = max(0, (float)$sale['due']  - $amount);
        $newPaid      = (float)$sale['paid'] + $amount;
        $newAdvUsed   = (float)($sale['advance_used'] ?? 0) + $amount;
        $newStatus    = $newDue <= 0.001 ? 'Paid' : 'Partial';
        $newCustAdv   = max(0, $available - $amount);

        // Update sale
        db_run(
            "UPDATE sales
                SET paid = ?, due = ?, advance_used = ?, status = ?
              WHERE id = ?",
            [$newPaid, $newDue, $newAdvUsed, $newStatus, $saleId]
        );

        // Reduce customer advance
        db_run(
            "UPDATE customers SET advance = ? WHERE id = ?",
            [$newCustAdv, $custId]
        );

        // Log in cash ledger
        $ref = 'ADV-' . $custId . '-ADJ-' . date('YmdHis');
        $ledgerId = db_insert(
            "INSERT INTO cash_ledger (date,description,account,type,amount,ref)
             VALUES (?,?,'Cash','in',?,?)",
            [
                date('Y-m-d'),
                "Advance adjusted — {$cus['name']} against {$sale['invoice']}",
                $amount,
                $ref,
            ]
        );
        enqueue_sync('cash_ledger', $ledgerId, 'INSERT',
            db_row("SELECT * FROM cash_ledger WHERE id = ?", [$ledgerId]));
        enqueue_sync('sales', $saleId, 'UPDATE', db_row("SELECT * FROM sales WHERE id = ?", [$saleId]));
        enqueue_sync('customers', $custId, 'UPDATE', db_row("SELECT * FROM customers WHERE id = ?", [$custId]));

        db()->commit();
        ok(['msg' => 'Advance adjusted successfully',
            'new_due' => $newDue, 'new_advance' => $newCustAdv]);

    } catch (Throwable $e) {
        db()->rollBack();
        fail('Adjustment failed: ' . $e->getMessage());
    }
}

function ok(array $extra = []): void {
    echo json_encode(array_merge(['success' => true], $extra));
    exit;
}
function fail(string $msg): never {
    echo json_encode(['success' => false, 'error' => $msg]);
    exit;
}
