import 'package:drift/drift.dart';

import '../../../../core/database/app_database.dart';
import '../../domain/enums/priority.dart';
import '../models/task_model.dart';

abstract class TaskLocalDataSource {
  Future<List<TaskModel>> getTasksByDate(String date, {String? status});
  Future<TaskModel> getTaskById(String id);
  Future<TaskModel> createTask(TaskModel task);
  Future<TaskModel> updateTask(TaskModel task);
  Future<void> deleteTask(String id);
  Future<TaskModel> toggleTaskStatus(String id);
  Future<TaskModel> rescheduleTask(String id, String targetDate);
  Future<List<TaskModel>> getAllTasks();
}

class TaskLocalDataSourceImpl implements TaskLocalDataSource {
  final AppDatabase database;

  TaskLocalDataSourceImpl({required this.database});

  TaskModel _taskFromDb(Task dbTask) {
    return TaskModel(
      id: dbTask.id,
      title: dbTask.title,
      description: dbTask.description,
      date: dbTask.date,
      time: dbTask.time,
      priority: Priority.fromString(dbTask.priority),
      isDone: dbTask.isDone,
      createdAt: dbTask.createdAt,
      updatedAt: dbTask.updatedAt,
    );
  }

  TasksCompanion _taskToDb(TaskModel task) {
    return TasksCompanion(
      id: Value(task.id),
      title: Value(task.title),
      description: Value(task.description),
      date: Value(task.date),
      time: Value(task.time),
      priority: Value(task.priority.name),
      isDone: Value(task.isDone),
      createdAt: Value(task.createdAt ?? DateTime.now()),
      updatedAt: Value(DateTime.now()),
    );
  }

  @override
  Future<List<TaskModel>> getTasksByDate(String date, {String? status}) async {
    final dateTime = DateTime.parse(date);
    final tasks = await database.getTasksByDate(dateTime);

    var result = tasks.map(_taskFromDb).toList();

    if (status != null && status != 'all') {
      if (status == 'completed') {
        result = result.where((t) => t.isDone).toList();
      } else if (status == 'active') {
        result = result.where((t) => !t.isDone).toList();
      }
    }

    return result;
  }

  @override
  Future<TaskModel> getTaskById(String id) async {
    final task = await database.getTaskById(id);
    if (task == null) {
      throw Exception('Task not found');
    }
    return _taskFromDb(task);
  }

  @override
  Future<TaskModel> createTask(TaskModel task) async {
    final companion = _taskToDb(task);
    await database.insertTask(companion);
    return task;
  }

  @override
  Future<TaskModel> updateTask(TaskModel task) async {
    final updatedTask = TaskModel(
      id: task.id,
      title: task.title,
      description: task.description,
      date: task.date,
      time: task.time,
      priority: task.priority,
      isDone: task.isDone,
      createdAt: task.createdAt,
      updatedAt: DateTime.now(),
    );
    final companion = _taskToDb(updatedTask);
    await database.updateTask(companion);
    return updatedTask;
  }

  @override
  Future<void> deleteTask(String id) async {
    await database.deleteTaskById(id);
  }

  @override
  Future<TaskModel> toggleTaskStatus(String id) async {
    final task = await getTaskById(id);
    final updated = TaskModel(
      id: task.id,
      title: task.title,
      description: task.description,
      date: task.date,
      time: task.time,
      priority: task.priority,
      isDone: !task.isDone,
      createdAt: task.createdAt,
      updatedAt: DateTime.now(),
    );
    await updateTask(updated);
    return updated;
  }

  @override
  Future<TaskModel> rescheduleTask(String id, String targetDate) async {
    final task = await getTaskById(id);
    final updated = TaskModel(
      id: task.id,
      title: task.title,
      description: task.description,
      date: DateTime.parse(targetDate),
      time: task.time,
      priority: task.priority,
      isDone: task.isDone,
      createdAt: task.createdAt,
      updatedAt: DateTime.now(),
    );
    await updateTask(updated);
    return updated;
  }

  @override
  Future<List<TaskModel>> getAllTasks() async {
    final tasks = await database.getAllTasks();
    return tasks.map(_taskFromDb).toList();
  }
}
