<?php
// /traderalign/api/accounts/transaction.php
//
// Handles deposits and withdrawals on live/personal trading accounts.
// Updates current_balance, net_deposits/net_withdrawals, and peak_equity.
// Automatically closes the account if a full withdrawal is made.
//
// POST body: { account_id: string, type: 'deposit' | 'withdrawal', amount: number }

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

$userId = $auth->requireAuth();

$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid request body']);
    exit;
}

$accountId = trim($input['account_id'] ?? '');
$type = trim($input['type'] ?? '');
$amount = (float)($input['amount'] ?? 0);

// Validate required fields
if ($accountId === '') {
    http_response_code(400);
    echo json_encode(['error' => 'account_id is required']);
    exit;
}

if ($type === '') {
    http_response_code(400);
    echo json_encode(['error' => 'type is required (deposit or withdrawal)']);
    exit;
}

if (!in_array($type, ['deposit', 'withdrawal'], true)) {
    http_response_code(400);
    echo json_encode(['error' => 'type must be "deposit" or "withdrawal"']);
    exit;
}

if ($amount <= 0) {
    http_response_code(400);
    echo json_encode(['error' => 'amount must be greater than 0']);
    exit;
}

try {
    $pdo->beginTransaction();

    // 2026-08-17 account-level workflow isolation: a deposit/withdrawal is a
    // real money operation — must never succeed against an account that
    // doesn't belong to the requester's CURRENT workflow (a crafted
    // account_id for the other workflow's account, otherwise invisible in
    // the now-scoped UI, would still have reached this endpoint before).
    $txWorkflowState = ValidationService::getWorkflowState($userId, $db);

    // Fetch and lock the account
    $account = $db->raw(
        "SELECT id, label, current_balance, net_deposits, net_withdrawals, peak_equity,
                lifecycle_state, account_type, lifecycle_display_id
         FROM trading_accounts
         WHERE id = :account_id
           AND user_id = :uid
           AND workflow_context = :wfctx
           AND deleted_at IS NULL
         FOR UPDATE",
        [
            ':account_id' => $accountId,
            ':uid' => $userId,
            ':wfctx' => $txWorkflowState,
        ]
    );

    if (empty($account)) {
        $pdo->rollBack();
        http_response_code(404);
        echo json_encode(['error' => 'Account not found']);
        exit;
    }

    $acct = $account[0];

    // Verify it's a personal account
    if ($acct['account_type'] !== 'personal') {
        $pdo->rollBack();
        http_response_code(400);
        echo json_encode(['error' => 'Only personal/live accounts support deposits and withdrawals']);
        exit;
    }

    // Verify it's in 'active' state
    if ($acct['lifecycle_state'] !== 'active') {
        $pdo->rollBack();
        http_response_code(400);
        echo json_encode([
            'error' => 'Account is not in active state. Current state: ' . $acct['lifecycle_state'],
        ]);
        exit;
    }

    $currentBalance = (float)($acct['current_balance'] ?? 0);
    $netDeposits = (float)($acct['net_deposits'] ?? 0);
    $netWithdrawals = (float)($acct['net_withdrawals'] ?? 0);
    $peakEquity = (float)($acct['peak_equity'] ?? 0);

    $newBalance = 0;
    $eventType = '';
    $isFullWithdrawal = false;

    // ── Handle Deposit ──
    if ($type === 'deposit') {
        $newBalance = $currentBalance + $amount;
        $newNetDeposits = $netDeposits + $amount;
        $newPeakEquity = $peakEquity;

        // Update peak_equity if new balance exceeds current peak
        if ($newBalance > $peakEquity) {
            $newPeakEquity = $newBalance;
        }

        $stmt = $pdo->prepare(
            "UPDATE trading_accounts
             SET current_balance = :new_balance,
                 net_deposits = :net_deposits,
                 peak_equity = :peak_equity,
                 updated_at = NOW()
             WHERE id = :account_id 
               AND user_id = :uid 
               AND deleted_at IS NULL"
        );
        $stmt->execute([
            ':new_balance' => $newBalance,
            ':net_deposits' => $newNetDeposits,
            ':peak_equity' => $newPeakEquity,
            ':account_id' => $accountId,
            ':uid' => $userId,
        ]);

        $eventType = 'CAPITAL_ADDED';
    }

    // ── Handle Withdrawal ──
    else {
        // Validate sufficient balance
        if ($amount > $currentBalance) {
            $pdo->rollBack();
            http_response_code(400);
            echo json_encode([
                'error' => 'Insufficient balance. Current balance: $' . number_format($currentBalance, 2) . 
                          ', withdrawal amount: $' . number_format($amount, 2),
            ]);
            exit;
        }

        $newBalance = $currentBalance - $amount;
        $newNetWithdrawals = $netWithdrawals + $amount;

        // Check if this is a full withdrawal (balance goes to zero)
        $tolerance = 0.01;
        $isFullWithdrawal = ($newBalance <= $tolerance);
        $newBalance = max(0, $newBalance); // Prevent negative due to floating point

        if ($isFullWithdrawal) {
            // Full withdrawal — close the account
            $stmt = $pdo->prepare(
                "UPDATE trading_accounts
                 SET current_balance = 0,
                     net_withdrawals = :net_withdrawals,
                     lifecycle_state = 'closed',
                     current_outcome = 'FULL_WITHDRAWAL',
                     boundary_event = 'ACCOUNT_CLOSED',
                     boundary_occurred_at = NOW(),
                     closed_at = NOW(),
                     updated_at = NOW()
                 WHERE id = :account_id 
                   AND user_id = :uid 
                   AND deleted_at IS NULL"
            );
            $stmt->execute([
                ':net_withdrawals' => $newNetWithdrawals,
                ':account_id' => $accountId,
                ':uid' => $userId,
            ]);

            $eventType = 'FULL_WITHDRAWAL';
        } else {
            // Partial withdrawal
            $newPeakEquity = $peakEquity;

            $stmt = $pdo->prepare(
                "UPDATE trading_accounts
                 SET current_balance = :new_balance,
                     net_withdrawals = :net_withdrawals,
                     peak_equity = :peak_equity,
                     updated_at = NOW()
                 WHERE id = :account_id 
                   AND user_id = :uid 
                   AND deleted_at IS NULL"
            );
            $stmt->execute([
                ':new_balance' => $newBalance,
                ':net_withdrawals' => $newNetWithdrawals,
                ':peak_equity' => $newPeakEquity,
                ':account_id' => $accountId,
                ':uid' => $userId,
            ]);

            $eventType = 'PARTIAL_WITHDRAWAL';
        }
    }

    if ($stmt->rowCount() === 0) {
        $pdo->rollBack();
        http_response_code(500);
        echo json_encode(['error' => 'Failed to update account']);
        exit;
    }

    // Insert lifecycle event
    $eventId = $db->uuid();
    $stmt = $pdo->prepare(
        "INSERT INTO lifecycle_events (id, account_id, account_type, event_type, occurred_at)
         VALUES (:id, :account_id, :account_type, :event_type, NOW())"
    );
    $stmt->execute([
        ':id' => $eventId,
        ':account_id' => $accountId,
        ':account_type' => 'live',
        ':event_type' => $eventType,
    ]);

    $pdo->commit();

    $response = [
        'success' => true,
        'account_id' => $accountId,
        'lifecycle_display_id' => $acct['lifecycle_display_id'] ?? null,
        'type' => $type,
        'amount' => $amount,
        'previous_balance' => $currentBalance,
        'new_balance' => $newBalance,
        'event' => $eventType,
    ];

    if ($isFullWithdrawal) {
        $response['account_closed'] = true;
        $response['lifecycle_state'] = 'closed';
    }

    echo json_encode($response);
    exit;

} catch (Exception $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    error_log('accounts/transaction.php failed: ' . $e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => 'Failed to process transaction. Please try again.']);
    exit;
}