using CartWise.Domain.Enums;

namespace CartWise.Domain.Entities;

public class Product
{
    private readonly List<ProductIdentifier> _identifiers = [];

    public Guid ProductId { get; private set; }

    public Guid? GroceryConceptId { get; private set; }

    public Guid? BrandId { get; private set; }

    public string Name { get; private set; } = null!;

    public string NormalizedName { get; private set; } = null!;

    public decimal? SizeValue { get; private set; }

    public string? SizeUnit { get; private set; }

    public string? ImageUrl { get; private set; }

    public ProductSourceType SourceType { get; private set; }

    public string? SourceExternalId { get; private set; }

    public DateTime CreatedUtc { get; private set; }

    public DateTime UpdatedUtc { get; private set; }

    public IReadOnlyCollection<ProductIdentifier> Identifiers => _identifiers.AsReadOnly();

    private Product()
    {
    }

    public Product(
        string name,
        ProductSourceType sourceType,
        DateTime createdUtc,
        Guid? groceryConceptId = null,
        Guid? brandId = null,
        decimal? sizeValue = null,
        string? sizeUnit = null,
        string? imageUrl = null,
        string? sourceExternalId = null)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("Product name is required.", nameof(name));
        }

        ProductId = Guid.NewGuid();
        Name = name.Trim();
        NormalizedName = Name.ToUpperInvariant();
        SourceType = sourceType;
        GroceryConceptId = groceryConceptId;
        BrandId = brandId;
        SizeValue = sizeValue;
        SizeUnit = sizeUnit;
        ImageUrl = imageUrl;
        SourceExternalId = sourceExternalId;
        CreatedUtc = createdUtc;
        UpdatedUtc = createdUtc;
    }

    public ProductIdentifier AddIdentifier(ProductIdentifierType identifierType, string value)
    {
        var normalized = ProductIdentifier.Normalize(value);
        if (_identifiers.Any(i => i.IdentifierType == identifierType && i.NormalizedValue == normalized))
        {
            throw new InvalidOperationException("This product already has that identifier.");
        }

        var identifier = new ProductIdentifier(ProductId, identifierType, value);
        _identifiers.Add(identifier);
        return identifier;
    }
}
