<?php
// /traderalign/api/accounts/close.php
//
// Closes a live/personal trading account.
// Validates the account belongs to the authenticated user and is in 'active' state.
// Updates lifecycle_state to 'closed', records the closure outcome, and inserts a lifecycle event.
//
// POST body: { account_id: string, outcome: string }
//
// Valid outcomes:
//   CAPITAL_DEPLETED, FULL_WITHDRAWAL, ACCOUNT_RETIRED,
//   ACCOUNT_MIGRATED, MANUAL_CLOSURE, OTHER

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'] ?? '');
$outcome = trim($input['outcome'] ?? '');

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

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

// Validate outcome is one of the allowed values
$validOutcomes = [
    'CAPITAL_DEPLETED',
    'FULL_WITHDRAWAL',
    'ACCOUNT_RETIRED',
    'ACCOUNT_MIGRATED',
    'MANUAL_CLOSURE',
    'OTHER',
];

if (!in_array($outcome, $validOutcomes, true)) {
    http_response_code(400);
    echo json_encode([
        'error' => 'Invalid outcome. Must be one of: ' . implode(', ', $validOutcomes),
    ]);
    exit;
}

try {
    $pdo->beginTransaction();

    // 2026-08-17 account-level workflow isolation — same rule as
    // transaction.php: closing an account is a real, permanent state
    // change, must never succeed against a foreign-workflow account.
    $closeWorkflowState = ValidationService::getWorkflowState($userId, $db);

    // Fetch the account and lock it — must be a personal account in 'active' state
    $account = $db->raw(
        "SELECT id, label, 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' => $closeWorkflowState,
        ]
    );

    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 can be closed via this endpoint']);
        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;
    }

    // Update the trading account to closed state
    $stmt = $pdo->prepare(
        "UPDATE trading_accounts
         SET lifecycle_state = 'closed',
             current_outcome = :outcome,
             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([
        ':outcome' => $outcome,
        ':account_id' => $accountId,
        ':uid' => $userId,
    ]);

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

    // Insert lifecycle event for account closure
    $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' => 'ACCOUNT_CLOSED',
    ]);

    $pdo->commit();

    echo json_encode([
        'success' => true,
        'message' => 'Account closed',
        'account_id' => $accountId,
        'lifecycle_display_id' => $acct['lifecycle_display_id'] ?? null,
        'label' => $acct['label'],
        'outcome' => $outcome,
        'previous_state' => 'active',
        'new_state' => 'closed',
    ]);
    exit;

} catch (Exception $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    // 2026-08-19 security fix: never echo a raw exception message to the
    // client — it can carry table/column/constraint names or other
    // internal detail. Logged server-side instead.
    error_log('accounts/close.php failed: ' . $e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => 'Failed to close account. Please try again.']);
    exit;
}