using MktXService.Domain.Events;
using MktXService.Domain.Exceptions;
using MktXService.Domain.SeedWork;

namespace MktXService.Domain.AggregatesModel.ContactAggregate;

/// <summary>
/// EN: Contact aggregate root representing Twitter users who interact with merchant accounts.
/// VI: Aggregate root Contact đại diện cho người dùng Twitter tương tác với tài khoản merchant.
/// </summary>
public class Contact : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _accountId;
    private string _twitterUserId = null!;
    private string _username = null!;
    private string? _displayName;
    private string? _profileImageUrl;
    private string _source = null!;
    private Dictionary<string, object> _attributes = new();
    private List<ContactTag> _tags = new();
    private DateTime _firstInteractionAt;
    private DateTime? _lastInteractionAt;
    private DateTime _createdAt;
    private DateTime? _updatedAt;

    /// <summary>
    /// EN: Twitter account ID this contact belongs to.
    /// VI: ID tài khoản Twitter mà liên hệ này thuộc về.
    /// </summary>
    public Guid AccountId => _accountId;

    /// <summary>
    /// EN: Twitter user ID.
    /// VI: Twitter user ID.
    /// </summary>
    public string TwitterUserId => _twitterUserId;

    /// <summary>
    /// EN: Twitter username (handle without @).
    /// VI: Twitter username (handle không có @).
    /// </summary>
    public string Username => _username;

    /// <summary>
    /// EN: Display name on Twitter.
    /// VI: Tên hiển thị trên Twitter.
    /// </summary>
    public string? DisplayName => _displayName;

    /// <summary>
    /// EN: Profile image URL.
    /// VI: URL ảnh đại diện.
    /// </summary>
    public string? ProfileImageUrl => _profileImageUrl;

    /// <summary>
    /// EN: Source of contact creation (e.g., inbound_message, follower, campaign).
    /// VI: Nguồn tạo liên hệ (ví dụ: inbound_message, follower, campaign).
    /// </summary>
    public string Source => _source;

    /// <summary>
    /// EN: Custom attributes as JSON.
    /// VI: Thuộc tính tùy chỉnh dạng JSON.
    /// </summary>
    public IReadOnlyDictionary<string, object> Attributes => _attributes;

    /// <summary>
    /// EN: Contact tags for segmentation.
    /// VI: Tags liên hệ để phân khúc.
    /// </summary>
    public IReadOnlyCollection<ContactTag> Tags => _tags.AsReadOnly();

    /// <summary>
    /// EN: First interaction timestamp.
    /// VI: Thời gian tương tác đầu tiên.
    /// </summary>
    public DateTime FirstInteractionAt => _firstInteractionAt;

    /// <summary>
    /// EN: Last interaction timestamp.
    /// VI: Thời gian tương tác cuối cùng.
    /// </summary>
    public DateTime? LastInteractionAt => _lastInteractionAt;

    /// <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 Contact()
    {
    }

    /// <summary>
    /// EN: Create a new contact from a Twitter user interaction.
    /// VI: Tạo một liên hệ mới từ tương tác người dùng Twitter.
    /// </summary>
    public Contact(
        Guid accountId,
        string twitterUserId,
        string username,
        string source,
        string? displayName = null,
        string? profileImageUrl = null) : this()
    {
        if (accountId == Guid.Empty)
            throw new ContactDomainException("Account ID cannot be empty");
        if (string.IsNullOrWhiteSpace(twitterUserId))
            throw new ContactDomainException("Twitter user ID cannot be empty");
        if (string.IsNullOrWhiteSpace(username))
            throw new ContactDomainException("Username cannot be empty");
        if (string.IsNullOrWhiteSpace(source))
            throw new ContactDomainException("Source cannot be empty");

        Id = Guid.NewGuid();
        _accountId = accountId;
        _twitterUserId = twitterUserId;
        _username = username;
        _source = source;
        _displayName = displayName;
        _profileImageUrl = profileImageUrl;
        _firstInteractionAt = DateTime.UtcNow;
        _lastInteractionAt = DateTime.UtcNow;
        _createdAt = DateTime.UtcNow;

        // EN: Add domain event for creation
        // VI: Thêm domain event cho việc tạo
        AddDomainEvent(new ContactCreatedDomainEvent(this));
    }

    /// <summary>
    /// EN: Update profile information from Twitter.
    /// VI: Cập nhật thông tin profile từ Twitter.
    /// </summary>
    public void UpdateProfile(string username, string? displayName, string? profileImageUrl)
    {
        if (string.IsNullOrWhiteSpace(username))
            throw new ContactDomainException("Username cannot be empty");

        _username = username;
        _displayName = displayName;
        _profileImageUrl = profileImageUrl;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Add a tag to this contact.
    /// VI: Thêm một tag cho liên hệ này.
    /// </summary>
    public void AddTag(string tagName)
    {
        if (string.IsNullOrWhiteSpace(tagName))
            throw new ContactDomainException("Tag name cannot be empty");

        var normalizedName = tagName.ToLowerInvariant().Trim();

        // EN: Check for duplicate
        // VI: Kiểm tra trùng lặp
        if (_tags.Any(t => t.Name == normalizedName))
            return; // Tag already exists, no-op

        var tag = new ContactTag(Id, normalizedName);
        _tags.Add(tag);
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new ContactTaggedDomainEvent(Id, normalizedName));
    }

    /// <summary>
    /// EN: Remove a tag from this contact.
    /// VI: Xóa một tag khỏi liên hệ này.
    /// </summary>
    public void RemoveTag(string tagName)
    {
        if (string.IsNullOrWhiteSpace(tagName))
            throw new ContactDomainException("Tag name cannot be empty");

        var normalizedName = tagName.ToLowerInvariant().Trim();
        var tag = _tags.FirstOrDefault(t => t.Name == normalizedName);

        if (tag != null)
        {
            _tags.Remove(tag);
            _updatedAt = DateTime.UtcNow;
        }
    }

    /// <summary>
    /// EN: Update a single custom attribute.
    /// VI: Cập nhật một thuộc tính tùy chỉnh.
    /// </summary>
    public void SetAttribute(string key, object value)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new ContactDomainException("Attribute key cannot be empty");

        _attributes[key] = value;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Remove a custom attribute.
    /// VI: Xóa một thuộc tính tùy chỉnh.
    /// </summary>
    public void RemoveAttribute(string key)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new ContactDomainException("Attribute key cannot be empty");

        _attributes.Remove(key);
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Bulk update custom attributes.
    /// VI: Cập nhật hàng loạt thuộc tính tùy chỉnh.
    /// </summary>
    public void UpdateAttributes(Dictionary<string, object> attributes)
    {
        foreach (var kvp in attributes)
        {
            if (!string.IsNullOrWhiteSpace(kvp.Key))
            {
                _attributes[kvp.Key] = kvp.Value;
            }
        }
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Record an interaction with this contact.
    /// VI: Ghi nhận một tương tác với liên hệ này.
    /// </summary>
    public void RecordInteraction()
    {
        _lastInteractionAt = DateTime.UtcNow;
        _updatedAt = DateTime.UtcNow;
    }
}
