// EN: Product aggregate root for polymorphic products.
// VI: Aggregate root Product cho sản phẩm đa hình.

using System.Text.Json;
using CatalogService.Domain.Events;
using CatalogService.Domain.Exceptions;
using CatalogService.Domain.SeedWork;

namespace CatalogService.Domain.AggregatesModel.ProductAggregate;

/// <summary>
/// EN: Product aggregate root - polymorphic product supporting multi-vertical.
/// VI: Aggregate root Product - sản phẩm đa hình hỗ trợ đa ngành hàng.
/// </summary>
public class Product : Entity, IAggregateRoot
{
    private Guid _shopId;
    private string _name = null!;
    private string? _description;
    private decimal _price;
    private ProductType _type = null!;
    private JsonDocument? _attributes; // Type-specific attributes in JSONB
    private string? _imageUrl;
    private string? _sku;
    private bool _isActive;
    private DateTime _createdAt;
    private DateTime? _updatedAt;

    /// <summary>
    /// EN: Shop ID that owns this product.
    /// VI: ID shop sở hữu sản phẩm này.
    /// </summary>
    public Guid ShopId => _shopId;

    /// <summary>
    /// EN: Product name.
    /// VI: Tên sản phẩm.
    /// </summary>
    public string Name => _name;

    /// <summary>
    /// EN: Product description.
    /// VI: Mô tả sản phẩm.
    /// </summary>
    public string? Description => _description;

    /// <summary>
    /// EN: Product price.
    /// VI: Giá sản phẩm.
    /// </summary>
    public decimal Price => _price;

    /// <summary>
    /// EN: Product type.
    /// VI: Loại sản phẩm.
    /// </summary>
    public ProductType Type => _type;

    /// <summary>
    /// EN: Type ID for EF Core mapping.
    /// VI: Type ID cho EF Core mapping.
    /// </summary>
    public int TypeId { get; private set; }

    /// <summary>
    /// EN: Type-specific attributes stored as JSONB.
    /// VI: Thuộc tính theo loại lưu dưới dạng JSONB.
    /// </summary>
    public JsonDocument? Attributes => _attributes;

    /// <summary>
    /// EN: Product image URL.
    /// VI: URL hình ảnh sản phẩm.
    /// </summary>
    public string? ImageUrl => _imageUrl;

    /// <summary>
    /// EN: Stock Keeping Unit (for Physical products).
    /// VI: Mã SKU (cho sản phẩm vật lý).
    /// </summary>
    public string? Sku => _sku;

    /// <summary>
    /// EN: Is product active and available for sale.
    /// VI: Sản phẩm có đang hoạt động và sẵn sàng bán không.
    /// </summary>
    public bool IsActive => _isActive;

    /// <summary>
    /// EN: Creation timestamp.
    /// VI: Thời gian tạo.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: Last update timestamp.
    /// VI: Thời gian cập nhật cuối.
    /// </summary>
    public DateTime? UpdatedAt => _updatedAt;

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

    /// <summary>
    /// EN: Create a new product.
    /// VI: Tạo sản phẩm mới.
    /// </summary>
    public Product(
        Guid shopId,
        string name,
        decimal price,
        ProductType type,
        string? description = null,
        JsonDocument? attributes = null,
        string? sku = null)
    {
        if (shopId == Guid.Empty)
            throw new DomainException("Shop ID cannot be empty");
        if (string.IsNullOrWhiteSpace(name))
            throw new DomainException("Product name cannot be empty");
        if (price < 0)
            throw new DomainException("Price cannot be negative");
        ArgumentNullException.ThrowIfNull(type, nameof(type));

        Id = Guid.NewGuid();
        _shopId = shopId;
        _name = name.Trim();
        _description = description?.Trim();
        _price = price;
        _type = type;
        TypeId = type.Id;
        _attributes = attributes;
        _sku = sku?.Trim();
        _isActive = true;
        _createdAt = DateTime.UtcNow;

        AddDomainEvent(new ProductCreatedDomainEvent(this));
    }

    /// <summary>
    /// EN: Update product basic information.
    /// VI: Cập nhật thông tin cơ bản sản phẩm.
    /// </summary>
    public void UpdateInfo(string name, string? description, decimal price)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new DomainException("Product name cannot be empty");
        if (price < 0)
            throw new DomainException("Price cannot be negative");

        _name = name.Trim();
        _description = description?.Trim();
        _price = price;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update type-specific attributes.
    /// VI: Cập nhật thuộc tính theo loại.
    /// </summary>
    public void UpdateAttributes(JsonDocument? attributes)
    {
        _attributes = attributes;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update product image.
    /// VI: Cập nhật hình ảnh sản phẩm.
    /// </summary>
    public void UpdateImage(string? imageUrl)
    {
        _imageUrl = imageUrl;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Activate product.
    /// VI: Kích hoạt sản phẩm.
    /// </summary>
    public void Activate()
    {
        if (_isActive)
            throw new DomainException("Product is already active");

        _isActive = true;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Deactivate product.
    /// VI: Vô hiệu hóa sản phẩm.
    /// </summary>
    public void Deactivate()
    {
        if (!_isActive)
            throw new DomainException("Product is already inactive");

        _isActive = false;
        _updatedAt = DateTime.UtcNow;
    }
}
