<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;

class ConnectedWalletService
{
    /**
     * Get wallet token balances in USD (WETH, ETH, USDC, USDT)
     * 
     * @param string $ethAddress Ethereum wallet address
     * @return array Formatted token values and total USD
     */
    public static function getWalletBalance($ethAddress)
    {
        // Validate Ethereum address
        if (!preg_match('/^0x[a-fA-F0-9]{40}$/', $ethAddress)) {
            return self::getEmptyResponse('Invalid Ethereum address');
        }

        $ethAddress = strtolower($ethAddress);
        
        // Cache key based on wallet address (2 minutes = 120 seconds)
        $cacheKey = "wallet_balance_{$ethAddress}";
        $cacheDuration = 120; // 2 minutes

        return Cache::remember($cacheKey, $cacheDuration, function () use ($ethAddress) {
            return self::fetchWalletBalance($ethAddress);
        });
    }

    /**
     * Fetch wallet token balances from external APIs
     * 
     * @param string $ethAddress Ethereum wallet address
     * @return array Formatted token values and total USD
     */
    private static function fetchWalletBalance($ethAddress)
    {
        try {
            $apiKey = config('services.etherscan.api_key');

            if (!$apiKey) {
                return self::getEmptyResponse('Etherscan API key not configured');
            }

            // Token info
            $tokens = [
                'ETH' => ['contract' => null, 'decimals' => 18],
                'WETH' => ['contract' => '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'decimals' => 18],
                'USDC' => ['contract' => '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 'decimals' => 6],
                'USDT' => ['contract' => '0xdAC17F958D2ee523a2206206994597C13D831ec7', 'decimals' => 6],
            ];


            $balances = [];

            // Get ETH balance using V2 API
            $response = Http::get('https://api.etherscan.io/v2/api', [
                'chainid' => 1,
                'module' => 'account',
                'action' => 'balance',
                'address' => $ethAddress,
                'tag' => 'latest',
                'apikey' => $apiKey,
            ]);


            $balances['ETH'] = ($response->successful() && $response->json()['status'] == '1')
                ? (float)$response->json()['result'] / 1e18
                : 0;

            // Get ERC-20 balances using V2 API
            foreach (['WETH', 'USDC', 'USDT'] as $symbol) {
                $response = Http::get('https://api.etherscan.io/v2/api', [
                    'chainid' => 1,
                    'module' => 'account',
                    'action' => 'tokenbalance',
                    'contractaddress' => $tokens[$symbol]['contract'],
                    'address' => $ethAddress,
                    'tag' => 'latest',
                    'apikey' => $apiKey,
                ]);


                $balances[$symbol] = ($response->successful() && $response->json()['status'] == '1')
                    ? (float)$response->json()['result'] / pow(10, $tokens[$symbol]['decimals'])
                    : 0;

                sleep(1);
            }

            // Get prices from CoinGecko
            $priceResponse = Http::get('https://api.coingecko.com/api/v3/simple/price', [
                'ids' => 'ethereum,usd-coin,tether',
                'vs_currencies' => 'usd',
            ]);

            $prices = [];
            if ($priceResponse->successful()) {
                $data = $priceResponse->json();
                $prices = [
                    'ETH' => $data['ethereum']['usd'] ?? 0,
                    'WETH' => $data['ethereum']['usd'] ?? 0,
                    'USDC' => $data['usd-coin']['usd'] ?? 0,
                    'USDT' => $data['tether']['usd'] ?? 0,
                ];
            }

            // Calculate USD values
            $result = [
                'success' => true,
                'address' => $ethAddress,
                'tokens' => [],
                'total_usd' => 0,
            ];

            foreach (['ETH', 'WETH', 'USDC', 'USDT'] as $symbol) {
                $balance = $balances[$symbol] ?? 0;
                $price = $prices[$symbol] ?? 0;
                $value = $balance * $price;

                $result['total_usd'] += $value;

                $result['tokens'][$symbol] = [
                    'balance' => round($balance, 8),
                    'price_usd' => $price,
                    'value_usd' => round($value, 2),
                    'formatted' => sprintf(
                        '%s %s ($%s)',
                        $symbol,
                        number_format($balance, 8, '.', ''),
                        number_format($value, 2)
                    ),
                ];
            }

            $result['total_usd'] = round($result['total_usd'], 2);

            return $result;
        } catch (\Exception $e) {
            Log::error('Wallet balance error: ' . $e);
            return self::getEmptyResponse($e->getMessage());
        }
    }

    /**
     * Get empty response with zeroed-out token values
     * 
     * @param string|null $error Error message if any
     * @return array
     */
    private static function getEmptyResponse(?string $error = null): array
    {
        $emptyToken = [
            'balance' => 0,
            'price_usd' => 0,
            'value_usd' => 0,
            'formatted' => '',
        ];

        return [
            'success' => false,
            'error' => $error,
            'address' => null,
            'tokens' => [
                'ETH' => $emptyToken,
                'WETH' => $emptyToken,
                'USDC' => $emptyToken,
                'USDT' => $emptyToken,
            ],
            'total_usd' => 0,
        ];
    }
}
