using ColaFlow.Domain.Common;
using ColaFlow.Domain.Exceptions;
using ColaFlow.Domain.ValueObjects;

namespace ColaFlow.Domain.Aggregates.ProjectAggregate;

/// <summary>
/// Epic Entity (part of Project aggregate)
/// </summary>
public class Epic : Entity
{
    public new EpicId Id { get; private set; }
    public string Name { get; private set; }
    public string Description { get; private set; }
    public ProjectId ProjectId { get; private set; }
    public WorkItemStatus Status { get; private set; }
    public TaskPriority Priority { get; private set; }

    private readonly List<Story> _stories = new();
    public IReadOnlyCollection<Story> Stories => _stories.AsReadOnly();

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

    // EF Core constructor
    private Epic()
    {
        Id = null!;
        Name = null!;
        Description = null!;
        ProjectId = null!;
        Status = null!;
        Priority = null!;
        CreatedBy = null!;
    }

    public static Epic Create(string name, string description, ProjectId projectId, UserId createdBy)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new DomainException("Epic name cannot be empty");

        if (name.Length > 200)
            throw new DomainException("Epic name cannot exceed 200 characters");

        return new Epic
        {
            Id = EpicId.Create(),
            Name = name,
            Description = description ?? string.Empty,
            ProjectId = projectId,
            Status = WorkItemStatus.ToDo,
            Priority = TaskPriority.Medium,
            CreatedAt = DateTime.UtcNow,
            CreatedBy = createdBy
        };
    }

    public Story CreateStory(string title, string description, TaskPriority priority, UserId createdBy)
    {
        var story = Story.Create(title, description, this.Id, priority, createdBy);
        _stories.Add(story);
        return story;
    }

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

        if (name.Length > 200)
            throw new DomainException("Epic name cannot exceed 200 characters");

        Name = name;
        Description = description ?? string.Empty;
        UpdatedAt = DateTime.UtcNow;
    }

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

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