import 'package:flutter/foundation.dart';

import '../../../../core/errors/failures.dart';
import '../../../../core/logging/app_logger.dart';
import '../../domain/entities/task_entity.dart';
import '../../domain/enums/priority.dart';
import '../../domain/repositories/task_repository.dart';

enum TasksStatus { initial, loading, success, error }

enum TaskFilter { all, active, completed }

class DailyTasksViewModel extends ChangeNotifier {
  final TaskRepository repository;
  final AppLogger logger;

  DailyTasksViewModel({
    required this.repository,
    required this.logger,
  });

  TasksStatus _status = TasksStatus.initial;
  List<TaskEntity> _tasks = [];
  Failure? _failure;
  DateTime _selectedDate = DateTime.now();
  TaskFilter _filter = TaskFilter.all;

  TasksStatus get status => _status;
  List<TaskEntity> get tasks => _filteredTasks;
  Failure? get failure => _failure;
  DateTime get selectedDate => _selectedDate;
  TaskFilter get filter => _filter;

  List<TaskEntity> get _filteredTasks {
    List<TaskEntity> filtered;
    switch (_filter) {
      case TaskFilter.all:
        filtered = List.from(_tasks);
        break;
      case TaskFilter.active:
        filtered = _tasks.where((t) => !t.isDone).toList();
        break;
      case TaskFilter.completed:
        filtered = _tasks.where((t) => t.isDone).toList();
        break;
    }
    // Sort by priority: high first, then medium, then low
    filtered.sort((a, b) => _priorityOrder(a.priority).compareTo(_priorityOrder(b.priority)));
    return filtered;
  }

  int _priorityOrder(Priority priority) {
    switch (priority) {
      case Priority.high:
        return 0;
      case Priority.medium:
        return 1;
      case Priority.low:
        return 2;
    }
  }

  int get totalCount => _tasks.length;
  int get completedCount => _tasks.where((t) => t.isDone).length;

  Future<void> loadTasks() async {
    _status = TasksStatus.loading;
    _failure = null;
    notifyListeners();

    final result = await repository.getTasksByDate(_selectedDate);

    result.when(
      success: (data) {
        _tasks = data;
        _status = TasksStatus.success;
        logger.info('Loaded ${data.length} tasks');
      },
      error: (failure) {
        _failure = failure;
        _status = TasksStatus.error;
        logger.error('Failed to load tasks: ${failure.message}');
      },
    );

    notifyListeners();
  }

  void setSelectedDate(DateTime date) {
    _selectedDate = DateTime(date.year, date.month, date.day);
    loadTasks();
  }

  void previousDay() {
    setSelectedDate(_selectedDate.subtract(const Duration(days: 1)));
  }

  void nextDay() {
    setSelectedDate(_selectedDate.add(const Duration(days: 1)));
  }

  void setFilter(TaskFilter filter) {
    _filter = filter;
    notifyListeners();
  }

  Future<void> toggleTask(String id) async {
    final result = await repository.toggleTaskStatus(id);

    result.when(
      success: (updatedTask) {
        final index = _tasks.indexWhere((t) => t.id == id);
        if (index != -1) {
          _tasks[index] = updatedTask;
          notifyListeners();
        }
      },
      error: (failure) {
        _failure = failure;
        notifyListeners();
      },
    );
  }

  Future<void> deleteTask(String id) async {
    final result = await repository.deleteTask(id);

    result.when(
      success: (_) {
        _tasks.removeWhere((t) => t.id == id);
        notifyListeners();
      },
      error: (failure) {
        _failure = failure;
        notifyListeners();
      },
    );
  }

  Future<void> rescheduleToTomorrow(String id) async {
    final tomorrow = _selectedDate.add(const Duration(days: 1));
    final result = await repository.rescheduleTask(id, tomorrow);

    result.when(
      success: (_) {
        _tasks.removeWhere((t) => t.id == id);
        notifyListeners();
        logger.info('Task rescheduled to tomorrow');
      },
      error: (failure) {
        _failure = failure;
        notifyListeners();
      },
    );
  }
}
