using TodoList.Application.Interfaces;
using TodoList.Application.Models;
using TodoList.Core.Entities;
using TodoList.Core.Interfaces;

namespace TodoList.Application.Services;

public class TaskService : ITaskService
{
    private readonly ITaskRepository _taskRepository;

    public TaskService(ITaskRepository taskRepository)
    {
        _taskRepository = taskRepository;
    }

    public async Task<List<TaskDto>> GetAllTasksAsync()
    {
        var tasks = await _taskRepository.GetAllAsync();
        return tasks.Select(MapToDto).ToList();
    }

    public async Task<TaskDto?> GetTaskByIdAsync(int id)
    {
        var task = await _taskRepository.GetByIdAsync(id);
        return task != null ? MapToDto(task) : null;
    }

    public async Task<List<TaskDto>> GetActiveTasksAsync()
    {
        var allTasks = await _taskRepository.GetAllAsync();
        return allTasks.Where(t => !t.IsCompleted).Select(MapToDto).ToList();
    }

    public async Task<List<TaskDto>> GetCompletedTasksAsync()
    {
        var allTasks = await _taskRepository.GetAllAsync();
        return allTasks.Where(t => t.IsCompleted).Select(MapToDto).ToList();
    }

    public async Task<TaskDto> CreateTaskAsync(CreateTaskDto dto)
    {
        var task = new TaskEntity
        {
            Title = dto.Title,
            Priority = dto.Priority,
            IsCompleted = false,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow,
            ParentTaskId = dto.ParentTaskId
        };

        var createdTask = await _taskRepository.AddAsync(task);
        return MapToDto(createdTask);
    }

    public async Task<TaskDto> UpdateTaskAsync(UpdateTaskDto dto)
    {
        var task = await _taskRepository.GetByIdAsync(dto.Id);
        if (task == null)
        {
            throw new KeyNotFoundException($"Task with ID {dto.Id} not found");
        }

        if (!string.IsNullOrEmpty(dto.Title))
        {
            task.Title = dto.Title;
        }

        if (dto.Priority.HasValue)
        {
            task.Priority = dto.Priority.Value;
        }

        task.UpdatedAt = DateTime.UtcNow;

        var updatedTask = await _taskRepository.UpdateAsync(task);
        return MapToDto(updatedTask);
    }

    public async Task<TaskDto> ToggleCompleteAsync(int id)
    {
        var task = await _taskRepository.GetByIdAsync(id);
        if (task == null)
        {
            throw new KeyNotFoundException($"Task with ID {id} not found");
        }

        task.IsCompleted = !task.IsCompleted;
        task.UpdatedAt = DateTime.UtcNow;

        var updatedTask = await _taskRepository.UpdateAsync(task);
        return MapToDto(updatedTask);
    }

    public async Task DeleteTaskAsync(int id)
    {
        var task = await _taskRepository.GetByIdAsync(id);
        if (task == null)
        {
            throw new KeyNotFoundException($"Task with ID {id} not found");
        }

        await _taskRepository.DeleteAsync(id);
    }

    public async Task<List<TaskDto>> GetSubTasksAsync(int parentTaskId)
    {
        var allTasks = await _taskRepository.GetAllAsync();
        return allTasks.Where(t => t.ParentTaskId == parentTaskId).Select(MapToDto).ToList();
    }

    private TaskDto MapToDto(TaskEntity task)
    {
        return new TaskDto
        {
            Id = task.Id,
            Title = task.Title,
            Priority = task.Priority,
            IsCompleted = task.IsCompleted,
            CreatedAt = task.CreatedAt,
            UpdatedAt = task.UpdatedAt,
            ParentTaskId = task.ParentTaskId,
            SubTasks = task.SubTasks.Select(MapToDto).ToList()
        };
    }
}
