import 'dart:convert';

import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:http/http.dart' as http;
import 'package:injectable/injectable.dart';

@singleton
class GooglePlacesService {
  Future<List<MapPlace>> fetchSuggestions(String query) async {
    final String apiKey = dotenv.env['GOOGLE_MAP']!;

    const String baseUrl =
        'https://maps.googleapis.com/maps/api/place/autocomplete/json';
    final Uri uri =
        Uri.parse('$baseUrl?input=$query&key=$apiKey&types=geocode');

    final response = await http.get(uri);
    if (response.statusCode == 200) {
      final data = json.decode(response.body);
      final List<dynamic> predictions = data['predictions'];

      return predictions.map((prediction) {
        return MapPlace.fromJson(prediction);
      }).toList();
    } else {
      throw Exception('Failed to fetch place suggestions');
    }
  }

  Future<Map<String, dynamic>> getPlaceDetails(String placeId) async {
    final String apiKey = dotenv.env['GOOGLE_MAP']!;
    final String url =
        'https://maps.googleapis.com/maps/api/place/details/json?place_id=$placeId&key=$apiKey';

    final response = await http.get(Uri.parse(url));

    if (response.statusCode == 200) {
      final data = json.decode(response.body);
      final result = data['result'];
      final location = result['geometry']['location'];

      Map<String, dynamic> addressDetails = {
        'lat': location['lat'], // Latitude
        'lng': location['lng'], // Longitude
        'formatted_address': result['formatted_address'], // Full Address
      };

      for (var component in result['address_components']) {
        List types = component['types'];
        if (types.contains('street_number')) {
          addressDetails['street_number'] = component['long_name'];
        }
        if (types.contains('route')) {
          addressDetails['street'] = component['long_name'];
        }
        if (types.contains('locality')) {
          addressDetails['city'] = component['long_name'];
        }
        if (types.contains('administrative_area_level_1')) {
          addressDetails['state'] = component['long_name'];
        }
        if (types.contains('country')) {
          addressDetails['country'] = component['long_name'];
        }
        if (types.contains('postal_code')) {
          addressDetails['postal_code'] = component['long_name'];
        }
      }

      return addressDetails;
    } else {
      throw Exception('Failed to fetch place details');
    }
  }
}

class MapPlace {
  final String description;
  final String placeId;

  MapPlace({required this.description, required this.placeId});

  toJson() {
    return {
      'description': description,
      'place_id': placeId,
    };
  }

  factory MapPlace.fromJson(Map<String, dynamic> json) {
    return MapPlace(
      description: json['description'],
      placeId: json['place_id'],
    );
  }
}
