import '../../../../core/errors/exceptions.dart';
import '../../../../core/errors/failures.dart';
import '../../../../core/errors/result.dart';
import '../../../../core/logging/app_logger.dart';
import '../../domain/entities/task_entity.dart';
import '../../domain/repositories/task_repository.dart';
import '../datasources/task_remote_datasource.dart';
import '../models/task_model.dart';

class TaskRepositoryImpl implements TaskRepository {
  final TaskRemoteDataSource remoteDataSource;
  final AppLogger logger;

  TaskRepositoryImpl({
    required this.remoteDataSource,
    required this.logger,
  });

  String _formatDate(DateTime date) {
    return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
  }

  @override
  Future<Result<List<TaskEntity>>> getTasksByDate(DateTime date, {String? status}) async {
    try {
      final tasks = await remoteDataSource.getTasksByDate(
        _formatDate(date),
        status: status,
      );
      logger.info('Loaded ${tasks.length} tasks for ${_formatDate(date)}');
      return Success(tasks);
    } on NetworkException catch (e) {
      logger.error('Network error: ${e.message}');
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      logger.error('Server error: ${e.message}');
      return Error(ServerFailure(message: e.message, code: e.statusCode?.toString()));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }

  @override
  Future<Result<TaskEntity>> getTaskById(String id) async {
    try {
      final task = await remoteDataSource.getTaskById(id);
      return Success(task);
    } on NotFoundException catch (e) {
      logger.warning('Task not found: $id');
      return Error(NotFoundFailure(message: e.message));
    } on NetworkException catch (e) {
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Error(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }

  @override
  Future<Result<TaskEntity>> createTask(TaskEntity task) async {
    try {
      final model = TaskModel.fromEntity(task);
      final created = await remoteDataSource.createTask(model);
      logger.info('Created task: ${created.id}');
      return Success(created);
    } on ValidationException catch (e) {
      logger.warning('Validation error: ${e.message}');
      return Error(ValidationFailure(message: e.message));
    } on NetworkException catch (e) {
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Error(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }

  @override
  Future<Result<TaskEntity>> updateTask(TaskEntity task) async {
    try {
      final model = TaskModel.fromEntity(task);
      final updated = await remoteDataSource.updateTask(model);
      logger.info('Updated task: ${updated.id}');
      return Success(updated);
    } on NotFoundException catch (e) {
      return Error(NotFoundFailure(message: e.message));
    } on ValidationException catch (e) {
      return Error(ValidationFailure(message: e.message));
    } on NetworkException catch (e) {
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Error(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }

  @override
  Future<Result<void>> deleteTask(String id) async {
    try {
      await remoteDataSource.deleteTask(id);
      logger.info('Deleted task: $id');
      return const Success(null);
    } on NotFoundException catch (e) {
      return Error(NotFoundFailure(message: e.message));
    } on NetworkException catch (e) {
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Error(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }

  @override
  Future<Result<TaskEntity>> toggleTaskStatus(String id) async {
    try {
      final task = await remoteDataSource.toggleTaskStatus(id);
      logger.info('Toggled task status: $id -> ${task.isDone}');
      return Success(task);
    } on NotFoundException catch (e) {
      return Error(NotFoundFailure(message: e.message));
    } on NetworkException catch (e) {
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Error(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }

  @override
  Future<Result<TaskEntity>> rescheduleTask(String id, DateTime targetDate) async {
    try {
      final task = await remoteDataSource.rescheduleTask(id, _formatDate(targetDate));
      logger.info('Rescheduled task: $id -> ${_formatDate(targetDate)}');
      return Success(task);
    } on NotFoundException catch (e) {
      return Error(NotFoundFailure(message: e.message));
    } on NetworkException catch (e) {
      return Error(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Error(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      logger.error('Unexpected error', e, stackTrace);
      return Error(UnexpectedFailure(message: e.toString()));
    }
  }
}
