using FacebookService.Domain.Events;
using FacebookService.Domain.Exceptions;
using FacebookService.Domain.SeedWork;

namespace FacebookService.Domain.AggregatesModel.CustomerAggregate;

/// <summary>
/// EN: Customer aggregate root representing a Facebook Messenger user.
/// VI: Customer aggregate root đại diện cho người dùng Facebook Messenger.
/// </summary>
public class Customer : Entity, IAggregateRoot
{
    // EN: Maximum number of custom fields allowed per customer
    // VI: Số lượng custom fields tối đa cho mỗi khách hàng
    private const int MaxCustomFields = 50;

    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private string _facebookUserId = null!;
    private string? _name;
    private string? _email;
    private string? _phone;
    private string? _profilePicUrl;
    private string? _locale;
    private string? _timezone;
    private List<string> _tags = new();
    private Dictionary<string, string> _customFields = new();
    private DateTime _firstSeenAt;
    private DateTime _lastInteractionAt;

    /// <summary>
    /// EN: Facebook User ID (unique). / VI: Facebook User ID (duy nhất).
    /// </summary>
    public string FacebookUserId => _facebookUserId;

    /// <summary>
    /// EN: Customer display name. / VI: Tên hiển thị của khách hàng.
    /// </summary>
    public string? Name => _name;

    /// <summary>
    /// EN: Customer email address. / VI: Địa chỉ email của khách hàng.
    /// </summary>
    public string? Email => _email;

    /// <summary>
    /// EN: Customer phone number. / VI: Số điện thoại của khách hàng.
    /// </summary>
    public string? Phone => _phone;

    /// <summary>
    /// EN: Facebook profile picture URL. / VI: URL ảnh đại diện Facebook.
    /// </summary>
    public string? ProfilePicUrl => _profilePicUrl;

    /// <summary>
    /// EN: Customer locale (e.g., en_US, vi_VN). / VI: Locale của khách hàng.
    /// </summary>
    public string? Locale => _locale;

    /// <summary>
    /// EN: Customer timezone. / VI: Múi giờ của khách hàng.
    /// </summary>
    public string? Timezone => _timezone;

    /// <summary>
    /// EN: Customer tags for segmentation. / VI: Tags để phân khúc khách hàng.
    /// </summary>
    public IReadOnlyCollection<string> Tags => _tags.AsReadOnly();

    /// <summary>
    /// EN: Custom fields for additional data. / VI: Custom fields cho dữ liệu bổ sung.
    /// </summary>
    public IReadOnlyDictionary<string, string> CustomFields => _customFields.AsReadOnly();

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

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

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

    /// <summary>
    /// EN: Create a new Customer from Facebook user ID.
    /// VI: Tạo Customer mới từ Facebook user ID.
    /// </summary>
    /// <param name="facebookUserId">EN: Facebook user ID / VI: ID người dùng Facebook</param>
    /// <param name="name">EN: Optional display name / VI: Tên hiển thị tùy chọn</param>
    public Customer(string facebookUserId, string? name = null) : this()
    {
        if (string.IsNullOrWhiteSpace(facebookUserId))
            throw new FacebookDomainException("Facebook User ID cannot be empty");

        Id = Guid.NewGuid();
        _facebookUserId = facebookUserId;
        _name = name;
        _firstSeenAt = DateTime.UtcNow;
        _lastInteractionAt = DateTime.UtcNow;

        AddDomainEvent(new CustomerCreatedDomainEvent(this));
    }

    /// <summary>
    /// EN: Update customer profile from Facebook data.
    /// VI: Cập nhật hồ sơ khách hàng từ dữ liệu Facebook.
    /// </summary>
    public void UpdateProfile(string? name, string? email, string? phone, 
        string? profilePicUrl, string? locale, string? timezone)
    {
        _name = name;
        _email = email;
        _phone = phone;
        _profilePicUrl = profilePicUrl;
        _locale = locale;
        _timezone = timezone;
        _lastInteractionAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Add a tag to the customer for segmentation.
    /// VI: Thêm tag cho khách hàng để phân khúc.
    /// </summary>
    /// <param name="tag">EN: Tag name / VI: Tên tag</param>
    public void AddTag(string tag)
    {
        if (string.IsNullOrWhiteSpace(tag))
            throw new FacebookDomainException("Tag cannot be empty");

        var normalizedTag = tag.Trim();
        if (!_tags.Contains(normalizedTag, StringComparer.OrdinalIgnoreCase))
        {
            _tags.Add(normalizedTag);
        }
    }

    /// <summary>
    /// EN: Remove a tag from the customer.
    /// VI: Xóa tag khỏi khách hàng.
    /// </summary>
    /// <param name="tag">EN: Tag name / VI: Tên tag</param>
    public void RemoveTag(string tag)
    {
        if (string.IsNullOrWhiteSpace(tag))
            return;

        var tagToRemove = _tags.FirstOrDefault(t => 
            t.Equals(tag.Trim(), StringComparison.OrdinalIgnoreCase));
        
        if (tagToRemove != null)
        {
            _tags.Remove(tagToRemove);
        }
    }

    /// <summary>
    /// EN: Set a custom field value.
    /// VI: Đặt giá trị custom field.
    /// </summary>
    /// <param name="key">EN: Field key / VI: Key của field</param>
    /// <param name="value">EN: Field value / VI: Giá trị của field</param>
    public void SetCustomField(string key, string value)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new FacebookDomainException("Custom field key cannot be empty");

        if (!_customFields.ContainsKey(key) && _customFields.Count >= MaxCustomFields)
            throw new FacebookDomainException($"Cannot add more than {MaxCustomFields} custom fields");

        _customFields[key] = value;
    }

    /// <summary>
    /// EN: Remove a custom field.
    /// VI: Xóa custom field.
    /// </summary>
    /// <param name="key">EN: Field key / VI: Key của field</param>
    public void RemoveCustomField(string key)
    {
        if (!string.IsNullOrWhiteSpace(key))
        {
            _customFields.Remove(key);
        }
    }

    /// <summary>
    /// EN: Record a new interaction (update 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;
    }
}
