<?php

namespace App\Services;

use App\Models\BrentPrice;
use App\Services\BrentPriceSources\BrentPriceFetchException;
use App\Services\BrentPriceSources\EiaBrentPriceSource;
use App\Services\BrentPriceSources\FredBrentPriceSource;

final readonly class BrentPriceFetcher
{
    public function __construct(
        private readonly EiaBrentPriceSource $eia,
        private readonly FredBrentPriceSource $fred,
    ) {}

    /**
     * Fetch from EIA and persist. Throws on failure.
     */
    public function fetchFromEia(): void
    {
        $rows = $this->eia->fetch();

        if ($rows === null) {
            throw new BrentPriceFetchException('EIA fetch returned no data');
        }

        BrentPrice::upsert($rows, ['date'], ['price_usd']);
    }

    /**
     * Fetch from FRED and persist. Throws on failure.
     */
    public function fetchFromFred(): void
    {
        $rows = $this->fred->fetch();

        if ($rows === null) {
            throw new BrentPriceFetchException('FRED fetch returned no data');
        }

        BrentPrice::upsert($rows, ['date'], ['price_usd']);
    }

    /**
     * One-shot Brent backfill via FRED's observation_start/end. Used to
     * seed `brent_prices` going back to 2018 so Phase 9's volatility
     * detector and Phase 8's LLM overlay have proper context.
     *
     * @return int rows inserted/updated
     */
    public function backfillFromFred(string $from, string $to): int
    {
        $rows = $this->fred->fetchRange($from, $to);

        if ($rows === null) {
            throw new BrentPriceFetchException("FRED backfill ({$from} → {$to}) returned no data");
        }

        BrentPrice::upsert($rows, ['date'], ['price_usd']);

        return count($rows);
    }
}
