/// Repository Implementation: Home Repository
///
/// Concrete implementation of the HomeRepository interface.
/// Coordinates between local and remote data sources to provide home data.
///
/// Implements offline-first strategy:
/// 1. Try to return cached data immediately
/// 2. Fetch fresh data from server in background
/// 3. Update cache with fresh data
library;

import 'package:worker/core/errors/exceptions.dart';
import 'package:worker/core/errors/failures.dart';
import 'package:worker/features/home/data/datasources/home_local_datasource.dart';
import 'package:worker/features/home/domain/entities/member_card.dart';
import 'package:worker/features/home/domain/entities/promotion.dart';
import 'package:worker/features/home/domain/repositories/home_repository.dart';

/// Home Repository Implementation
///
/// Responsibilities:
/// - Coordinate between local cache and remote API
/// - Implement offline-first data strategy
/// - Handle errors and convert to domain failures
/// - Manage cache invalidation
class HomeRepositoryImpl implements HomeRepository {
  /// Local data source (Hive)
  final HomeLocalDataSource localDataSource;

  /// Remote data source (API) - TODO: Add when API is ready
  // final HomeRemoteDataSource remoteDataSource;

  /// Constructor
  HomeRepositoryImpl({
    required this.localDataSource,
    // required this.remoteDataSource, // TODO: Add when API ready
  });

  @override
  Future<MemberCard> getMemberCard() async {
    try {
      // TODO: Implement offline-first strategy
      // 1. Check if cache is valid
      final isCacheValid = await localDataSource.isMemberCardCacheValid();

      if (isCacheValid) {
        // 2. Return cached data if valid
        final cachedModel = await localDataSource.getMemberCard();
        return cachedModel.toEntity();
      }

      // 3. If cache invalid, fetch from remote (when API ready)
      // For now, try to return cached data even if expired
      try {
        final cachedModel = await localDataSource.getMemberCard();
        return cachedModel.toEntity();
      } catch (e) {
        // TODO: Fetch from remote API when available
        // final remoteModel = await remoteDataSource.getMemberCard();
        // await localDataSource.cacheMemberCard(remoteModel);
        // return remoteModel.toEntity();

        throw const CacheException('No member card data available');
      }
    } on CacheException catch (e) {
      throw CacheFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to get member card: $e');
    }
  }

  @override
  Future<List<Promotion>> getPromotions() async {
    try {
      // TODO: Implement offline-first strategy
      // 1. Check if cache is valid
      final isCacheValid = await localDataSource.isPromotionsCacheValid();

      if (isCacheValid) {
        // 2. Return cached data if valid
        final cachedModels = await localDataSource.getPromotions();
        return cachedModels.map((model) => model.toEntity()).toList();
      }

      // 3. If cache invalid, fetch from remote (when API ready)
      // For now, try to return cached data even if expired
      try {
        final cachedModels = await localDataSource.getPromotions();
        return cachedModels.map((model) => model.toEntity()).toList();
      } catch (e) {
        // TODO: Fetch from remote API when available
        // final remoteModels = await remoteDataSource.getPromotions();
        // await localDataSource.cachePromotions(remoteModels);
        // return remoteModels.map((m) => m.toEntity()).toList();

        // Return empty list if no data available
        return [];
      }
    } on CacheException catch (e) {
      throw CacheFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to get promotions: $e');
    }
  }

  @override
  Future<MemberCard> refreshMemberCard() async {
    try {
      // TODO: Implement force refresh from API
      // This should always fetch from remote, bypassing cache

      // When API is ready:
      // 1. Fetch from remote
      // final remoteModel = await remoteDataSource.getMemberCard();

      // 2. Update cache
      // await localDataSource.cacheMemberCard(remoteModel);

      // 3. Return entity
      // return remoteModel.toEntity();

      // For now, just return cached data
      final cachedModel = await localDataSource.getMemberCard();
      return cachedModel.toEntity();
    } on ServerException catch (e) {
      throw ServerFailure(message: e.message);
    } on NetworkException catch (e) {
      throw NetworkFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to refresh member card: $e');
    }
  }

  @override
  Future<List<Promotion>> refreshPromotions() async {
    try {
      // TODO: Implement force refresh from API
      // This should always fetch from remote, bypassing cache

      // When API is ready:
      // 1. Fetch from remote
      // final remoteModels = await remoteDataSource.getPromotions();

      // 2. Update cache
      // await localDataSource.cachePromotions(remoteModels);

      // 3. Return entities
      // return remoteModels.map((m) => m.toEntity()).toList();

      // For now, just return cached data
      final cachedModels = await localDataSource.getPromotions();
      return cachedModels.map((model) => model.toEntity()).toList();
    } on ServerException catch (e) {
      throw ServerFailure(message: e.message);
    } on NetworkException catch (e) {
      throw NetworkFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to refresh promotions: $e');
    }
  }
}
