config('app.verify_ssl'), ])->get($url); if (!$response->successful()) { return []; } $data = $response->json('data'); if (!is_array($data)) { return []; } return $data; } public function fetchFlightData(string $airlineCode, string $flightNumber, ?CarbonImmutable $date = null): ?FlightStatData { $specificDate = $date !== null; $date ??= now()->utc()->toImmutable(); $data = $this->fetchForDate($airlineCode, $flightNumber, $date); if ($data || $specificDate) return $data; $otherDays = $this->fetchOtherDays($airlineCode, $flightNumber); $pastDays = collect($otherDays) ->filter(fn($day) => !empty($day['flights'])) ->sortByDesc(fn($day) => $day['year'] . $day['date1']); foreach ($pastDays as $day) { $pastDate = CarbonImmutable::createFromFormat('Y-d-M', $day['year'] . '-' . $day['date1']); $result = $this->fetchForDate($airlineCode, $flightNumber, $pastDate); if ($result) return $result; } return null; } protected function fetchForDate(string $airlineCode, string $flightNumber, CarbonImmutable $date): ?FlightStatData { $url = sprintf( 'https://www.flightstats.com/v2/api-next/flight-tracker/%s/%s/%d/%d/%d', $airlineCode, $flightNumber, $date->year, $date->month, $date->day, ); $response = Http::withOptions([ 'verify' => config('app.verify_ssl'), ])->get($url); if (!$response->successful()) { Log::warning("FlightStats request failed for {$airlineCode}{$flightNumber}: HTTP {$response->status()}"); return null; } $flightData = $response->json('data'); if (empty($flightData)) return null; return FlightStatData::fromApiResponse($flightData); } public function guessAircraftFromIata(string $iataCode): ?Aircraft { $equipment = IataEquipmentCode::where('iata_code', $iataCode)->first(); if (!$equipment) { Log::info("Unknown IATA equipment code: {$iataCode}"); return null; } $aircraft = Aircraft::where('designator', $equipment->icao_code) ->orderByDesc('preferred') ->orderBy('id') ->first(); if (!$aircraft) { Log::info("No aircraft found for ICAO: {$equipment->icao_code} (IATA: {$iataCode})"); } return $aircraft; } }