<?php

use App\Models\Outcode;
use App\Models\Postcode;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

if (! function_exists('writeOnspdFixture')) {
    function writeOnspdFixture(string $contents): string
    {
        $path = tempnam(sys_get_temp_dir(), 'onspd_').'.csv';
        file_put_contents($path, $contents);

        return $path;
    }
}

it('imports active postcodes from an ONSPD CSV', function (): void {
    $csv = <<<'CSV'
pcd,pcds,doterm,lat,long
"SW1A1AA","SW1A 1AA","",51.501009,-0.141588
"M11AD","M1 1AD",,53.480957,-2.237428
CSV;

    $path = writeOnspdFixture($csv);

    $this->artisan('postcodes:import', ['--file' => $path])
        ->assertSuccessful();

    expect(Postcode::count())->toBe(2)
        ->and(Postcode::find('SW1A1AA')->outcode)->toBe('SW1A')
        ->and(Postcode::find('M11AD')->outcode)->toBe('M1');
});

it('skips terminated postcodes', function (): void {
    $csv = <<<'CSV'
pcd,pcds,doterm,lat,long
"SW1A1AA","SW1A 1AA","",51.501009,-0.141588
"OLD1AA","OLD 1AA","202301",50.000000,-1.000000
CSV;

    $path = writeOnspdFixture($csv);

    $this->artisan('postcodes:import', ['--file' => $path])->assertSuccessful();

    expect(Postcode::count())->toBe(1)
        ->and(Postcode::find('OLD1AA'))->toBeNull();
});

it('skips rows with blank coordinates', function (): void {
    $csv = <<<'CSV'
pcd,pcds,doterm,lat,long
"SW1A1AA","SW1A 1AA","",51.501009,-0.141588
"BT11AA","BT1 1AA","",,
CSV;

    $path = writeOnspdFixture($csv);

    $this->artisan('postcodes:import', ['--file' => $path])->assertSuccessful();

    expect(Postcode::count())->toBe(1)
        ->and(Postcode::find('BT11AA'))->toBeNull();
});

it('accepts ArcGIS ONSPD exports that use PCD7 instead of PCD', function (): void {
    $csv = <<<'CSV'
OBJECTID,PCD7,PCD8,PCDS,DOTERM,LAT,LONG,x,y
1,"SW1A 1AA","SW1A 1AA","SW1A 1AA","",51.501009,-0.141588,529090,179645
2,"M1   1AD","M1   1AD","M1 1AD","",53.480957,-2.237428,384730,398295
CSV;

    $path = writeOnspdFixture($csv);

    $this->artisan('postcodes:import', ['--file' => $path])->assertSuccessful();

    expect(Postcode::count())->toBe(2)
        ->and(Postcode::find('SW1A1AA')->outcode)->toBe('SW1A')
        ->and(Postcode::find('M11AD')->outcode)->toBe('M1');
});

it('derives outcode centroids as the average of member postcodes', function (): void {
    $csv = <<<'CSV'
pcd,pcds,doterm,lat,long
"PE71AA","PE7 1AA","",52.500000,-0.200000
"PE71AB","PE7 1AB","",52.600000,-0.220000
"M11AD","M1 1AD","",53.480957,-2.237428
CSV;

    $path = writeOnspdFixture($csv);

    $this->artisan('postcodes:import', ['--file' => $path])->assertSuccessful();

    $pe7 = Outcode::find('PE7');

    expect($pe7)->not->toBeNull()
        ->and(round((float) $pe7->lat, 6))->toBe(52.550000)
        ->and(round((float) $pe7->lng, 6))->toBe(-0.210000)
        ->and(Outcode::find('M1'))->not->toBeNull();
});
