// EN: Barista queue item entity for cafe drink preparation queue.
// VI: Entity BaristaQueueItem cho hang doi pha che cafe.

using FnbEngine.Domain.Events;
using FnbEngine.Domain.SeedWork;

namespace FnbEngine.Domain.AggregatesModel.BaristaAggregate;

/// <summary>
/// EN: Barista queue item - represents a drink in the barista preparation queue.
/// VI: Barista queue item - dai dien cho do uong trong hang doi pha che.
/// </summary>
public class BaristaQueueItem : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private de dong goi
    private Guid _shopId;
    private Guid _orderId;
    private Guid _orderItemId;
    private string _drinkName = null!;
    private string? _customizations; // JSON string
    private int _priority;
    private int _statusId;
    private string? _assignedTo; // barista name
    private int _estimatedMinutes;
    private DateTime _createdAt;
    private DateTime? _startedAt;
    private DateTime? _completedAt;

    /// <summary>
    /// EN: Shop ID where the drink was ordered.
    /// VI: ID shop noi do uong duoc dat.
    /// </summary>
    public Guid ShopId => _shopId;

    /// <summary>
    /// EN: Order ID from order-service.
    /// VI: ID don hang tu order-service.
    /// </summary>
    public Guid OrderId => _orderId;

    /// <summary>
    /// EN: Order item ID from order-service.
    /// VI: ID item don hang tu order-service.
    /// </summary>
    public Guid OrderItemId => _orderItemId;

    /// <summary>
    /// EN: Display name of the drink.
    /// VI: Ten hien thi cua do uong.
    /// </summary>
    public string DrinkName => _drinkName;

    /// <summary>
    /// EN: Customizations as JSON (e.g. ice level, sugar, toppings).
    /// VI: Tuy chinh dang JSON (vd: muc da, duong, topping).
    /// </summary>
    public string? Customizations => _customizations;

    /// <summary>
    /// EN: Priority (higher = more urgent). 0 is normal.
    /// VI: Do uu tien (cao = gap hon). 0 la binh thuong.
    /// </summary>
    public int Priority => _priority;

    /// <summary>
    /// EN: Status ID: 1=Queued, 2=Preparing, 3=Ready, 4=Delivered, 5=Cancelled.
    /// VI: ID trang thai: 1=Cho, 2=Dang pha, 3=San sang, 4=Da giao, 5=Da huy.
    /// </summary>
    public int StatusId => _statusId;

    /// <summary>
    /// EN: Status display name.
    /// VI: Ten hien thi trang thai.
    /// </summary>
    public string StatusName => _statusId switch
    {
        1 => "Queued",
        2 => "Preparing",
        3 => "Ready",
        4 => "Delivered",
        5 => "Cancelled",
        _ => "Unknown"
    };

    /// <summary>
    /// EN: Barista assigned to prepare this drink.
    /// VI: Barista duoc giao pha che do uong nay.
    /// </summary>
    public string? AssignedTo => _assignedTo;

    /// <summary>
    /// EN: Estimated preparation time in minutes.
    /// VI: Thoi gian pha che du kien tinh bang phut.
    /// </summary>
    public int EstimatedMinutes => _estimatedMinutes;

    /// <summary>
    /// EN: When the item was added to the queue.
    /// VI: Khi item duoc them vao hang doi.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: When preparation started.
    /// VI: Khi bat dau pha che.
    /// </summary>
    public DateTime? StartedAt => _startedAt;

    /// <summary>
    /// EN: When the drink was completed (Ready or Delivered).
    /// VI: Khi do uong hoan thanh (San sang hoac Da giao).
    /// </summary>
    public DateTime? CompletedAt => _completedAt;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected BaristaQueueItem()
    {
    }

    /// <summary>
    /// EN: Create a new barista queue item.
    /// VI: Tao barista queue item moi.
    /// </summary>
    public BaristaQueueItem(
        Guid shopId,
        Guid orderId,
        Guid orderItemId,
        string drinkName,
        string? customizations = null,
        int priority = 0,
        int estimatedMinutes = 5)
    {
        if (shopId == Guid.Empty)
            throw new ArgumentException("Shop ID cannot be empty / Shop ID khong duoc rong", nameof(shopId));
        if (orderId == Guid.Empty)
            throw new ArgumentException("Order ID cannot be empty / Order ID khong duoc rong", nameof(orderId));
        if (orderItemId == Guid.Empty)
            throw new ArgumentException("Order item ID cannot be empty / Order item ID khong duoc rong", nameof(orderItemId));
        if (string.IsNullOrWhiteSpace(drinkName))
            throw new ArgumentException("Drink name cannot be empty / Ten do uong khong duoc rong", nameof(drinkName));

        Id = Guid.NewGuid();
        _shopId = shopId;
        _orderId = orderId;
        _orderItemId = orderItemId;
        _drinkName = drinkName;
        _customizations = customizations;
        _priority = priority;
        _statusId = 1; // Queued
        _estimatedMinutes = estimatedMinutes > 0 ? estimatedMinutes : 5;
        _createdAt = DateTime.UtcNow;

        // EN: Raise domain event for new drink queued
        // VI: Phat domain event khi do uong moi duoc xep hang
        AddDomainEvent(new DrinkQueuedDomainEvent(this));
    }

    /// <summary>
    /// EN: Start preparing the drink. Assigns a barista.
    /// VI: Bat dau pha che do uong. Giao cho barista.
    /// </summary>
    /// <param name="baristaName">Name of the barista / Ten barista</param>
    public void StartPreparing(string baristaName)
    {
        if (_statusId != 1) // Not Queued
            throw new InvalidOperationException(
                $"Can only start preparing from Queued status. Current: {StatusName} / " +
                $"Chi co the bat dau pha che tu trang thai Cho. Hien tai: {StatusName}");
        if (string.IsNullOrWhiteSpace(baristaName))
            throw new ArgumentException("Barista name is required / Ten barista la bat buoc", nameof(baristaName));

        _statusId = 2; // Preparing
        _assignedTo = baristaName;
        _startedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Mark the drink as ready for pickup.
    /// VI: Danh dau do uong san sang de lay.
    /// </summary>
    public void MarkReady()
    {
        if (_statusId != 2) // Not Preparing
            throw new InvalidOperationException(
                $"Can only mark ready from Preparing status. Current: {StatusName} / " +
                $"Chi co the danh dau san sang tu trang thai Dang pha. Hien tai: {StatusName}");

        _statusId = 3; // Ready
        _completedAt = DateTime.UtcNow;

        // EN: Raise domain event for drink ready notification
        // VI: Phat domain event thong bao do uong san sang
        AddDomainEvent(new DrinkReadyDomainEvent(this));
    }

    /// <summary>
    /// EN: Mark the drink as delivered to the customer.
    /// VI: Danh dau do uong da giao cho khach.
    /// </summary>
    public void MarkDelivered()
    {
        if (_statusId != 3) // Not Ready
            throw new InvalidOperationException(
                $"Can only mark delivered from Ready status. Current: {StatusName} / " +
                $"Chi co the danh dau da giao tu trang thai San sang. Hien tai: {StatusName}");

        _statusId = 4; // Delivered
        if (_completedAt == null)
            _completedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Cancel the queue item.
    /// VI: Huy item trong hang doi.
    /// </summary>
    public void Cancel()
    {
        if (_statusId == 4) // Delivered
            throw new InvalidOperationException(
                "Cannot cancel a delivered drink / Khong the huy do uong da giao");
        if (_statusId == 5) // Already cancelled
            throw new InvalidOperationException(
                "Drink is already cancelled / Do uong da bi huy roi");

        _statusId = 5; // Cancelled
        _completedAt = DateTime.UtcNow;
    }
}
