/// Location Repository Implementation
///
/// Implements location repository with offline-first strategy.
library;

import 'package:worker/features/account/data/datasources/location_local_datasource.dart';
import 'package:worker/features/account/data/datasources/location_remote_datasource.dart';
import 'package:worker/features/account/domain/entities/city.dart';
import 'package:worker/features/account/domain/entities/ward.dart';
import 'package:worker/features/account/domain/repositories/location_repository.dart';

/// Location Repository Implementation
///
/// Offline-first implementation:
/// - Cities: Cache in Hive, fetch from API if cache is empty or force refresh
/// - Wards: Cache per city, fetch from API if not cached or force refresh
class LocationRepositoryImpl implements LocationRepository {
  final LocationRemoteDataSource _remoteDataSource;
  final LocationLocalDataSource _localDataSource;

  LocationRepositoryImpl({
    required LocationRemoteDataSource remoteDataSource,
    required LocationLocalDataSource localDataSource,
  })  : _remoteDataSource = remoteDataSource,
        _localDataSource = localDataSource;

  @override
  Future<List<City>> getCities({bool forceRefresh = false}) async {
    try {
      // Check cache first (offline-first)
      if (!forceRefresh && _localDataSource.hasCities()) {
        final cachedCities = _localDataSource.getCities();
        if (cachedCities.isNotEmpty) {
          return cachedCities.map((model) => model.toEntity()).toList();
        }
      }

      // Fetch from API
      final cityModels = await _remoteDataSource.getCities();

      // Save to cache
      await _localDataSource.saveCities(cityModels);

      return cityModels.map((model) => model.toEntity()).toList();
    } catch (e) {
      // Fallback to cache on error
      if (!forceRefresh) {
        final cachedCities = _localDataSource.getCities();
        if (cachedCities.isNotEmpty) {
          return cachedCities.map((model) => model.toEntity()).toList();
        }
      }

      rethrow;
    }
  }

  @override
  Future<List<Ward>> getWards(
    String cityCode, {
    bool forceRefresh = false,
  }) async {
    try {
      // Check cache first (offline-first)
      if (!forceRefresh && _localDataSource.hasWards(cityCode)) {
        final cachedWards = _localDataSource.getWards(cityCode);
        if (cachedWards.isNotEmpty) {
          return cachedWards.map((model) => model.toEntity()).toList();
        }
      }

      // Fetch from API
      final wardModels = await _remoteDataSource.getWards(cityCode);

      // Save to cache
      await _localDataSource.saveWards(cityCode, wardModels);

      return wardModels.map((model) => model.toEntity()).toList();
    } catch (e) {
      // Fallback to cache on error
      if (!forceRefresh) {
        final cachedWards = _localDataSource.getWards(cityCode);
        if (cachedWards.isNotEmpty) {
          return cachedWards.map((model) => model.toEntity()).toList();
        }
      }

      rethrow;
    }
  }

  @override
  Future<void> clearCache() async {
    await _localDataSource.clearAll();
  }
}
