<?php

namespace App\Console\Commands;

use App\Models\ExchangeRate;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

class WeshareFxSync extends Command
{
    protected $signature = 'weshare:fx-sync {--force : Ignore cache and sync now}';

    protected $description = 'Sync FX rates from OpenExchangeRates';

    public function handle(): int
    {
        $appId = (string) config('services.openexchangerates.app_id', '');
        if ($appId === '') {
            $this->error('Missing OpenExchangeRates app id. Set OPENEXCHANGERATES_APP_ID.');
            return self::FAILURE;
        }

        $cacheKey = 'fx:sync:lock';
        if (! $this->option('force') && Cache::get($cacheKey)) {
            $this->info('FX sync skipped (recently synced).');
            return self::SUCCESS;
        }

        $url = 'https://openexchangerates.org/api/latest.json';
        $res = Http::timeout(15)->get($url, [
            'app_id' => $appId,
        ]);

        if (! $res->ok()) {
            $this->error('OpenExchangeRates request failed: ' . $res->status());
            return self::FAILURE;
        }

        $json = $res->json();
        $base = strtoupper((string) ($json['base'] ?? 'USD'));
        $rates = (array) ($json['rates'] ?? []);
        $timestamp = isset($json['timestamp']) ? (int) $json['timestamp'] : null;
        $asOf = $timestamp ? now()->setTimestamp($timestamp) : now();

        if ($base !== 'USD') {
            // We can still store whatever base they return, but our conversion assumes USD pivot.
            $this->warn("Unexpected base={$base}; continuing but conversion assumes USD.");
        }

        $allowed = ['USD', 'BRL', 'EUR'];
        $now = now();

        foreach ($allowed as $quote) {
            if ($quote === 'USD') {
                ExchangeRate::query()->updateOrCreate(
                    ['base' => 'USD', 'quote' => 'USD'],
                    ['rate' => 1.0, 'as_of' => $asOf, 'updated_at' => $now]
                );
                continue;
            }

            $rate = $rates[$quote] ?? null;
            if (! is_numeric($rate)) {
                continue;
            }

            ExchangeRate::query()->updateOrCreate(
                ['base' => 'USD', 'quote' => $quote],
                ['rate' => (float) $rate, 'as_of' => $asOf, 'updated_at' => $now]
            );
        }

        Cache::put($cacheKey, true, 60 * 30);
        Cache::forget('fx:USD:USD');
        Cache::forget('fx:USD:BRL');
        Cache::forget('fx:USD:EUR');

        $this->info('FX sync complete.');
        return self::SUCCESS;
    }
}

