<?php
namespace App\Services;

use GuzzleHttp\Client;
use App\Core\Model;
use PDO;

class ExchangeRateService
{
    private $client;
    private $apiKey;
    private $baseUrl = 'https://v6.exchangerate-api.com/v6/';
    private $cacheTtl = 3600; // Cache rates for 1 hour (3600 seconds)

    public function __construct()
    {
        $this->client = new Client();
        $this->apiKey = $_ENV['EXCHANGE_RATE_API_KEY'] ?? '';
    }

    /**
     * Get exchange rate from one currency to another (with caching)
     */
    public function getRate($from, $to = 'KES')
    {
        if ($from === $to) {
            return 1.0;
        }

        // Try to get from cache first
        $cached = $this->getCachedRate($from, $to);
        if ($cached !== null) {
            return $cached;
        }

        // Fetch fresh from API
        $freshRate = $this->fetchRateFromApi($from, $to);
        if ($freshRate !== null) {
            $this->saveRateToCache($from, $to, $freshRate);
        }

        return $freshRate;
    }

    /**
     * Get all rates for a base currency (cached)
     */
    public function getAllRates($base = 'KES')
    {
        // Check cache for all rates
        $cached = $this->getCachedAllRates($base);
        if (!empty($cached)) {
            return $cached;
        }

        // Fetch fresh from API
        $freshRates = $this->fetchAllRatesFromApi($base);
        if (!empty($freshRates)) {
            $this->saveAllRatesToCache($base, $freshRates);
        }

        return $freshRates;
    }

    /**
     * Get cached rate from database
     */
    private function getCachedRate($from, $to)
    {
        $pdo = Model::getPDO();
        $stmt = $pdo->prepare("
            SELECT rate FROM exchange_rates 
            WHERE base_currency = ? AND target_currency = ? 
            AND last_updated > DATE_SUB(NOW(), INTERVAL ? SECOND)
        ");
        $stmt->execute([$from, $to, $this->cacheTtl]);
        return $stmt->fetchColumn() ?: null;
    }

    /**
     * Get all cached rates for a base currency
     */
    private function getCachedAllRates($base)
    {
        $pdo = Model::getPDO();
        $stmt = $pdo->prepare("
            SELECT target_currency, rate FROM exchange_rates 
            WHERE base_currency = ? 
            AND last_updated > DATE_SUB(NOW(), INTERVAL ? SECOND)
        ");
        $stmt->execute([$base, $this->cacheTtl]);
        $rows = $stmt->fetchAll();
        $rates = [];
        foreach ($rows as $row) {
            $rates[$row['target_currency']] = $row['rate'];
        }
        return $rates;
    }

    /**
     * Save a single rate to cache
     */
    private function saveRateToCache($from, $to, $rate)
    {
        $pdo = Model::getPDO();
        $stmt = $pdo->prepare("
            INSERT INTO exchange_rates (base_currency, target_currency, rate, last_updated)
            VALUES (?, ?, ?, NOW())
            ON DUPLICATE KEY UPDATE rate = VALUES(rate), last_updated = NOW()
        ");
        $stmt->execute([$from, $to, $rate]);
    }

    /**
     * Save multiple rates to cache
     */
    private function saveAllRatesToCache($base, $rates)
    {
        $pdo = Model::getPDO();
        $pdo->beginTransaction();
        try {
            $stmt = $pdo->prepare("
                INSERT INTO exchange_rates (base_currency, target_currency, rate, last_updated)
                VALUES (?, ?, ?, NOW())
                ON DUPLICATE KEY UPDATE rate = VALUES(rate), last_updated = NOW()
            ");
            foreach ($rates as $target => $rate) {
                $stmt->execute([$base, $target, $rate]);
            }
            $pdo->commit();
        } catch (\Exception $e) {
            $pdo->rollBack();
            error_log("Failed to cache exchange rates: " . $e->getMessage());
        }
    }

    /**
     * Fetch a specific rate from the API
     */
    private function fetchRateFromApi($from, $to)
    {
        $rates = $this->fetchAllRatesFromApi($from);
        return $rates[$to] ?? null;
    }

    /**
     * Fetch all rates from the API
     */
    private function fetchAllRatesFromApi($base)
    {
        if (empty($this->apiKey)) {
            error_log("ExchangeRateService: No API key configured");
            return [];
        }

        try {
            $response = $this->client->get($this->baseUrl . $this->apiKey . '/latest/' . $base);
            $data = json_decode($response->getBody(), true);
            
            if ($data['result'] === 'success') {
                return $data['conversion_rates'] ?? [];
            } else {
                error_log("ExchangeRate API error: " . ($data['error-type'] ?? 'Unknown'));
            }
        } catch (\Exception $e) {
            error_log("ExchangeRate API exception: " . $e->getMessage());
        }

        return [];
    }

    /**
     * Force refresh all rates (useful for admin panel)
     */
    public function refreshAllRates($base = 'KES')
    {
        $pdo = Model::getPDO();
        $pdo->prepare("DELETE FROM exchange_rates WHERE base_currency = ?")->execute([$base]);
        return $this->getAllRates($base);
    }
}