using ColaFlow.Shared.Kernel.Common;
using ColaFlow.Modules.ProjectManagement.Domain.Exceptions;
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;

using ColaFlow.Modules.ProjectManagement.Domain.Events;
namespace ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;

/// <summary>
/// Task Entity (part of Project aggregate)
/// Named "WorkTask" to avoid conflict with System.Threading.Tasks.Task
/// </summary>
public class WorkTask : Entity
{
    public new TaskId Id { get; private set; }
    public TenantId TenantId { get; private set; }
    public string Title { get; private set; }
    public string Description { get; private set; }
    public StoryId StoryId { get; private set; }
    public WorkItemStatus Status { get; private set; }
    public TaskPriority Priority { get; private set; }
    public decimal? EstimatedHours { get; private set; }
    public decimal? ActualHours { get; private set; }
    public UserId? AssigneeId { get; private set; }

    public DateTime CreatedAt { get; private set; }
    public UserId CreatedBy { get; private set; }
    public DateTime? UpdatedAt { get; private set; }

    // EF Core constructor
    private WorkTask()
    {
        Id = null!;
        TenantId = null!;
        Title = null!;
        Description = null!;
        StoryId = null!;
        Status = null!;
        Priority = null!;
        CreatedBy = null!;
    }

    public static WorkTask Create(TenantId tenantId, string title, string description, StoryId storyId, TaskPriority priority, UserId createdBy)
    {
        if (string.IsNullOrWhiteSpace(title))
            throw new DomainException("Task title cannot be empty");

        if (title.Length > 200)
            throw new DomainException("Task title cannot exceed 200 characters");

        return new WorkTask
        {
            Id = TaskId.Create(),
            TenantId = tenantId,
            Title = title,
            Description = description ?? string.Empty,
            StoryId = storyId,
            Status = WorkItemStatus.ToDo,
            Priority = priority,
            CreatedAt = DateTime.UtcNow,
            CreatedBy = createdBy
        };
    }

    public void UpdateDetails(string title, string description)
    {
        if (string.IsNullOrWhiteSpace(title))
            throw new DomainException("Task title cannot be empty");

        if (title.Length > 200)
            throw new DomainException("Task title cannot exceed 200 characters");

        Title = title;
        Description = description ?? string.Empty;
        UpdatedAt = DateTime.UtcNow;
    }

    public void UpdateStatus(WorkItemStatus newStatus)
    {
        Status = newStatus;
        UpdatedAt = DateTime.UtcNow;
    }

    public void AssignTo(UserId assigneeId)
    {
        AssigneeId = assigneeId;
        UpdatedAt = DateTime.UtcNow;
    }

    public void UpdatePriority(TaskPriority newPriority)
    {
        Priority = newPriority;
        UpdatedAt = DateTime.UtcNow;
    }

    public void UpdateEstimate(decimal hours)
    {
        if (hours < 0)
            throw new DomainException("Estimated hours cannot be negative");

        EstimatedHours = hours;
        UpdatedAt = DateTime.UtcNow;
    }

    public void LogActualHours(decimal hours)
    {
        if (hours < 0)
            throw new DomainException("Actual hours cannot be negative");

        ActualHours = hours;
        UpdatedAt = DateTime.UtcNow;
    }
}
