false, 'error' => 'VIN must be exactly 17 characters long.', 'data' => null ]; } // Make API request to NHTSA $response = Http::timeout(10)->get(self::NHTSA_API_BASE . "/vehicles/DecodeVin/{$vin}", [ 'format' => 'json' ]); if (!$response->successful()) { return [ 'success' => false, 'error' => 'Failed to connect to VIN decoder service.', 'data' => null ]; } $data = $response->json(); if (empty($data['Results'])) { return [ 'success' => false, 'error' => 'No vehicle data found for this VIN.', 'data' => null ]; } // Parse the results $vehicleData = $this->parseVinResults($data['Results']); return [ 'success' => true, 'error' => null, 'data' => $vehicleData ]; } catch (\Exception $e) { Log::error('VIN Decoder Error: ' . $e->getMessage()); return [ 'success' => false, 'error' => 'An error occurred while decoding the VIN. Please try again.', 'data' => null ]; } } /** * Parse NHTSA API results into usable vehicle data */ private function parseVinResults(array $results): array { $vehicleData = [ 'make' => null, 'model' => null, 'year' => null, 'engine_type' => null, 'transmission' => null, 'body_class' => null, 'fuel_type' => null, 'drive_type' => null, 'error_codes' => [] ]; // Initialize engine-related variables $cylinders = null; $displacement = null; $engineConfig = null; foreach ($results as $result) { $variable = $result['Variable'] ?? ''; $value = $result['Value'] ?? ''; $errorCode = $result['ErrorCode'] ?? ''; // Skip empty values if (empty($value) || $value === 'Not Applicable' || $value === 'N/A') { continue; } // Collect error codes if (!empty($errorCode) && $errorCode !== '0') { $vehicleData['error_codes'][] = $result['ErrorText'] ?? 'Unknown error'; continue; } // Map NHTSA fields to our vehicle data switch ($variable) { case 'Make': $vehicleData['make'] = $value; break; case 'Model': $vehicleData['model'] = $value; break; case 'Model Year': $vehicleData['year'] = (int) $value; break; case 'Engine Number of Cylinders': $cylinders = $value; break; case 'Displacement (L)': $displacement = $value; break; case 'Engine Configuration': $engineConfig = $value; break; case 'Fuel Type - Primary': $vehicleData['fuel_type'] = $value; break; case 'Transmission Style': $vehicleData['transmission'] = $value; break; case 'Body Class': $vehicleData['body_class'] = $value; break; case 'Drive Type': $vehicleData['drive_type'] = $value; break; } } // Build engine description from available data $engineParts = array_filter([ $displacement ? $displacement . 'L' : null, $cylinders ? $cylinders . '-cyl' : null, $engineConfig ?? null, $vehicleData['fuel_type'] ?? null ]); if (!empty($engineParts)) { $vehicleData['engine_type'] = implode(' ', $engineParts); } return $vehicleData; } /** * Get vehicle makes for dropdown */ public function getVehicleMakes(): array { try { $response = Http::timeout(10)->get(self::NHTSA_API_BASE . '/vehicles/GetMakesForVehicleType/car', [ 'format' => 'json' ]); if ($response->successful()) { $data = $response->json(); $makes = collect($data['Results'] ?? []) ->pluck('MakeName') ->filter() ->sort() ->values() ->all(); return $makes; } } catch (\Exception $e) { Log::error('Error fetching vehicle makes: ' . $e->getMessage()); } return []; } /** * Get vehicle models for a specific make and year */ public function getModelsForMakeAndYear(string $make, int $year): array { try { $response = Http::timeout(10)->get(self::NHTSA_API_BASE . "/vehicles/GetModelsForMakeYear/make/{$make}/modelyear/{$year}", [ 'format' => 'json' ]); if ($response->successful()) { $data = $response->json(); $models = collect($data['Results'] ?? []) ->pluck('Model_Name') ->filter() ->unique() ->sort() ->values() ->all(); return $models; } } catch (\Exception $e) { Log::error('Error fetching vehicle models: ' . $e->getMessage()); } return []; } }