<?php

namespace App\Services;

use App\Models\Market;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class PriceService
{
    /**
     * CoinGecko API endpoint
     */
    protected const COINGECKO_API = 'https://api.coingecko.com/api/v3';

    /**
     * Get real-time price for a cryptocurrency
     * Fetches from CoinGecko API (free, no auth required)
     * 
     * @param string $symbol Currency symbol (e.g., "BTC", "ETH", "ICP")
     * @return float Price in USD
     */
    public static function getPrice(string $symbol): float
    {
        // Cache prices for 1 minute to avoid excessive API calls
        $cacheKey = "price_{$symbol}";

        return Cache::remember($cacheKey, 60, function () use ($symbol) {
            try {
                // Convert symbol to CoinGecko ID
                $coinId = self::getCoinGeckoId($symbol);

                if (!$coinId) {
                    return 0;
                }

                // Fetch from CoinGecko
                $response = Http::timeout(10)->get(self::COINGECKO_API . '/simple/price', [
                    'ids' => $coinId,
                    'vs_currencies' => 'usd',
                ]);

                if ($response->successful()) {
                    $data = $response->json();
                    if (isset($data[$coinId]['usd'])) {
                        return (float) $data[$coinId]['usd'];
                    }
                }

                return 0;
            } catch (\Exception $e) {
                Log::error("Price fetch error for {$symbol}: " . $e->getMessage());
                return 0;
            }
        });
    }

    /**
     * Get prices for multiple cryptocurrencies at once
     * More efficient than individual requests
     */
    public static function getPrices(array $symbols): array
    {
        $prices = [];
        $coinIds = [];

        // Get CoinGecko IDs for all symbols
        foreach ($symbols as $symbol) {
            $coinId = self::getCoinGeckoId($symbol);
            if ($coinId) {
                $coinIds[$symbol] = $coinId;
            }
        }

        if (empty($coinIds)) {
            return $prices;
        }

        try {
            // Fetch all prices in one request
            $response = Http::timeout(10)->get(self::COINGECKO_API . '/simple/price', [
                'ids' => implode(',', array_values($coinIds)),
                'vs_currencies' => 'usd',
            ]);

            if ($response->successful()) {
                $data = $response->json();
                foreach ($coinIds as $symbol => $coinId) {
                    $prices[$symbol] = isset($data[$coinId]['usd']) ? (float) $data[$coinId]['usd'] : 0;
                }
            }
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\Log::error("Batch price fetch error: " . $e->getMessage());
        }

        return $prices;
    }

    /**
     * Calculate real swap amount based on market prices
     * Converts FROM amount to TO amount using CoinGecko prices
     */
    public static function calculateSwapAmount(Market $fromMarket, Market $toMarket, float $fromAmount): float
    {
        // Extract symbols from asset (e.g., "BTC / USDT" -> "BTC")
        $fromSymbol = self::extractSymbol($fromMarket->asset);
        $toSymbol = self::extractSymbol($toMarket->asset);
        Log::info("fromSymbol: {$fromSymbol}, toSymbol: {$toSymbol}");
        // If it's a direct USDT/USD swap, no conversion needed
        if ($fromSymbol === 'USDT' && $toSymbol === 'USDT') {
            return $fromAmount;
        }

        // Get prices
        $fromPrice = self::getPrice($fromSymbol);
        $toPrice = self::getPrice($toSymbol);
        Log::info("fromPrice: {$fromPrice}, toPrice: {$toPrice}");
        if ($fromPrice == 0 || $toPrice == 0) {
            throw new \Exception("Unable to fetch market prices. Please try again.");
        }

        // Convert FROM amount to USD value, then to TO amount
        $usdValue = $fromAmount * $fromPrice;
        $toAmount = $usdValue / $toPrice;

        return round($toAmount, 8);
    }

    /**
     * Extract cryptocurrency symbol from asset format
     * "BTC / USDT" -> "BTC"
     * "ETH / USDT" -> "ETH"
     */
    protected static function extractSymbol(string $asset): string
    {
        $parts = explode('/', $asset);
        return strtolower(trim($parts[0]));
    }

    /**
     * Map cryptocurrency symbols to CoinGecko IDs
     * CoinGecko uses lowercase IDs like "bitcoin", "ethereum", etc.
     */
    protected static function getCoinGeckoId(string $symbol): ?string
    {
        $symbol = strtolower($symbol);

        $mapping = [
            'btc' => 'bitcoin',
            'eth' => 'ethereum',
            'usdt' => 'tether',
            'usdc' => 'usd-coin',
            'usd' => 'usd-coin',
            'icp' => 'internet-computer',
            'sol' => 'solana',
            'ada' => 'cardano',
            'xrp' => 'ripple',
            'doge' => 'dogecoin',
            'bnb' => 'binancecoin',
            'xmr' => 'monero',
            'ltc' => 'litecoin',
            'bch' => 'bitcoin-cash',
            'trx' => 'tron',
            'avax' => 'avalanche-2',
            'matic' => 'matic-network',
            'link' => 'chainlink',
            'dot' => 'polkadot',
            'vet' => 'vechain',
        ];

        return $mapping[$symbol] ?? null;
    }

    /**
     * Clear all cached prices
     */
    public static function clearPriceCache(): void
    {
        // This could be enhanced to clear all price_* keys
        \Illuminate\Support\Facades\Cache::flush();
    }
}
