<?php
/**
 * API Endpoint: Trading Instruments
 * Devuelve la lista de instrumentos de trading disponibles
 */

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

// Verificar autenticación del cliente con manejo seguro
$clientId = $_SESSION['client_id'] ?? null;
$clientStatus = $_SESSION['client_status'] ?? null;
$authorized = ($clientId && $clientStatus === 'active');
 
// En modo invitado permitimos continuar y devolvemos una lista mínima

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

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

try {
    $db = Database::getInstance();
    $pdo = $db->getConnection();
    // Integra Finage para precios en tiempo real y % diario
    require_once __DIR__ . '/../finage_api.php';
    $finage = getFinageAPI();
    $cfgPath = __DIR__ . '/../../../config/finage_config.php';
    if (function_exists('opcache_invalidate')) { @opcache_invalidate($cfgPath, true); }
    $cfg = include $cfgPath;
    $targetFx = ['AUDUSD','EURUSD','GBPUSD','USDCAD','USDJPY'];
    $extraFx = ['NZDUSD','EURGBP','EURJPY','GBPJPY','USDTRY','USDZAR','USDMXN','USDINR','USDBRL','EURTRY','GBPZAR','AUDMXN','USDPLN','USDRUB'];
    $targetFx = array_values(array_unique(array_merge($targetFx, $extraFx)));
    $requestedStocks = ['AMD','AMZN','META','GOOGL','JPM','BAC','WFC','C','GS','MS','BLK'];
    $baseStocks = isset($cfg['stock_symbols']) && is_array($cfg['stock_symbols']) ? $cfg['stock_symbols'] : ['AAPL','MSFT','AMZN','GOOGL','META','TSLA','NVDA','JPM','V','NFLX'];
    $targetStocks = array_values(array_unique(array_merge($baseStocks, $requestedStocks)));
    $targetIndices = ['SPX','NDX','DJI','FTSE','GDAXI','N225','HSI','FCHI'];
    $targetCommodities = ['XAUUSD','XAGUSD','XPDUSD','USOIL','WTIUSD','XBRUSD','UKOILUSD','COPPERUSD','CORNUSD','SUGARUSD'];
    $targetSymbols = array_merge($targetFx, $targetStocks, $targetIndices, $targetCommodities);

    
    // Obtener instrumentos de trading (ajustado al esquema real)
    $stmt = $pdo->prepare("
        SELECT 
            symbol,
            name,
            category,
            base_currency,
            quote_currency,
            pip_size,
            pip_value,
            min_volume,
            max_volume,
            volume_step,
            contract_size,
            margin_rate,
            commission,
            swap_long,
            swap_short,
            spread_type,
            spread_value,
            is_active
        FROM trading_instruments 
        WHERE is_active = 1
        ORDER BY category, symbol
    ");
    $stmt->execute();
    $instruments = $stmt->fetchAll(PDO::FETCH_ASSOC);
    // Seed en BD los pares FX adicionales si no existen
    try {
        $check = $pdo->prepare("SELECT COUNT(*) FROM trading_instruments WHERE symbol = ?");
        $insert = $pdo->prepare("INSERT INTO trading_instruments (
            symbol, name, category, base_currency, quote_currency, pip_size, pip_value, min_volume, max_volume, volume_step, contract_size, margin_rate, commission, swap_long, swap_short, spread_type, spread_value, is_active
        ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1)");
        foreach ($targetFx as $sym) {
            $S = strtoupper($sym);
            $check->execute([$S]);
            $exists = (int)$check->fetchColumn() > 0;
            if (!$exists) {
                $base = substr($S,0,3);
                $quote = substr($S,3,3);
                $pipSize = (str_contains($S,'JPY')?0.01:0.0001);
                $insert->execute([$S,$S,'forex',$base,$quote,$pipSize,1,0.01,50,0.01,100000,0.02,0,0,0,'variable',null]);
            }
        }
        foreach ($targetStocks as $sym) {
            $S = strtoupper($sym);
            $check->execute([$S]);
            $exists = (int)$check->fetchColumn() > 0;
            if (!$exists) {
                $insert->execute([$S,$S,'stocks',null,'USD',0.01,1,1,10000,1,1,1,0,0,0,'variable',null]);
            }
        }
        foreach ($targetIndices as $sym) {
            $S = strtoupper($sym);
            $check->execute([$S]);
            $exists = (int)$check->fetchColumn() > 0;
            if (!$exists) {
                $insert->execute([$S,$S,'indices',null,'USD',0.01,1,1,10000,1,1,1,0,0,0,'variable',null]);
            }
        }
        foreach ($targetCommodities as $sym) {
            $S = strtoupper($sym);
            $check->execute([$S]);
            $exists = (int)$check->fetchColumn() > 0;
            if (!$exists) {
                $base = (str_ends_with($S,'USD') && strlen($S) > 3) ? substr($S,0,strlen($S)-3) : null;
                $quote = (str_ends_with($S,'USD')) ? 'USD' : 'USD';
                $pipSize = 0.01;
                $insert->execute([$S,$S,'commodities',$base,$quote,$pipSize,1,1,10000,1,1,1,0,0,0,'variable',null]);
            }
        }
    } catch (\Throwable $e) { error_log('Seed FX error: '.$e->getMessage()); }
    $existing = [];
    foreach ($instruments as $it) { $existing[strtoupper($it['symbol'])] = true; }
    // Asegurar FX por defecto
    foreach ($targetFx as $sym) {
        $S = strtoupper($sym);
        if (!isset($existing[$S])) {
            $instruments[] = [
                'symbol' => $S,
                'name' => $S,
                'category' => 'forex',
                'base_currency' => substr($S,0,3),
                'quote_currency' => substr($S,3,3),
                'pip_size' => (str_contains($S,'JPY')?0.01:0.0001),
                'pip_value' => 1,
                'min_volume' => 0.01,
                'max_volume' => 50,
                'volume_step' => 0.01,
                'contract_size' => 100000,
                'margin_rate' => 0.02,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
            $existing[$S] = true;
        }
    }
    // Asegurar acciones solicitadas
    foreach ($targetStocks as $sym) {
        $S = strtoupper($sym);
        if (!isset($existing[$S])) {
            $instruments[] = [
                'symbol' => $S,
                'name' => $S,
                'category' => 'stocks',
                'base_currency' => null,
                'quote_currency' => 'USD',
                'pip_size' => 0.01,
                'pip_value' => 1,
                'min_volume' => 1,
                'max_volume' => 10000,
                'volume_step' => 1,
                'contract_size' => 1,
                'margin_rate' => 1,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
            $existing[$S] = true;
        }
    }
    // Asegurar índices
    foreach ($targetIndices as $sym) {
        $S = strtoupper($sym);
        if (!isset($existing[$S])) {
            $instruments[] = [
                'symbol' => $S,
                'name' => $S,
                'category' => 'indices',
                'base_currency' => null,
                'quote_currency' => 'USD',
                'pip_size' => 0.01,
                'pip_value' => 1,
                'min_volume' => 1,
                'max_volume' => 10000,
                'volume_step' => 1,
                'contract_size' => 1,
                'margin_rate' => 1,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
            $existing[$S] = true;
        }
    }
    // Asegurar materias primas
    foreach ($targetCommodities as $sym) {
        $S = strtoupper($sym);
        if (!isset($existing[$S])) {
            $instruments[] = [
                'symbol' => $S,
                'name' => $S,
                'category' => 'commodities',
                'base_currency' => (str_ends_with($S,'USD') && strlen($S) > 3) ? substr($S,0,strlen($S)-3) : null,
                'quote_currency' => (str_ends_with($S,'USD')) ? 'USD' : 'USD',
                'pip_size' => 0.01,
                'pip_value' => 1,
                'min_volume' => 1,
                'max_volume' => 10000,
                'volume_step' => 1,
                'contract_size' => 1,
                'margin_rate' => 1,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
            $existing[$S] = true;
        }
    }
    if (!is_array($instruments) || count($instruments) === 0) {
        $instruments = [];
        foreach ($targetFx as $sym) {
            $instruments[] = [
                'symbol' => $sym,
                'name' => $sym,
                'category' => 'forex',
                'base_currency' => substr($sym,0,3),
                'quote_currency' => substr($sym,3,3),
                'pip_size' => (strpos($sym,'JPY')!==false)?0.01:0.0001,
                'pip_value' => 1,
                'min_volume' => 0.01,
                'max_volume' => 50,
                'volume_step' => 0.01,
                'contract_size' => 100000,
                'margin_rate' => 0.02,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
        }
        foreach ($targetStocks as $sym) {
            $instruments[] = [
                'symbol' => $sym,
                'name' => $sym,
                'category' => 'stocks',
                'base_currency' => null,
                'quote_currency' => 'USD',
                'pip_size' => 0.01,
                'pip_value' => 1,
                'min_volume' => 1,
                'max_volume' => 10000,
                'volume_step' => 1,
                'contract_size' => 1,
                'margin_rate' => 1,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
        }
        foreach ($targetIndices as $sym) {
            $instruments[] = [
                'symbol' => $sym,
                'name' => $sym,
                'category' => 'indices',
                'base_currency' => null,
                'quote_currency' => 'USD',
                'pip_size' => 0.01,
                'pip_value' => 1,
                'min_volume' => 1,
                'max_volume' => 10000,
                'volume_step' => 1,
                'contract_size' => 1,
                'margin_rate' => 1,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
        }
        foreach ($targetCommodities as $sym) {
            $instruments[] = [
                'symbol' => $sym,
                'name' => $sym,
                'category' => 'commodities',
                'base_currency' => (str_ends_with($sym,'USD') && strlen($sym) > 3) ? substr($sym,0,strlen($sym)-3) : null,
                'quote_currency' => (str_ends_with($sym,'USD')) ? 'USD' : 'USD',
                'pip_size' => 0.01,
                'pip_value' => 1,
                'min_volume' => 1,
                'max_volume' => 10000,
                'volume_step' => 1,
                'contract_size' => 1,
                'margin_rate' => 1,
                'commission' => 0,
                'swap_long' => 0,
                'swap_short' => 0,
                'spread_type' => 'variable',
                'spread_value' => null,
                'is_active' => 1
            ];
        }
    }
    
    // Intentar obtener precios reales Finage para los símbolos objetivo
    $realPrices = [];
    try {
        // Sólo FX por este método
        $realPrices = $finage->getMultiplePrices($targetFx);
    } catch (\Throwable $e) {
        error_log('Finage prices error: ' . $e->getMessage());
        $realPrices = [];
    }

    // Agregar datos de precios desde Finage (modo rápido opcional)
    $fast = isset($_GET['fast']) ? (int)$_GET['fast'] : 0;
    foreach ($instruments as &$instrument) {
        $symbol = $instrument['symbol'];
        
        $cat = strtolower($instrument['category'] ?? '');
        $isStocks = ($cat === 'stocks');
        $isFx = ($cat === 'forex' || $cat === 'fx');
        // Preferir precios Finage para FX
        if ($isFx && in_array($symbol, $targetFx) && isset($realPrices[$symbol])) {
            $rp = $realPrices[$symbol];
            $instrument['bid'] = floatval($rp['bid']);
            $instrument['ask'] = floatval($rp['ask']);
            $mid = ($instrument['bid'] + $instrument['ask']) / 2.0;
            // Calcular % diario: modo rápido usa change_percent del snapshot múltiple si existe
            $change = 0.0; $changePct = 0.0;
            if ($fast) {
                if (isset($rp['change_percent'])) $changePct = floatval($rp['change_percent']);
            } else {
                try {
                    $candles = $finage->getHistoricalData($symbol, '1day', 2, 'forex');
                    if (is_array($candles) && count($candles) >= 2) {
                        $prevClose = floatval($candles[count($candles)-2]['close']);
                        $change = $mid - $prevClose;
                        if ($prevClose > 0) { $changePct = ($change / $prevClose) * 100.0; }
                    }
                    if (!$changePct && isset($rp['change_percent'])) {
                        $changePct = floatval($rp['change_percent']);
                    }
                } catch (\Throwable $e) {
                    error_log('Finage daily change error ' . $symbol . ': ' . $e->getMessage());
                }
            }

            $instrument['change'] = $change;
            $instrument['change_percent'] = $changePct;
            // Alias para compatibilidad con el frontend
            $instrument['changePercent'] = $instrument['change_percent'];
        } elseif ($isStocks) {
            // Determinar si mercado USA está abierto (ET)
            $dt = new \DateTime('now', new \DateTimeZone('America/New_York'));
            $wd = (int)$dt->format('N'); // 1..7
            $mins = ((int)$dt->format('H'))*60 + (int)$dt->format('i');
            $openM = 9*60+30; $closeM = 16*60;
            $marketOpen = ($wd >= 1 && $wd <= 5 && $mins >= $openM && $mins < $closeM);
            try {
                // Snapshot de acciones: incluye últimas cotizaciones y trades
                $snapMap = $finage->getStockSnapshot([$symbol]);
                $key = strtoupper($symbol);
                $sd = $snapMap[$key] ?? $snapMap[$symbol] ?? null;
                $px = null;
                if (is_array($sd)) {
                    // Preferir último trade como "último precio"
                    if (isset($sd['last_price'])) {
                        $px = floatval($sd['last_price']);
                    } elseif (isset($sd['bid']) && isset($sd['ask'])) {
                        $px = (floatval($sd['bid']) + floatval($sd['ask'])) / 2.0;
                    } elseif (isset($sd['bid'])) {
                        $px = floatval($sd['bid']);
                    } elseif (isset($sd['ask'])) {
                        $px = floatval($sd['ask']);
                    }
                }
                if ($px === null) {
                    // Fallback: usar último cierre diario
                    try {
                        $hist = $finage->getHistoricalData($symbol, '1day', 2, 'stock');
                        if (is_array($hist) && count($hist) >= 1) {
                            $last = $hist[count($hist)-1];
                            if (isset($last['close'])) { $px = floatval($last['close']); }
                            // Guardar prevClose si hay al menos 2
                            if (count($hist) >= 2) {
                                $prevBar = $hist[count($hist)-2];
                                if (isset($prevBar['close'])) { $instrument['prevClose'] = floatval($prevBar['close']); }
                                if (isset($prevBar['open'])) { $instrument['open'] = floatval($prevBar['open']); }
                            }
                        }
                    } catch (\Throwable $ex) { /* noop */ }
                }
                if ($px !== null) {
                    if ($marketOpen) {
                        $instrument['bid'] = $px;
                        $instrument['ask'] = $px;
                        $instrument['frozen'] = 0;
                    } else {
                        // Mercado cerrado: congelar al último precio conocido
                        $instrument['bid'] = $px;
                        $instrument['ask'] = $px;
                        $instrument['frozen'] = 1;
                    }
                    $instrument['price'] = $px;
                }
                // Cambio: si tenemos last_price y bid/ask previos, intentar calcular; si no, dejar 0
                $instrument['change'] = $instrument['change'] ?? 0.0;
                $instrument['change_percent'] = $instrument['change_percent'] ?? 0.0;
                $instrument['changePercent'] = $instrument['change_percent'];
            } catch (\Throwable $e) {
                $instrument['bid'] = $instrument['bid'] ?? null;
                $instrument['ask'] = $instrument['ask'] ?? null;
                $instrument['change'] = $instrument['change'] ?? 0.0;
                $instrument['change_percent'] = $instrument['change_percent'] ?? 0.0;
                $instrument['changePercent'] = $instrument['change_percent'] ?? 0.0;
            }
        } else {
            $instrument['bid'] = null;
            $instrument['ask'] = null;
            $instrument['change'] = 0.0;
            $instrument['change_percent'] = 0.0;
            $instrument['changePercent'] = 0.0;
        }
        
        // Formatear valores para mostrar
        $decimals = ($instrument['symbol'] === 'USDJPY' || strpos($instrument['symbol'], 'JPY') !== false || strtolower($instrument['category']??'')==='stocks') ? 2 : 5;
        
        $instrument['bid_formatted'] = is_numeric($instrument['bid']) ? number_format($instrument['bid'], $decimals) : '-';
        $instrument['ask_formatted'] = is_numeric($instrument['ask']) ? number_format($instrument['ask'], $decimals) : '-';
        $instrument['change_formatted'] = ($instrument['change'] >= 0 ? '+' : '') . number_format($instrument['change'], $decimals);
        $instrument['change_percent_formatted'] = ($instrument['change_percent'] >= 0 ? '+' : '') . number_format($instrument['change_percent'], 2) . '%';
        // Asegurar campo que usa el frontend
        $instrument['changePercent'] = $instrument['change_percent'];
        
        // Determinar dirección del cambio
        $instrument['direction'] = $instrument['change'] >= 0 ? 'up' : 'down';
        
        // Calcular spread
        $instrument['spread'] = (is_numeric($instrument['ask']) && is_numeric($instrument['bid'])) ? ($instrument['ask'] - $instrument['bid']) : null;
        $instrument['spread_formatted'] = is_numeric($instrument['spread']) ? number_format($instrument['spread'], $decimals) : '-';
    }
    
    // Agrupar por categoría
    $groupedInstruments = [];
    foreach ($instruments as $instrument) {
        $category = $instrument['category'];
        if (!isset($groupedInstruments[$category])) {
            $groupedInstruments[$category] = [];
        }
        $groupedInstruments[$category][] = $instrument;
    }
    
    echo json_encode([
        'success' => true,
        'instruments' => $instruments,
        'grouped' => $groupedInstruments,
        'total_count' => count($instruments),
        'last_updated' => date('Y-m-d H:i:s')
    ]);
    
} catch (Exception $e) {
    error_log("Error en instruments.php: " . $e->getMessage());
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => 'Error interno del servidor'
    ]);
}
?>
