using WhatsAppService.Domain.Events;
using WhatsAppService.Domain.Exceptions;
using WhatsAppService.Domain.SeedWork;

namespace WhatsAppService.Domain.AggregatesModel.WhatsAppAccountAggregate;

/// <summary>
/// EN: WhatsApp Business Account aggregate root for managing shop's WhatsApp connection.
/// VI: WhatsApp Business Account aggregate root để quản lý kết nối WhatsApp của shop.
/// </summary>
public class WhatsAppAccount : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _shopId;
    private string _phoneNumberId = null!;
    private string _accessTokenEncrypted = null!;
    private string? _webhookUrl;
    private string? _webhookVerifyToken;
    private WhatsAppAccountStatus _status = null!;
    private string _messageTier = "tier_1";
    private DateTime _createdAt;
    private DateTime? _updatedAt;

    /// <summary>
    /// EN: Shop ID that owns this WhatsApp account.
    /// VI: Shop ID sở hữu WhatsApp account này.
    /// </summary>
    public Guid ShopId => _shopId;

    /// <summary>
    /// EN: WhatsApp phone number ID from Meta.
    /// VI: Phone number ID WhatsApp từ Meta.
    /// </summary>
    public string PhoneNumberId => _phoneNumberId;

    /// <summary>
    /// EN: Encrypted access token for WhatsApp Cloud API.
    /// VI: Access token đã mã hóa cho WhatsApp Cloud API.
    /// </summary>
    public string AccessTokenEncrypted => _accessTokenEncrypted;

    /// <summary>
    /// EN: Webhook URL for receiving WhatsApp events.
    /// VI: Webhook URL để nhận các sự kiện WhatsApp.
    /// </summary>
    public string? WebhookUrl => _webhookUrl;

    /// <summary>
    /// EN: Webhook verification token.
    /// VI: Token xác minh webhook.
    /// </summary>
    public string? WebhookVerifyToken => _webhookVerifyToken;

    /// <summary>
    /// EN: Current account status.
    /// VI: Trạng thái account hiện tại.
    /// </summary>
    public WhatsAppAccountStatus Status => _status;

    /// <summary>
    /// EN: Status ID for EF Core mapping.
    /// VI: ID trạng thái cho EF Core mapping.
    /// </summary>
    public int StatusId { get; private set; }

    /// <summary>
    /// EN: Message tier (tier_1, tier_2, tier_3, unlimited).
    /// VI: Tier tin nhắn (tier_1, tier_2, tier_3, unlimited).
    /// </summary>
    public string MessageTier => _messageTier;

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

    /// <summary>
    /// EN: Create a new WhatsApp account connection.
    /// VI: Tạo một kết nối WhatsApp account mới.
    /// </summary>
    /// <param name="shopId">EN: Shop ID that owns this account / VI: Shop ID sở hữu account này</param>
    /// <param name="phoneNumberId">EN: WhatsApp phone number ID / VI: WhatsApp phone number ID</param>
    /// <param name="accessTokenEncrypted">EN: Encrypted access token / VI: Access token đã mã hóa</param>
    /// <param name="webhookUrl">EN: Optional webhook URL / VI: Webhook URL tùy chọn</param>
    public WhatsAppAccount(
        Guid shopId,
        string phoneNumberId,
        string accessTokenEncrypted,
        string? webhookUrl = null) : this()
    {
        if (shopId == Guid.Empty)
            throw new WhatsAppAccountDomainException("Shop ID cannot be empty");
        
        if (string.IsNullOrWhiteSpace(phoneNumberId))
            throw new WhatsAppAccountDomainException("Phone number ID cannot be empty");
        
        if (string.IsNullOrWhiteSpace(accessTokenEncrypted))
            throw new WhatsAppAccountDomainException("Access token cannot be empty");

        Id = Guid.NewGuid();
        _shopId = shopId;
        _phoneNumberId = phoneNumberId;
        _accessTokenEncrypted = accessTokenEncrypted;
        _webhookUrl = webhookUrl;
        _status = WhatsAppAccountStatus.Pending;
        StatusId = WhatsAppAccountStatus.Pending.Id;
        _createdAt = DateTime.UtcNow;

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

    /// <summary>
    /// EN: Activate the WhatsApp account after verification.
    /// VI: Kích hoạt WhatsApp account sau khi xác minh.
    /// </summary>
    public void Activate()
    {
        if (_status == WhatsAppAccountStatus.Disconnected)
            throw new WhatsAppAccountDomainException("Cannot activate a disconnected account");

        if (_status == WhatsAppAccountStatus.Active)
            return; // EN: Already active, no-op / VI: Đã active, không làm gì

        var previousStatus = _status;
        _status = WhatsAppAccountStatus.Active;
        StatusId = WhatsAppAccountStatus.Active.Id;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new WhatsAppAccountStatusChangedEvent(Id, previousStatus, _status));
    }

    /// <summary>
    /// EN: Suspend the WhatsApp account temporarily.
    /// VI: Tạm ngưng WhatsApp account.
    /// </summary>
    public void Suspend()
    {
        if (_status == WhatsAppAccountStatus.Disconnected)
            throw new WhatsAppAccountDomainException("Cannot suspend a disconnected account");

        if (_status == WhatsAppAccountStatus.Suspended)
            return; // EN: Already suspended, no-op / VI: Đã suspended, không làm gì

        var previousStatus = _status;
        _status = WhatsAppAccountStatus.Suspended;
        StatusId = WhatsAppAccountStatus.Suspended.Id;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new WhatsAppAccountStatusChangedEvent(Id, previousStatus, _status));
    }

    /// <summary>
    /// EN: Disconnect the WhatsApp account permanently.
    /// VI: Ngắt kết nối WhatsApp account vĩnh viễn.
    /// </summary>
    public void Disconnect()
    {
        if (_status == WhatsAppAccountStatus.Disconnected)
            throw new WhatsAppAccountDomainException("Account is already disconnected");

        var previousStatus = _status;
        _status = WhatsAppAccountStatus.Disconnected;
        StatusId = WhatsAppAccountStatus.Disconnected.Id;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new WhatsAppAccountStatusChangedEvent(Id, previousStatus, _status));
    }

    /// <summary>
    /// EN: Update webhook configuration.
    /// VI: Cập nhật cấu hình webhook.
    /// </summary>
    /// <param name="webhookUrl">EN: New webhook URL / VI: Webhook URL mới</param>
    /// <param name="verifyToken">EN: Webhook verification token / VI: Token xác minh webhook</param>
    public void UpdateWebhook(string webhookUrl, string? verifyToken = null)
    {
        if (_status == WhatsAppAccountStatus.Disconnected)
            throw new WhatsAppAccountDomainException("Cannot update webhook on a disconnected account");

        if (string.IsNullOrWhiteSpace(webhookUrl))
            throw new WhatsAppAccountDomainException("Webhook URL cannot be empty");

        _webhookUrl = webhookUrl;
        _webhookVerifyToken = verifyToken;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new WebhookVerifiedEvent(Id, webhookUrl));
    }

    /// <summary>
    /// EN: Update access token (encrypted).
    /// VI: Cập nhật access token (đã mã hóa).
    /// </summary>
    /// <param name="accessTokenEncrypted">EN: New encrypted access token / VI: Access token đã mã hóa mới</param>
    public void UpdateAccessToken(string accessTokenEncrypted)
    {
        if (_status == WhatsAppAccountStatus.Disconnected)
            throw new WhatsAppAccountDomainException("Cannot update access token on a disconnected account");

        if (string.IsNullOrWhiteSpace(accessTokenEncrypted))
            throw new WhatsAppAccountDomainException("Access token cannot be empty");

        _accessTokenEncrypted = accessTokenEncrypted;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Upgrade message tier.
    /// VI: Nâng cấp tier tin nhắn.
    /// </summary>
    /// <param name="tier">EN: New message tier / VI: Tier tin nhắn mới</param>
    public void UpgradeMessageTier(string tier)
    {
        if (string.IsNullOrWhiteSpace(tier))
            throw new WhatsAppAccountDomainException("Message tier cannot be empty");

        var validTiers = new[] { "tier_1", "tier_2", "tier_3", "unlimited" };
        if (!validTiers.Contains(tier.ToLowerInvariant()))
            throw new WhatsAppAccountDomainException($"Invalid message tier. Valid values: {string.Join(", ", validTiers)}");

        _messageTier = tier.ToLowerInvariant();
        _updatedAt = DateTime.UtcNow;
    }
}
