import 'dart:developer';

import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';

import '../../../domain/outlet/outlet.dart';
import '../datasources/local_data_provider.dart';
import '../datasources/remote_data_provider.dart';

@Injectable(as: IOutletRepository)
class OutletRepository implements IOutletRepository {
  final OutletRemoteDataProvider _remoteDataProvider;
  final OutletLocalDatasource _localDataProvider;

  final _logName = 'OutletRepository';
  OutletRepository(this._remoteDataProvider, this._localDataProvider);

  @override
  Future<Either<OutletFailure, List<Outlet>>> getOutlets({
    int page = 1,
    int limit = 10,
  }) async {
    try {
      final result = await _remoteDataProvider.fetchOutlets(
        page: page,
        limit: limit,
      );

      if (result.hasError) {
        return left(result.error!);
      }

      final outlets = result.data!.map((dto) => dto.toDomain()).toList();

      return right(outlets);
    } catch (e, s) {
      log('getOutlets', name: _logName, error: e, stackTrace: s);
      return left(const OutletFailure.unexpectedError());
    }
  }

  @override
  Future<Either<OutletFailure, Outlet>> getOutletById(String id) async {
    try {
      final localOutlet = await _localDataProvider.currentOutlet();
      if (localOutlet.id == id) {
        return right(localOutlet);
      }

      final result = await _remoteDataProvider.fetchOutletById(id);
      if (result.hasError) {
        return left(result.error!);
      }

      await _localDataProvider.saveCurrentOutlet(result.data!);
      final outlet = result.data!.toDomain();
      return right(outlet);
    } catch (e, s) {
      log('getOutletById', name: _logName, error: e, stackTrace: s);
      return left(const OutletFailure.unexpectedError());
    }
  }

  @override
  Future<Outlet> currentOutlet() async {
    final result = await _localDataProvider.currentOutlet();
    return result;
  }
}
