<?php

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/ApiProviderRotationService.php';
require_once __DIR__ . '/CacheService.php';

class EconomicCalendarProviderService
{
    public static function fetchUpcoming(int $hoursAhead = 24): array
    {
        $cacheKey = 'economic_calendar:upcoming:' . $hoursAhead;

        return CacheService::remember($cacheKey, 300, function () use ($hoursAhead) {
            $providers = self::activeProviders();

            $lastError = '';

            foreach ($providers as $provider) {
                $name = strtolower(trim((string)($provider['provider'] ?? '')));
                $started = microtime(true);

                try {
                    if ($name === 'tradingeconomics') {
                        $result = self::fetchTradingEconomics($provider, $hoursAhead);
                    } elseif ($name === 'financialmodelingprep' || $name === 'fmp') {
                        $result = self::fetchFmpCalendar($provider);
                    } else {
                        $result = self::fetchGenericCalendar($provider);
                    }

                    $responseMs = (int)((microtime(true) - $started) * 1000);

                    if (!empty($result['success'])) {
                        ApiProviderRotationService::markSuccess($provider, 'economic_calendar', null, null, 1, $responseMs);
                        self::storeEvents($provider, $result['events']);

                        return [
                            'success' => true,
                            'provider' => $provider['provider'] ?? '',
                            'events' => $result['events']
                        ];
                    }

                    $lastError = $result['error'] ?? 'Calendar provider failed.';
                    ApiProviderRotationService::markFailure($provider, 'economic_calendar', $lastError, null, null, $responseMs);
                } catch (Throwable $e) {
                    $responseMs = (int)((microtime(true) - $started) * 1000);
                    $lastError = $e->getMessage();
                    ApiProviderRotationService::markFailure($provider, 'economic_calendar', $lastError, null, null, $responseMs);
                }
            }

            return [
                'success' => false,
                'provider' => null,
                'events' => [],
                'error' => $lastError ?: 'No economic calendar provider available.'
            ];
        });
    }

    private static function activeProviders(): array
    {
        $stmt = db()->query("
            SELECT *
            FROM api_settings
            WHERE is_active = 1
              AND (provider_type = 'economic_calendar' OR supports_calendar = 1)
              AND (cooldown_until IS NULL OR cooldown_until <= NOW())
            ORDER BY priority_order ASC, fail_count ASC, used_today ASC
        ");

        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }

    private static function fetchTradingEconomics(array $provider, int $hoursAhead): array
    {
        $base = rtrim($provider['base_url'] ?: 'https://api.tradingeconomics.com', '/');
        $key = trim((string)($provider['api_key'] ?? ''));

        if ($key === '') {
            return ['success' => false, 'error' => 'TradingEconomics API key is empty.'];
        }

        $from = date('Y-m-d');
        $to = date('Y-m-d', time() + ($hoursAhead * 3600));

        $response = self::httpGet($base . '/calendar', [
            'c' => $key,
            'd1' => $from,
            'd2' => $to,
            'format' => 'json'
        ]);

        if (is_array($response['json']) && $response['json']) {
            $events = [];

            foreach ($response['json'] as $item) {
                $events[] = [
                    'event_id' => $item['CalendarId'] ?? md5(json_encode($item)),
                    'event_time' => date('Y-m-d H:i:s', strtotime($item['Date'] ?? 'now')),
                    'country' => $item['Country'] ?? '',
                    'currency' => $item['Currency'] ?? '',
                    'impact' => strtoupper($item['Importance'] ?? $item['Impact'] ?? 'MEDIUM'),
                    'title' => $item['Event'] ?? $item['Category'] ?? 'Economic Event',
                    'actual' => $item['Actual'] ?? '',
                    'forecast' => $item['Forecast'] ?? '',
                    'previous' => $item['Previous'] ?? '',
                    'raw_payload' => json_encode($item)
                ];
            }

            return ['success' => true, 'events' => $events];
        }

        return ['success' => false, 'error' => $response['error'] ?: 'TradingEconomics returned no events.'];
    }

    private static function fetchFmpCalendar(array $provider): array
    {
        $base = rtrim($provider['base_url'] ?: 'https://financialmodelingprep.com/api/v3', '/');
        $key = trim((string)($provider['api_key'] ?? ''));

        if ($key === '') {
            return ['success' => false, 'error' => 'FMP API key is empty.'];
        }

        $response = self::httpGet($base . '/economic_calendar', [
            'from' => date('Y-m-d'),
            'to' => date('Y-m-d', time() + 86400),
            'apikey' => $key
        ]);

        if (is_array($response['json']) && $response['json']) {
            $events = [];

            foreach ($response['json'] as $item) {
                $events[] = [
                    'event_id' => md5(json_encode($item)),
                    'event_time' => date('Y-m-d H:i:s', strtotime($item['date'] ?? 'now')),
                    'country' => $item['country'] ?? '',
                    'currency' => $item['currency'] ?? '',
                    'impact' => strtoupper($item['impact'] ?? 'MEDIUM'),
                    'title' => $item['event'] ?? 'Economic Event',
                    'actual' => $item['actual'] ?? '',
                    'forecast' => $item['estimate'] ?? '',
                    'previous' => $item['previous'] ?? '',
                    'raw_payload' => json_encode($item)
                ];
            }

            return ['success' => true, 'events' => $events];
        }

        return ['success' => false, 'error' => $response['error'] ?: 'FMP returned no events.'];
    }

    private static function fetchGenericCalendar(array $provider): array
    {
        return ['success' => false, 'error' => 'Generic economic calendar adapter is not configured for this provider.'];
    }

    private static function storeEvents(array $provider, array $events): void
    {
        foreach ($events as $event) {
            try {
                db()->prepare("
                    INSERT INTO economic_calendar_events
                        (provider, event_id, event_time, country, currency, impact, title, actual, forecast, previous, raw_payload, created_at, updated_at)
                    VALUES
                        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
                    ON DUPLICATE KEY UPDATE
                        event_time = VALUES(event_time),
                        country = VALUES(country),
                        currency = VALUES(currency),
                        impact = VALUES(impact),
                        title = VALUES(title),
                        actual = VALUES(actual),
                        forecast = VALUES(forecast),
                        previous = VALUES(previous),
                        raw_payload = VALUES(raw_payload),
                        updated_at = NOW()
                ")->execute([
                    $provider['provider'] ?? '',
                    $event['event_id'] ?? md5(json_encode($event)),
                    $event['event_time'],
                    $event['country'] ?? '',
                    $event['currency'] ?? '',
                    $event['impact'] ?? '',
                    $event['title'] ?? '',
                    $event['actual'] ?? '',
                    $event['forecast'] ?? '',
                    $event['previous'] ?? '',
                    $event['raw_payload'] ?? json_encode($event)
                ]);
            } catch (Throwable $e) {
            }
        }
    }

    private static function httpGet(string $url, array $params): array
    {
        $fullUrl = $url . '?' . http_build_query($params);

        if (function_exists('curl_init')) {
            $ch = curl_init($fullUrl);
            curl_setopt_array($ch, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 25,
                CURLOPT_CONNECTTIMEOUT => 10,
                CURLOPT_SSL_VERIFYPEER => true
            ]);
            $body = curl_exec($ch);
            $error = curl_error($ch);
            curl_close($ch);
        } else {
            $body = @file_get_contents($fullUrl);
            $error = $body === false ? 'HTTP request failed' : '';
        }

        return [
            'json' => json_decode((string)$body, true) ?: [],
            'error' => $error
        ];
    }
}
