using MktZaloService.Domain.Enums;
using MktZaloService.Domain.Events;
using MktZaloService.Domain.SeedWork;

namespace MktZaloService.Domain.AggregatesModel.CustomerAggregate;

/// <summary>
/// EN: Aggregate root for managing customer profiles and segmentation.
/// VI: Aggregate root để quản lý hồ sơ và phân khúc khách hàng.
/// </summary>
public class ZaloCustomer : Entity, IAggregateRoot
{
    private readonly List<Tag> _tags = new();

    /// <summary>
    /// EN: Zalo user ID (unique identifier from Zalo).
    /// VI: ID người dùng Zalo (định danh duy nhất từ Zalo).
    /// </summary>
    public string ZaloUserId { get; private set; } = string.Empty;

    /// <summary>
    /// EN: Customer profile information.
    /// VI: Thông tin hồ sơ khách hàng.
    /// </summary>
    public CustomerProfile Profile { get; private set; } = null!;

    /// <summary>
    /// EN: Customer segment based on engagement.
    /// VI: Phân khúc khách hàng dựa trên tương tác.
    /// </summary>
    public CustomerSegment Segment { get; private set; }

    /// <summary>
    /// EN: When the customer first interacted.
    /// VI: Thời điểm khách hàng tương tác lần đầu.
    /// </summary>
    public DateTime FirstInteractionAt { get; private set; }

    /// <summary>
    /// EN: When the customer last interacted.
    /// VI: Thời điểm khách hàng tương tác lần cuối.
    /// </summary>
    public DateTime LastInteractionAt { get; private set; }

    /// <summary>
    /// EN: Total number of conversations.
    /// VI: Tổng số cuộc hội thoại.
    /// </summary>
    public int ConversationCount { get; private set; }

    /// <summary>
    /// EN: Total number of messages across all conversations.
    /// VI: Tổng số tin nhắn trong tất cả cuộc hội thoại.
    /// </summary>
    public int TotalMessageCount { get; private set; }

    /// <summary>
    /// EN: Read-only collection of tags.
    /// VI: Danh sách thẻ chỉ đọc.
    /// </summary>
    public IReadOnlyCollection<Tag> Tags => _tags.AsReadOnly();

    /// <summary>
    /// EN: Whether the customer is blocked/inactive.
    /// VI: Khách hàng có bị chặn/không hoạt động không.
    /// </summary>
    public bool IsActive { get; private set; }

    /// <summary>
    /// EN: Audit field: Created timestamp.
    /// VI: Trường audit: Thời điểm tạo.
    /// </summary>
    public DateTime CreatedAt { get; private set; }

    /// <summary>
    /// EN: Audit field: Last updated timestamp.
    /// VI: Trường audit: Thời điểm cập nhật cuối.
    /// </summary>
    public DateTime UpdatedAt { get; private set; }

    /// <summary>
    /// EN: Required by EF Core.
    /// VI: Yêu cầu bởi EF Core.
    /// </summary>
    protected ZaloCustomer() { }

    /// <summary>
    /// EN: Create a new customer from Zalo user info.
    /// VI: Tạo khách hàng mới từ thông tin người dùng Zalo.
    /// </summary>
    public ZaloCustomer(string zaloUserId, string displayName, string? avatarUrl = null)
    {
        Id = Guid.NewGuid();
        ZaloUserId = zaloUserId ?? throw new ArgumentNullException(nameof(zaloUserId));
        Profile = new CustomerProfile(displayName, avatarUrl);
        Segment = CustomerSegment.New;
        FirstInteractionAt = DateTime.UtcNow;
        LastInteractionAt = DateTime.UtcNow;
        IsActive = true;
        CreatedAt = DateTime.UtcNow;
        UpdatedAt = DateTime.UtcNow;
        ConversationCount = 0;
        TotalMessageCount = 0;

        AddDomainEvent(new CustomerCreatedDomainEvent(Id, ZaloUserId, displayName));
    }

    /// <summary>
    /// EN: Update customer profile information.
    /// VI: Cập nhật thông tin hồ sơ khách hàng.
    /// </summary>
    public void UpdateProfile(
        string displayName,
        string? avatarUrl = null,
        string? phoneNumber = null,
        string? email = null)
    {
        Profile = new CustomerProfile(displayName, avatarUrl, phoneNumber, email);
        UpdatedAt = DateTime.UtcNow;

        AddDomainEvent(new CustomerProfileUpdatedDomainEvent(Id, ZaloUserId));
    }

    /// <summary>
    /// EN: Add a tag to the customer (idempotent).
    /// VI: Thêm thẻ cho khách hàng (idempotent).
    /// </summary>
    public void AddTag(string tagName)
    {
        var normalizedName = tagName.Trim().ToLowerInvariant();

        if (_tags.Any(t => t.Name.Equals(normalizedName, StringComparison.OrdinalIgnoreCase)))
        {
            return; // Idempotent - tag already exists
        }

        _tags.Add(new Tag(tagName));
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Remove a tag from the customer.
    /// VI: Xóa thẻ khỏi khách hàng.
    /// </summary>
    public void RemoveTag(string tagName)
    {
        var normalizedName = tagName.Trim().ToLowerInvariant();
        var tag = _tags.FirstOrDefault(t => t.Name.Equals(normalizedName, StringComparison.OrdinalIgnoreCase));

        if (tag is not null)
        {
            _tags.Remove(tag);
            UpdatedAt = DateTime.UtcNow;
        }
    }

    /// <summary>
    /// EN: Record a new interaction (updates last interaction time).
    /// VI: Ghi nhận tương tác mới (cập nhật thời gian tương tác cuối).
    /// </summary>
    public void RecordInteraction()
    {
        LastInteractionAt = DateTime.UtcNow;
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Increment conversation count.
    /// VI: Tăng số lượng cuộc hội thoại.
    /// </summary>
    public void IncrementConversationCount()
    {
        ConversationCount++;
        UpdateSegment();
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Increment total message count.
    /// VI: Tăng tổng số tin nhắn.
    /// </summary>
    public void IncrementMessageCount(int count = 1)
    {
        TotalMessageCount += count;
        UpdateSegment();
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update segment based on engagement metrics.
    /// VI: Cập nhật phân khúc dựa trên chỉ số tương tác.
    /// </summary>
    private void UpdateSegment()
    {
        Segment = (ConversationCount, TotalMessageCount) switch
        {
            (> 50, > 500) => CustomerSegment.VIP,
            (> 20, > 200) => CustomerSegment.Active,
            (> 5, > 50) => CustomerSegment.Regular,
            _ => CustomerSegment.New
        };
    }

    /// <summary>
    /// EN: Mark customer as inactive (blocked OA).
    /// VI: Đánh dấu khách hàng không hoạt động (đã chặn OA).
    /// </summary>
    public void MarkInactive()
    {
        IsActive = false;
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Mark customer as active.
    /// VI: Đánh dấu khách hàng hoạt động.
    /// </summary>
    public void MarkActive()
    {
        IsActive = true;
        UpdatedAt = DateTime.UtcNow;
    }
}
