/// Location Local Data Source
///
/// Handles Hive caching for cities and wards.
library;

import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/core/database/hive_service.dart';
import 'package:worker/features/account/data/models/city_model.dart';
import 'package:worker/features/account/data/models/ward_model.dart';

/// Location Local Data Source
///
/// Provides offline-first caching for cities and wards using Hive.
class LocationLocalDataSource {
  final HiveService _hiveService;

  LocationLocalDataSource(this._hiveService);

  // ============================================================================
  // CITIES
  // ============================================================================

  /// Get city box
  Box<dynamic> get _cityBox => _hiveService.getBox(HiveBoxNames.cityBox);

  /// Get all cached cities
  List<CityModel> getCities() {
    try {
      final cities = _cityBox.values.whereType<CityModel>().toList();
      return cities;
    } catch (e) {
      return [];
    }
  }

  /// Save cities to cache
  Future<void> saveCities(List<CityModel> cities) async {
    try {
      // Only clear if there are existing cities
      if (_cityBox.isNotEmpty) {
        await _cityBox.clear();
      }

      for (final city in cities) {
        await _cityBox.put(city.code, city);
      }
    } catch (e) {
      rethrow;
    }
  }

  /// Get city by code
  CityModel? getCityByCode(String code) {
    try {
      return _cityBox.get(code) as CityModel?;
    } catch (e) {
      return null;
    }
  }

  /// Check if cities are cached
  bool hasCities() {
    return _cityBox.isNotEmpty;
  }

  // ============================================================================
  // WARDS
  // ============================================================================

  /// Get ward box
  Box<dynamic> get _wardBox => _hiveService.getBox(HiveBoxNames.wardBox);

  /// Get cached wards for a city
  ///
  /// Wards are stored with key: "cityCode_wardCode"
  List<WardModel> getWards(String cityCode) {
    try {
      final wards = _wardBox.values
          .whereType<WardModel>()
          .where((ward) {
            // Check if this ward belongs to the city
            final key = '${cityCode}_${ward.code}';
            return _wardBox.containsKey(key);
          })
          .toList();

      return wards;
    } catch (e) {
      return [];
    }
  }

  /// Save wards for a specific city to cache
  Future<void> saveWards(String cityCode, List<WardModel> wards) async {
    try {
      // Remove old wards for this city (only if they exist)
      final keysToDelete = _wardBox.keys
          .where((key) => key.toString().startsWith('${cityCode}_'))
          .toList();

      if (keysToDelete.isNotEmpty) {
        for (final key in keysToDelete) {
          await _wardBox.delete(key);
        }
      }

      // Save new wards
      for (final ward in wards) {
        final key = '${cityCode}_${ward.code}';
        await _wardBox.put(key, ward);
      }
    } catch (e) {
      rethrow;
    }
  }

  /// Check if wards are cached for a city
  bool hasWards(String cityCode) {
    return _wardBox.keys.any((key) => key.toString().startsWith('${cityCode}_'));
  }

  /// Clear all cached data
  Future<void> clearAll() async {
    try {
      // Only clear if boxes are not empty
      if (_cityBox.isNotEmpty) {
        await _cityBox.clear();
      }
      if (_wardBox.isNotEmpty) {
        await _wardBox.clear();
      }
    } catch (e) {
      rethrow;
    }
  }
}
