<?php
/**
 * API Endpoint: Close Trading Position
 * Cierra una posición abierta del cliente
 */

session_start();

// Verificar autenticación del cliente
if (!isset($_SESSION['client_id']) || $_SESSION['client_status'] !== 'active') {
    http_response_code(401);
    echo json_encode(['error' => 'No autorizado']);
    exit;
}

// Solo permitir POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['error' => 'Método no permitido']);
    exit;
}

// Configuración de la base de datos
require_once __DIR__ . '/../../../database/connection.php';
require_once __DIR__ . '/../finage_api.php';

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

try {
    // Obtener datos de la solicitud
    $input = json_decode(file_get_contents('php://input'), true);
    
    if (!$input || empty($input['positionId'])) {
        throw new Exception('ID de posición requerido');
    }
    
    $positionId = intval($input['positionId']);
    $client_id = $_SESSION['client_id'];
    // Parámetro opcional: número de cuenta activo
    $accountNumber = !empty($input['account_number']) ? trim($input['account_number']) : null;
    
    // Obtener cuenta de trading del cliente
    $stmt = $pdo->prepare("
        SELECT id FROM trading_accounts 
        WHERE client_id = ? AND status = 'active'
        ORDER BY created_at DESC LIMIT 1
    ");
    $stmt->execute([$client_id]);
    $account = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$account) {
        throw new Exception('No se encontró cuenta de trading activa');
    }
    
    // Obtener la posición
    $stmt = $pdo->prepare("
        SELECT tp.*, ti.pip_size, ti.base_currency, ti.quote_currency, ti.category
        FROM trading_positions tp
        LEFT JOIN trading_instruments ti ON tp.symbol = ti.symbol
        WHERE tp.id = ? AND tp.account_id = ? AND tp.status = 'open'
    ");
    $stmt->execute([$positionId, $account['id']]);
    $position = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$position) {
        throw new Exception('Posición no encontrada o ya cerrada');
    }
    
    // Obtener precio actual para el cierre
    $assetType = mapAssetType($position['category'] ?? 'forex');
    $currentPrices = getCurrentPrices($position['symbol'], $assetType);
    $closePrice = ($position['type'] === 'buy') ? 
        $currentPrices['bid'] : 
        $currentPrices['ask'];
    
    // Calcular P&L
    $openPrice = floatval($position['open_price']);
    $volume = floatval($position['volume']);
    $symbol = $position['symbol'];
    
    $priceDiff = ($position['type'] === 'buy') ? 
        ($closePrice - $openPrice) : 
        ($openPrice - $closePrice);
    
    // Para pares JPY, el cálculo es diferente
    $isJpyPair = (strpos($symbol, 'JPY') !== false);
    $pipValue = $isJpyPair ? 0.01 : 0.0001;
    
    $pnl = ($priceDiff / $pipValue) * $pipValue * $volume * 100000; // Lot estándar
    
    if ($isJpyPair) {
        $pnl = $pnl / 100; // Ajuste para pares JPY
    }
    
    // Calcular comisión (simulada)
    $commission = $volume * 7.0; // $7 por lote
    $netPnl = $pnl - $commission;
    
    // Iniciar transacción
    $pdo->beginTransaction();
    
    try {
        // Cerrar la posición
        $stmt = $pdo->prepare("
            UPDATE trading_positions 
            SET status = 'closed',
                close_price = ?,
                closed_at = NOW(),
                profit = ?,
                commission = ?
            WHERE id = ?
        ");
        $stmt->execute([$closePrice, $netPnl, $commission, $positionId]);
        
        // Actualizar balance de la cuenta
        $stmt = $pdo->prepare("
            SELECT * FROM trading_accounts WHERE id = ?
        ");
        $stmt->execute([$account['id']]);
        $accountData = $stmt->fetch(PDO::FETCH_ASSOC);
        
        // Calcular margen liberado
        $leverage = floatval($accountData['leverage']);
        $marginReleased = ($volume * 100000 * $openPrice) / $leverage;
        
        // Actualizar balance
        $newBalance = $accountData['balance'] + $netPnl;
        $newEquity = $accountData['equity'] + $netPnl;
        $newMargin = $accountData['margin'] - $marginReleased;
        $newFreeMargin = $accountData['free_margin'] + $marginReleased;
        
        // Asegurar que los valores no sean negativos
        $newMargin = max(0, $newMargin);
        $newFreeMargin = max(0, $newFreeMargin);
        
        $stmt = $pdo->prepare("
            UPDATE trading_accounts 
            SET balance = ?,
                equity = ?,
                margin = ?,
                free_margin = ?,
                updated_at = NOW()
        WHERE id = ?
        ");
        $stmt->execute([$newBalance, $newEquity, $newMargin, $newFreeMargin, $account['id']]);
        
        // Sincronizar con cuentas del CRM si no es una cuenta demo
        if (strtolower($accountData['account_type'] ?? '') !== 'demo') {
            // Actualizar saldo en client_accounts usando client_id + account_number
            $clientId = (int)$accountData['client_id'];
            $accNumber = $accountData['account_number'] ?? null;
            if ($clientId > 0 && !empty($accNumber)) {
                // Actualizar balance CRM
                $stmtCa = $pdo->prepare("UPDATE client_accounts SET balance = ? WHERE client_id = ? AND account_number = ?");
                $stmtCa->execute([$newBalance, $clientId, $accNumber]);

                // Registrar ajuste por P&L en client_transactions
                $stmtTx = $pdo->prepare("INSERT INTO client_transactions (client_id, type, amount, currency, reference, notes, created_at) VALUES (?,?,?,?,?, ?, NOW())");
                $stmtTx->execute([
                    $clientId,
                    'adjustment',
                    $netPnl,
                    ($accountData['currency'] ?? 'USD'),
                    'P&L-' . $positionId,
                    'Ajuste de saldo por cierre de posición'
                ]);
            }
        }
        
        // Registrar la transacción en el historial
        $stmt = $pdo->prepare("
            INSERT INTO trading_history (
                account_id, position_id, symbol, type, volume,
                open_price, close_price, profit, commission,
                opened_at, closed_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
        ");
        $stmt->execute([
            $account['id'], $positionId, $symbol, $position['type'], $volume,
            $openPrice, $closePrice, $netPnl, $commission, $position['opened_at']
        ]);
        
        $pdo->commit();
        
        // Formatear respuesta
        $decimals = $isJpyPair ? 3 : 5;
        
        echo json_encode([
            'success' => true,
            'message' => 'Posición cerrada exitosamente',
            'position_id' => $positionId,
            'close_details' => [
                'symbol' => $symbol,
                'type' => $position['type'],
                'volume' => number_format($volume, 2),
                'open_price' => number_format($openPrice, $decimals),
                'close_price' => number_format($closePrice, $decimals),
                'pnl' => ($netPnl >= 0 ? '+' : '') . number_format($netPnl, 2),
                'commission' => number_format($commission, 2),
                'duration' => calculateTradeDuration($position['opened_at'])
            ],
            'account_update' => [
                'new_balance' => number_format($newBalance, 2),
                'new_equity' => number_format($newEquity, 2),
                'margin_released' => number_format($marginReleased, 2)
            ]
        ]);
        
    } catch (Exception $e) {
        $pdo->rollBack();
        throw $e;
    }
    
} catch (Exception $e) {
    error_log("Error en close-position.php: " . $e->getMessage());
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'message' => $e->getMessage()
    ]);
}

/**
 * Obtener precios actuales (simulados)
 */
function getCurrentPrices($symbol, $assetType) {
    $finage = getFinageAPI();
    $tick = $finage->getRealTimePrice($symbol);
    if (!is_array($tick)) throw new Exception('Proveedor sin datos');
    $bid = isset($tick['bid']) ? floatval($tick['bid']) : (isset($tick['price']) ? floatval($tick['price']) : null);
    $ask = isset($tick['ask']) ? floatval($tick['ask']) : (isset($tick['price']) ? floatval($tick['price']) : null);
    if (!is_numeric($bid) || !is_numeric($ask)) throw new Exception('Tick inválido');
    return ['bid' => $bid, 'ask' => $ask];
}

function mapAssetType($category) {
    $c = strtolower((string)$category);
    if (in_array($c, ['forex','fx'])) return 'forex';
    if (in_array($c, ['crypto'])) return 'crypto';
    if (in_array($c, ['stocks','equities'])) return 'stocks';
    if (in_array($c, ['indices','index'])) return 'indices';
    if (in_array($c, ['commodities','commodity'])) return 'commodities';
    return 'forex';
}

/**
 * Calcular duración del trade
 */
function calculateTradeDuration($openedAt) {
    $opened = new DateTime($openedAt);
    $now = new DateTime();
    $interval = $opened->diff($now);
    
    if ($interval->days > 0) {
        return $interval->days . ' día' . ($interval->days > 1 ? 's' : '') . 
               ' ' . $interval->h . ' hora' . ($interval->h > 1 ? 's' : '');
    } elseif ($interval->h > 0) {
        return $interval->h . ' hora' . ($interval->h > 1 ? 's' : '') . 
               ' ' . $interval->i . ' minuto' . ($interval->i > 1 ? 's' : '');
    } else {
        return $interval->i . ' minuto' . ($interval->i > 1 ? 's' : '') . 
               ' ' . $interval->s . ' segundo' . ($interval->s > 1 ? 's' : '');
    }
}
?>
