<?php

use App\Services\Forecasting\BeisImporter;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Http::preventStrayRequests();
});

function fakeBeisCsv(string $body, string $cdnUrl = 'https://assets.publishing.service.gov.uk/media/abc/weekly_road_fuel_prices_270426.csv'): void
{
    Http::fake([
        'https://www.gov.uk/api/content/government/statistics/weekly-road-fuel-prices' => Http::response([
            'details' => [
                'attachments' => [
                    ['title' => 'Weekly road fuel prices (Excel)', 'url' => 'https://assets.publishing.service.gov.uk/media/x/excel.xlsx'],
                    ['title' => 'Weekly road fuel prices (CSV) 2018 to 2026', 'url' => $cdnUrl],
                    ['title' => 'Weekly road fuel prices (CSV) 2003 to 2017', 'url' => 'https://assets.publishing.service.gov.uk/media/y/old.csv'],
                ],
            ],
        ]),
        $cdnUrl => Http::response($body, 200, ['Content-Type' => 'text/csv']),
    ]);
}

it('resolves the CSV URL from the gov.uk content API and upserts rows', function (): void {
    $csv = "Date,ULSP,ULSD,ULSP duty,ULSD duty,ULSP VAT,ULSD VAT\r\n"
        ."20/04/2026,157.62,191.24,52.95,52.95,20,20\r\n"
        ."27/04/2026,156.99,189.81,52.95,52.95,20,20\r\n";

    fakeBeisCsv($csv);

    $result = (new BeisImporter)->import();

    expect($result['parsed'])->toBe(2)
        ->and($result['latest_date'])->toBe('2026-04-27')
        ->and(DB::table('weekly_pump_prices')->count())->toBe(2);

    $row = DB::table('weekly_pump_prices')->where('date', '2026-04-27')->first();
    expect((int) $row->ulsp_pence)->toBe(15699)
        ->and((int) $row->ulsd_pence)->toBe(18981);
});

it('is idempotent on re-run with no new rows', function (): void {
    $csv = "Date,ULSP,ULSD,ULSP duty,ULSD duty,ULSP VAT,ULSD VAT\r\n"
        ."27/04/2026,156.99,189.81,52.95,52.95,20,20\r\n";
    fakeBeisCsv($csv);

    (new BeisImporter)->import();
    (new BeisImporter)->import();

    expect(DB::table('weekly_pump_prices')->count())->toBe(1);
});

it('updates existing rows when CSV values change (upsert)', function (): void {
    // Seed a stale row directly so we can prove the import overwrites it.
    DB::table('weekly_pump_prices')->insert([
        'date' => '2026-04-27',
        'ulsp_pence' => 15500,
        'ulsd_pence' => 18900,
        'ulsp_duty_pence' => 5295,
        'ulsd_duty_pence' => 5295,
        'ulsp_vat_pct' => 20,
        'ulsd_vat_pct' => 20,
    ]);

    $csv = "Date,ULSP,ULSD,ULSP duty,ULSD duty,ULSP VAT,ULSD VAT\r\n"
        ."27/04/2026,157.05,189.85,52.95,52.95,20,20\r\n";
    fakeBeisCsv($csv);

    (new BeisImporter)->import();

    $row = DB::table('weekly_pump_prices')->where('date', '2026-04-27')->first();
    expect((int) $row->ulsp_pence)->toBe(15705) // updated from 15500
        ->and((int) $row->ulsd_pence)->toBe(18985);
});

it('throws when gov.uk API does not contain the expected CSV attachment', function (): void {
    Http::fake([
        'https://www.gov.uk/api/content/government/statistics/weekly-road-fuel-prices' => Http::response([
            'details' => ['attachments' => [
                ['title' => 'Some other thing', 'url' => 'https://x'],
            ]],
        ]),
    ]);

    (new BeisImporter)->import();
})->throws(RuntimeException::class, 'did not return an attachment');

it('flushes the forecast cache after a successful import', function (): void {
    Cache::put('forecast:current:something', 'stale', 3600);

    $csv = "Date,ULSP,ULSD,ULSP duty,ULSD duty,ULSP VAT,ULSD VAT\r\n"
        ."27/04/2026,156.99,189.81,52.95,52.95,20,20\r\n";
    fakeBeisCsv($csv);

    (new BeisImporter)->import();

    expect(Cache::get('forecast:current:something'))->toBeNull();
});

it('skips malformed rows but imports the rest', function (): void {
    $csv = "Date,ULSP,ULSD,ULSP duty,ULSD duty,ULSP VAT,ULSD VAT\r\n"
        ."27/04/2026,156.99,189.81,52.95,52.95,20,20\r\n"
        ."not-a-date,123,123,52.95,52.95,20,20\r\n"
        ."20/04/2026,157.62,191.24,52.95,52.95,20,20\r\n";

    fakeBeisCsv($csv);

    $result = (new BeisImporter)->import();

    expect($result['parsed'])->toBe(2)
        ->and(DB::table('weekly_pump_prices')->count())->toBe(2);
});
