<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\Api\NearbyStationsRequest;
use App\Http\Resources\Api\StationResource;
use App\Services\PostcodeService;
use App\Services\StationSearch\SearchCriteria;
use App\Services\StationSearch\StationSearchService;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\ValidationException;

class StationController extends Controller
{
    public function __construct(
        private readonly PostcodeService $postcodeService,
        private readonly StationSearchService $searchService,
    ) {}

    public function index(NearbyStationsRequest $request): JsonResponse
    {
        [$lat, $lng] = $this->resolveCoordinates($request);

        $criteria = new SearchCriteria(
            lat: $lat,
            lng: $lng,
            fuelType: $request->fuelType(),
            radiusKm: $request->radius(),
            sort: $request->sort(),
        );

        $result = $this->searchService->search(
            $criteria,
            $request->user(),
            hash('sha256', $request->ip() ?? ''),
        );

        return response()->json([
            'data' => StationResource::collection($result->stations),
            'meta' => [
                'count' => $result->stations->count(),
                'fuel_type' => $criteria->fuelType->value,
                'radius_km' => $criteria->radiusKm,
                'lat' => $criteria->lat,
                'lng' => $criteria->lng,
                'lowest_pence' => $result->pricesSummary['lowest'],
                'highest_pence' => $result->pricesSummary['highest'],
                'cheapest_price_pence' => $result->pricesSummary['lowest'],
                'avg_pence' => $result->pricesSummary['avg'],
                'reliability_counts' => $result->reliabilityCounts,
            ],
            'prediction' => $result->prediction,
        ]);
    }

    /** @return array{0: float, 1: float} */
    private function resolveCoordinates(NearbyStationsRequest $request): array
    {
        if ($request->filled('postcode')) {
            $location = $this->postcodeService->resolve($request->string('postcode')->toString());

            if ($location === null) {
                throw ValidationException::withMessages(['postcode' => 'Postcode not found.']);
            }

            return [$location->lat, $location->lng];
        }

        return [(float) $request->input('lat'), (float) $request->input('lng')];
    }
}
