<?php

namespace App\Services;

use App\Models\Setting;
use App\Models\SportMatch;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class OddsApiService
{
    private Client $client;
    private string $apiKey;
    private string $baseUrl;
    private int $remainingRequests = -1;

    // TheOddsAPI v4 sport keys — covers all major sports
    public array $sportKeys = [
        // Soccer / Football
        'football'    => [
            'soccer_epl'               => ['league' => 'Premier League',   'country' => 'England'],
            'soccer_uefa_champ_league' => ['league' => 'Champions League', 'country' => 'Europe'],
            'soccer_bundesliga'        => ['league' => 'Bundesliga',        'country' => 'Germany'],
            'soccer_ligue_1'           => ['league' => 'Ligue 1',           'country' => 'France'],
            'soccer_serie_a'           => ['league' => 'Serie A',           'country' => 'Italy'],
            'soccer_spain_la_liga'     => ['league' => 'La Liga',           'country' => 'Spain'],
            'soccer_usa_mls'           => ['league' => 'MLS',               'country' => 'USA'],
            'soccer_netherlands_eredivisie' => ['league' => 'Eredivisie',   'country' => 'Netherlands'],
            'soccer_portugal_primeira_liga' => ['league' => 'Primeira Liga','country' => 'Portugal'],
            'soccer_uefa_europa_league'=> ['league' => 'Europa League',     'country' => 'Europe'],
        ],
        // Basketball
        'basketball'  => [
            'basketball_nba'           => ['league' => 'NBA',               'country' => 'USA'],
            'basketball_euroleague'    => ['league' => 'EuroLeague',        'country' => 'Europe'],
            'basketball_ncaab'         => ['league' => 'NCAA Basketball',   'country' => 'USA'],
        ],
        // American Football
        'americanfootball' => [
            'americanfootball_nfl'     => ['league' => 'NFL',               'country' => 'USA'],
            'americanfootball_ncaaf'   => ['league' => 'NCAA Football',     'country' => 'USA'],
        ],
        // Baseball
        'baseball'    => [
            'baseball_mlb'             => ['league' => 'MLB',               'country' => 'USA'],
        ],
        // Ice Hockey
        'hockey'      => [
            'icehockey_nhl'            => ['league' => 'NHL',               'country' => 'USA'],
        ],
        // Tennis
        'tennis'      => [
            'tennis_atp_french_open'   => ['league' => 'ATP French Open',   'country' => 'Global'],
            'tennis_atp_us_open'       => ['league' => 'ATP US Open',       'country' => 'Global'],
            'tennis_wta_us_open'       => ['league' => 'WTA US Open',       'country' => 'Global'],
        ],
        // Rugby
        'rugby'       => [
            'rugbyleague_nrl'          => ['league' => 'NRL',               'country' => 'Australia'],
            'rugbyunion_premiership'   => ['league' => 'Premiership Rugby', 'country' => 'England'],
        ],
        // Cricket
        'cricket'     => [
            'cricket_ipl'              => ['league' => 'IPL',               'country' => 'India'],
            'cricket_international_t20'=> ['league' => 'International T20', 'country' => 'Global'],
        ],
        // MMA
        'mma'         => [
            'mma_mixed_martial_arts'   => ['league' => 'UFC / MMA',         'country' => 'Global'],
        ],
        // Boxing
        'boxing'      => [
            'boxing_boxing'            => ['league' => 'Boxing',            'country' => 'Global'],
        ],
    ];

    public function __construct()
    {
        $this->apiKey  = (string) Setting::get('odds_api_key', config('services.odds_api.key', ''));
        $this->baseUrl = (string) Setting::get('odds_api_base_url', config('services.odds_api.base_url', 'https://api.the-odds-api.com/v4'));

        $this->client = new Client([
            'base_uri' => $this->baseUrl,
            'timeout'  => 15,
        ]);
    }

    public function hasKey(): bool
    {
        return (bool) Setting::get('odds_api_enabled', true)
            && !empty($this->apiKey)
            && $this->apiKey !== 'your_odds_api_key_here';
    }

    public function getRemainingRequests(): int
    {
        return $this->remainingRequests;
    }

    /** Fetch h2h odds for a specific sport key from TheOddsAPI */
    public function getOdds(string $sportKey): ?array
    {
        if (!$this->hasKey()) return null;

        try {
            $response = $this->client->get("/sports/{$sportKey}/odds", [
                'query' => [
                    'apiKey'      => $this->apiKey,
                    'regions'     => (string) Setting::get('odds_api_regions', 'eu,uk'),
                    'markets'     => (string) Setting::get('odds_api_markets', 'h2h'),
                    'oddsFormat'  => (string) Setting::get('odds_api_odds_format', 'decimal'),
                    'dateFormat'  => 'iso',
                ],
            ]);

            $this->remainingRequests = (int) ($response->getHeader('x-requests-remaining')[0] ?? -1);

            return json_decode($response->getBody()->getContents(), true);
        } catch (GuzzleException $e) {
            Log::warning("OddsAPI odds error [{$sportKey}]: " . $e->getMessage());
            return null;
        }
    }

    /** Fetch live scores for a specific sport key */
    public function getScores(string $sportKey, int $daysFrom = 1): ?array
    {
        if (!$this->hasKey()) return null;

        try {
            $response = $this->client->get("/sports/{$sportKey}/scores", [
                'query' => [
                    'apiKey'   => $this->apiKey,
                    'daysFrom' => $daysFrom,
                ],
            ]);

            $this->remainingRequests = (int) ($response->getHeader('x-requests-remaining')[0] ?? -1);

            return json_decode($response->getBody()->getContents(), true);
        } catch (GuzzleException $e) {
            Log::warning("OddsAPI scores error [{$sportKey}]: " . $e->getMessage());
            return null;
        }
    }

    /** Fetch event list (no odds — free, 0 credits) */
    public function getEvents(string $sportKey): ?array
    {
        if (!$this->hasKey()) return null;

        try {
            $response = $this->client->get("/sports/{$sportKey}/events", [
                'query' => ['apiKey' => $this->apiKey, 'dateFormat' => 'iso'],
            ]);
            return json_decode($response->getBody()->getContents(), true);
        } catch (GuzzleException $e) {
            Log::warning("OddsAPI events error [{$sportKey}]: " . $e->getMessage());
            return null;
        }
    }

    /** Get available sports list (0 credits) */
    public function getAllSports(): ?array
    {
        if (!$this->hasKey()) return null;

        try {
            $response = $this->client->get('/sports', [
                'query' => ['apiKey' => $this->apiKey],
            ]);
            return json_decode($response->getBody()->getContents(), true);
        } catch (GuzzleException $e) {
            Log::warning("OddsAPI sports list error: " . $e->getMessage());
            return null;
        }
    }

    /** Sync odds from API response into the sport_matches table */
    public function syncOddsToDatabase(array $events, string $sportType, string $league, string $country): int
    {
        $count = 0;
        foreach ($events as $event) {
            $odds = $this->extractBestOdds($event);
            if (!$odds['home'] || !$odds['away']) continue;

            SportMatch::updateOrCreate(
                ['external_id' => $event['id']],
                [
                    'sport'        => $sportType,
                    'league'       => $league,
                    'country'      => $country,
                    'home_team'    => $event['home_team'],
                    'away_team'    => $event['away_team'],
                    'home_odds'    => $odds['home'],
                    'draw_odds'    => $odds['draw'],
                    'away_odds'    => $odds['away'],
                    'status'       => 'upcoming',
                    'start_time'   => $event['commence_time'] ?? null,
                    'is_active'    => true,
                    'markets_count'=> count($event['bookmakers'] ?? []),
                ]
            );
            $count++;
        }
        return $count;
    }

    /** Sync live scores into the sport_matches table and return count of updates */
    public function syncScoresToDatabase(array $scores): int
    {
        $count = 0;
        foreach ($scores as $score) {
            $match = SportMatch::where('external_id', $score['id'])->first();
            if (!$match) continue;

            $homeScore = null;
            $awayScore = null;

            foreach ($score['scores'] ?? [] as $s) {
                if ($s['name'] === $score['home_team']) $homeScore = $s['score'];
                if ($s['name'] === $score['away_team']) $awayScore = $s['score'];
            }

            $completed  = $score['completed'] ?? false;
            $hasScores  = isset($score['scores']) && count($score['scores']) > 0;
            $isLive     = !$completed && $hasScores;

            $match->update([
                'home_score' => $homeScore,
                'away_score' => $awayScore,
                'status'     => $completed ? 'finished' : ($isLive ? 'live' : $match->status),
                'is_active'  => !$completed,
            ]);

            $count++;
        }
        return $count;
    }

    /** Sync odds for all configured sports — returns total matches synced */
    public function syncAll(): array
    {
        $results = [];
        foreach ($this->sportKeys as $sportType => $leagues) {
            foreach ($leagues as $apiKey => $meta) {
                $events = $this->getOdds($apiKey);
                if ($events) {
                    $n = $this->syncOddsToDatabase($events, $sportType, $meta['league'], $meta['country']);
                    $results[] = "  {$meta['country']} / {$meta['league']}: {$n} events";
                }
                // Stop if we're low on credits
                if ($this->remainingRequests >= 0 && $this->remainingRequests < 5) {
                    Log::warning('OddsAPI: Less than 5 credits remaining — stopping sync.');
                    break 2;
                }
            }
        }
        return $results;
    }

    /** Extract best h2h odds by averaging across all bookmakers */
    private function extractBestOdds(array $event): array
    {
        $homeTotal = $awayTotal = $drawTotal = 0;
        $homeCount = $awayCount = $drawCount = 0;

        foreach ($event['bookmakers'] ?? [] as $bookmaker) {
            foreach ($bookmaker['markets'] ?? [] as $market) {
                if ($market['key'] !== 'h2h') continue;
                foreach ($market['outcomes'] as $outcome) {
                    $price = (float) $outcome['price'];
                    if ($outcome['name'] === $event['home_team']) {
                        $homeTotal += $price; $homeCount++;
                    } elseif ($outcome['name'] === $event['away_team']) {
                        $awayTotal += $price; $awayCount++;
                    } elseif (strtolower($outcome['name']) === 'draw') {
                        $drawTotal += $price; $drawCount++;
                    }
                }
                break; // only first h2h market per bookmaker
            }
        }

        return [
            'home' => $homeCount > 0 ? round($homeTotal / $homeCount, 2) : null,
            'away' => $awayCount > 0 ? round($awayTotal / $awayCount, 2) : null,
            'draw' => $drawCount > 0 ? round($drawTotal / $drawCount, 2) : null,
        ];
    }

    /** Legacy method kept for backwards compatibility */
    public function syncToDatabase(array $events, string $sport): void
    {
        $meta = $this->sportKeys[$sport] ?? [];
        $firstMeta = reset($meta);
        $this->syncOddsToDatabase(
            $events,
            $sport,
            $firstMeta['league'] ?? $sport,
            $firstMeta['country'] ?? 'Global'
        );
    }
}
