<?php

namespace App\Services\Prediction\Signals;

use Illuminate\Support\Facades\DB;

final class BrandBehaviourSignal extends AbstractSignal
{
    public function compute(SignalContext $context): array
    {
        $rows = DB::table('station_prices')
            ->join('stations', 'station_prices.station_id', '=', 'stations.node_id')
            ->where('station_prices.fuel_type', $context->fuelType->value)
            ->where('station_prices.price_effective_at', '>=', now()->subDays(7))
            ->selectRaw('stations.is_supermarket, DATE(station_prices.price_effective_at) as day, AVG(station_prices.price_pence) as avg_price')
            ->groupBy('stations.is_supermarket', 'day')
            ->orderBy('day')
            ->get();

        $supermarket = $rows->where('is_supermarket', 1)->values();
        $major = $rows->where('is_supermarket', 0)->values();

        if ($supermarket->count() < 2 || $major->count() < 2) {
            return $this->disabledSignal('Insufficient brand data for comparison');
        }

        $supermarketSlope = $this->linearRegression($supermarket->pluck('avg_price')->map(fn ($v) => (float) $v / 100)->values()->all())['slope'];
        $majorSlope = $this->linearRegression($major->pluck('avg_price')->map(fn ($v) => (float) $v / 100)->values()->all())['slope'];

        $divergence = round(abs($supermarketSlope - $majorSlope) * 7, 1);
        $supermarketChange = round($supermarketSlope * 7, 1);
        $majorChange = round($majorSlope * 7, 1);

        if ($divergence < 1.0) {
            return [
                'score' => 0.0,
                'confidence' => 0.5,
                'direction' => 'stable',
                'detail' => 'Supermarkets and majors moving in sync.',
                'data_points' => $rows->count(),
                'enabled' => true,
            ];
        }

        $leaderChange = abs($supermarketChange) > abs($majorChange) ? $supermarketChange : $majorChange;
        $direction = $leaderChange > 0 ? 'up' : 'down';
        $leader = abs($supermarketChange) > abs($majorChange) ? 'Supermarkets' : 'Majors';
        $follower = $leader === 'Supermarkets' ? 'majors' : 'supermarkets';
        $leaderAbs = abs($leaderChange);
        $followerChange = $leader === 'Supermarkets' ? abs($majorChange) : abs($supermarketChange);

        return [
            'score' => $direction === 'up' ? 1.0 : -1.0,
            'confidence' => min(1.0, $divergence / 5.0),
            'direction' => $direction,
            'detail' => "{$leader} ".($leaderChange > 0 ? 'rose' : 'fell')." {$leaderAbs}p vs {$follower} {$followerChange}p (divergence: {$divergence}p). Expect {$follower} to follow.",
            'data_points' => $rows->count(),
            'enabled' => true,
        ];
    }
}
