<?php

use App\Enums\FuelType;
use App\Models\Station;
use App\Models\StationPrice;
use App\Models\StationPriceCurrent;
use App\Services\NationalFuelPredictionService;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('returns no_signal when there is insufficient price history', function () {
    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['predicted_direction'])->toBe('stable')
        ->and($result['signals']['trend']['enabled'])->toBeFalse()
        ->and($result['action'])->toBe('no_signal');
});

it('detects rising trend from consistently increasing daily averages', function () {
    $station = Station::factory()->create();

    // 7 days of prices rising at ~100 pence/day
    for ($daysAgo = 6; $daysAgo >= 0; $daysAgo--) {
        StationPrice::factory()->create([
            'station_id' => $station->node_id,
            'fuel_type' => FuelType::E10,
            'price_pence' => 14000 + ((6 - $daysAgo) * 100),
            'price_effective_at' => now()->subDays($daysAgo)->setTime(12, 0),
        ]);
    }

    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['signals']['trend']['direction'])->toBe('up')
        ->and($result['signals']['trend']['enabled'])->toBeTrue()
        ->and($result['predicted_direction'])->toBe('up')
        ->and($result['action'])->toBe('fill_now');
});

it('detects falling trend from consistently decreasing daily averages', function () {
    $station = Station::factory()->create();

    for ($daysAgo = 6; $daysAgo >= 0; $daysAgo--) {
        StationPrice::factory()->create([
            'station_id' => $station->node_id,
            'fuel_type' => FuelType::E10,
            'price_pence' => 16000 - ((6 - $daysAgo) * 100),
            'price_effective_at' => now()->subDays($daysAgo)->setTime(12, 0),
        ]);
    }

    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['signals']['trend']['direction'])->toBe('down')
        ->and($result['predicted_direction'])->toBe('down')
        ->and($result['action'])->toBe('wait');
});

it('returns current_avg from station_prices_current', function () {
    $station = Station::factory()->create();
    StationPriceCurrent::factory()->create([
        'station_id' => $station->node_id,
        'fuel_type' => FuelType::E10,
        'price_pence' => 14750,
    ]);

    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['current_avg'])->toBe(147.5);
});

it('includes all required keys in response', function () {
    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result)
        ->toHaveKeys([
            'fuel_type', 'current_avg', 'predicted_direction', 'predicted_change_pence',
            'confidence_score', 'confidence_label', 'action', 'reasoning',
            'prediction_horizon_days', 'region_key', 'methodology',
            'signals',
        ])
        ->and($result['signals'])->toHaveKeys([
            'trend', 'day_of_week', 'brand_behaviour',
            'national_momentum', 'regional_momentum', 'price_stickiness',
        ]);
});

it('always returns e10 as fuel_type', function () {
    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['fuel_type'])->toBe('e10');
});

it('returns national region_key without coordinates', function () {
    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['region_key'])->toBe('national');
});

it('returns regional region_key when coordinates are provided', function () {
    $result = app(NationalFuelPredictionService::class)->predict(51.5074, -0.1278);

    expect($result['region_key'])->toBe('regional');
});

it('enables regional_momentum signal when coordinates are provided', function () {
    $station = Station::factory()->create(['lat' => 51.5, 'lng' => -0.1]);

    for ($daysAgo = 6; $daysAgo >= 0; $daysAgo--) {
        StationPrice::factory()->create([
            'station_id' => $station->node_id,
            'fuel_type' => FuelType::E10,
            'price_pence' => 14000 + ((6 - $daysAgo) * 100),
            'price_effective_at' => now()->subDays($daysAgo)->setTime(12, 0),
        ]);
    }

    $result = app(NationalFuelPredictionService::class)->predict(51.5074, -0.1278);

    expect($result['signals']['regional_momentum']['enabled'])->toBeTrue();
});

it('disables regional_momentum signal without coordinates', function () {
    $result = app(NationalFuelPredictionService::class)->predict();

    expect($result['signals']['regional_momentum']['enabled'])->toBeFalse();
});

it('disables trend signal when r_squared is below 0.5', function () {
    $station = Station::factory()->create();

    // Highly erratic prices (zigzag pattern) — low R²
    $prices = [14000, 16000, 13000, 17000, 12000, 18000, 14500];
    foreach ($prices as $daysAgo => $price) {
        StationPrice::factory()->create([
            'station_id' => $station->node_id,
            'fuel_type' => FuelType::E10,
            'price_pence' => $price,
            'price_effective_at' => now()->subDays(count($prices) - 1 - $daysAgo)->setTime(12, 0),
        ]);
    }

    $result = app(NationalFuelPredictionService::class)->predict();

    // Trend signal may be disabled if both 5-day and 14-day lookbacks fail R² threshold
    expect($result['signals']['trend']['data_points'])->toBeInt();
});
