import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:sigap/src/cores/services/supabase_service.dart';
import 'package:sigap/src/features/map/data/models/models/districts_model.dart';

class DistrictsRepository extends GetxController {
  static DistrictsRepository get instance => Get.find();

  final _supabase = SupabaseService.instance.client;
  final _log = Get.find<Logger>();

  // Cache districts to reduce database calls
  final RxMap<String, List<DistrictModel>> _districtsByCity =
      <String, List<DistrictModel>>{}.obs;

  // Get all districts for a city
  Future<List<DistrictModel>> getDistrictsByCityId(String cityId) async {
    try {
      // If cache exists, return it
      if (_districtsByCity.containsKey(cityId)) {
        return _districtsByCity[cityId]!;
      }

      final response = await _supabase
          .from('districts')
          .select('*, cities(*), units(*)')
          .eq('city_id', cityId)
          .order('name');

      final data = response as List;
      final districts =
          data.map((json) => DistrictModel.fromJson(json)).toList();

      // Update cache
      _districtsByCity[cityId] = districts;
      return districts;
    } catch (e) {
      _log.e('Error fetching districts for city $cityId: $e');
      throw Exception('Failed to load districts: $e');
    }
  }

  // Get district by ID
  Future<DistrictModel> getDistrictById(String districtId) async {
    try {
      // Check cache first
      for (final cityDistricts in _districtsByCity.values) {
        final cachedDistrict = cityDistricts.firstWhereOrNull(
          (d) => d.id == districtId,
        );
        if (cachedDistrict != null) {
          return cachedDistrict;
        }
      }

      final response =
          await _supabase
              .from('districts')
              .select(
                '*, cities(*), units(*), crimes(*), demographics(*), geographics(*), locations(*)',
              )
              .eq('id', districtId)
              .single();

      return DistrictModel.fromJson(response);
    } catch (e) {
      _log.e('Error fetching district $districtId: $e');
      throw Exception('Failed to load district details: $e');
    }
  }

  // Get districts with crime data
  Future<List<DistrictModel>> getDistrictsWithCrimeData(
    int year,
    int? month,
  ) async {
    try {
      String query = 'districts.*, cities(*), crimes!inner(*)';

      var request = _supabase
          .from('districts')
          .select(query)
          .eq('crimes.year', year);

      if (month != null) {
        request = request.eq('crimes.month', month);
      }

      final response = await request;
      final data = response as List;

      return data.map((json) => DistrictModel.fromJson(json)).toList();
    } catch (e) {
      _log.e('Error fetching districts with crime data: $e');
      throw Exception('Failed to load districts with crime data: $e');
    }
  }

  // Clear cache
  void clearCache() {
    _districtsByCity.clear();
  }
}
