<?php
// includes/functions_wallet.php

/**
 * Updates a representative's wallet balance and records the transaction.
 * This function should be used for all wallet modifications.
 *
 * @param PDO $pdo The database connection object.
 * @param int $representative_id The ID of the representative.
 * @param float $amount The amount to add (positive) or deduct (negative).
 * @param string $type The type of transaction (e.g., 'deposit', 'payment', 'refund').
 * @param string $description A description of the transaction.
 * @param int|null $related_id An optional related ID (e.g., invoice ID).
 * @return bool True on success, false on failure.
 */
function updateWalletBalance(PDO $pdo, int $representative_id, float $amount, string $type, string $description, ?int $related_id = null): bool {
    try {
        $pdo->beginTransaction();

        // 1. Get current balance and lock the row
        $stmt = $pdo->prepare("SELECT wallet_balance FROM representatives WHERE id = ? FOR UPDATE");
        $stmt->execute([$representative_id]);
        $current_balance = $stmt->fetchColumn();

        if ($current_balance === false) {
            throw new Exception("Representative not found.");
        }

        $new_balance = $current_balance + $amount;

        // 2. Check for sufficient funds if it's a deduction
        if ($new_balance < 0) {
            // Not enough balance, but we don't throw an exception, just return false.
            // The calling code should handle this case.
            $pdo->rollBack();
            return false;
        }

        // 3. Update representative's wallet balance
        $stmt = $pdo->prepare("UPDATE representatives SET wallet_balance = ? WHERE id = ?");
        $stmt->execute([$new_balance, $representative_id]);

        // 4. Insert the transaction record
        $stmt = $pdo->prepare(
            "INSERT INTO transactions (representative_id, amount, type, description, related_id) VALUES (?, ?, ?, ?, ?)"
        );
        $stmt->execute([$representative_id, $amount, $type, $description, $related_id]);

        $pdo->commit();
        return true;

    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        error_log("Wallet Update Failed: " . $e->getMessage());
        return false;
    }
}

/**
 * Creates a new invoice for a representative.
 *
 * @param PDO $pdo
 * @param int $representative_id
 * @param array $items Array of invoice items, each item is an array with 'description', 'quantity', 'unit_price'.
 * @param string|null $due_date
 * @return int|false The new invoice ID on success, false on failure.
 */
function createInvoice(PDO $pdo, int $representative_id, array $items, ?string $due_date = null) {
    $total_amount = 0;
    foreach ($items as $item) {
        $total_amount += ($item['quantity'] * $item['unit_price']);
    }

    if ($total_amount <= 0) {
        return false;
    }

    try {
        $pdo->beginTransaction();

        // 1. Create the main invoice record
        $stmt = $pdo->prepare(
            "INSERT INTO invoices (representative_id, amount, status, due_date) VALUES (?, ?, 'unpaid', ?)"
        );
        $stmt->execute([$representative_id, $total_amount, $due_date]);
        $invoice_id = $pdo->lastInsertId();

        // 2. Add invoice items
        $stmt = $pdo->prepare(
            "INSERT INTO invoice_items (invoice_id, description, quantity, unit_price, total) VALUES (?, ?, ?, ?, ?)"
        );
        foreach ($items as $item) {
            $item_total = $item['quantity'] * $item['unit_price'];
            $stmt->execute([$invoice_id, $item['description'], $item['quantity'], $item['unit_price'], $item_total]);
        }

        $pdo->commit();
        return (int)$invoice_id;

    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        error_log("Invoice Creation Failed: " . $e->getMessage());
        return false;
    }
}

/**
 * Pays an invoice from the representative's wallet balance.
 *
 * @param PDO $pdo
 * @param int $invoice_id
 * @param int $representative_id
 * @return bool True on success, false on failure.
 */
function payInvoiceFromWallet(PDO $pdo, int $invoice_id, int $representative_id): bool {
    try {
        $pdo->beginTransaction();

        // 1. Get invoice details and lock the row
        $stmt = $pdo->prepare("SELECT * FROM invoices WHERE id = ? AND representative_id = ? FOR UPDATE");
        $stmt->execute([$invoice_id, $representative_id]);
        $invoice = $stmt->fetch();

        if (!$invoice || $invoice['status'] !== 'unpaid') {
            // Invoice not found, already paid, or doesn't belong to the user
            $pdo->rollBack();
            return false;
        }

        $amount_to_pay = (float)$invoice['amount'];

        // 2. Deduct amount from wallet
        $deduction_successful = updateWalletBalance(
            $pdo,
            $representative_id,
            -$amount_to_pay, // Negative amount for deduction
            'payment',
            "Payment for Invoice #{$invoice_id}",
            $invoice_id
        );

        if (!$deduction_successful) {
            // Insufficient funds
            $pdo->rollBack();
            return false;
        }

        // 3. Mark invoice as paid
        $stmt = $pdo->prepare("UPDATE invoices SET status = 'paid', paid_at = CURRENT_TIMESTAMP() WHERE id = ?");
        $stmt->execute([$invoice_id]);

        $pdo->commit();
        return true;

    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        error_log("Invoice Payment Failed: " . $e->getMessage());
        return false;
    }
}
