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

namespace MktXService.Domain.AggregatesModel.TwitterAccountAggregate;

/// <summary>
/// EN: Twitter account aggregate root managing connected Twitter accounts with OAuth credentials.
/// VI: Aggregate root tài khoản Twitter quản lý các tài khoản Twitter đã kết nối với OAuth credentials.
/// </summary>
public class TwitterAccount : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _merchantId;
    private string _twitterUserId = null!;
    private string _username = null!;
    private string? _displayName;
    private string? _profileImageUrl;
    private TwitterAccountStatus _status = null!;
    private string _oauthToken = null!;
    private string _oauthTokenSecret = null!;
    private string? _webhookId;
    private Dictionary<string, object> _settings = new();
    private DateTime _connectedAt;
    private DateTime _createdAt;
    private DateTime? _updatedAt;

    /// <summary>
    /// EN: Merchant ID who owns this account.
    /// VI: ID merchant sở hữu tài khoản này.
    /// </summary>
    public Guid MerchantId => _merchantId;

    /// <summary>
    /// EN: Twitter user ID (unique).
    /// VI: Twitter user ID (duy nhất).
    /// </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: Current status.
    /// VI: Trạng thái hiện tại.
    /// </summary>
    public TwitterAccountStatus 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: Encrypted OAuth token.
    /// VI: OAuth token đã mã hóa.
    /// </summary>
    public string OAuthToken => _oauthToken;

    /// <summary>
    /// EN: Encrypted OAuth token secret.
    /// VI: OAuth token secret đã mã hóa.
    /// </summary>
    public string OAuthTokenSecret => _oauthTokenSecret;

    /// <summary>
    /// EN: Twitter webhook ID for this account.
    /// VI: ID webhook Twitter cho tài khoản này.
    /// </summary>
    public string? WebhookId => _webhookId;

    /// <summary>
    /// EN: Account settings as JSON.
    /// VI: Cài đặt tài khoản dạng JSON.
    /// </summary>
    public IReadOnlyDictionary<string, object> Settings => _settings;

    /// <summary>
    /// EN: When the account was connected.
    /// VI: Thời điểm tài khoản được kết nối.
    /// </summary>
    public DateTime ConnectedAt => _connectedAt;

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

    /// <summary>
    /// EN: Create a new Twitter account with OAuth credentials.
    /// VI: Tạo một tài khoản Twitter mới với OAuth credentials.
    /// </summary>
    /// <param name="merchantId">EN: Merchant ID / VI: ID merchant</param>
    /// <param name="twitterUserId">EN: Twitter user ID / VI: Twitter user ID</param>
    /// <param name="username">EN: Twitter username / VI: Twitter username</param>
    /// <param name="oauthToken">EN: OAuth token (encrypted) / VI: OAuth token (đã mã hóa)</param>
    /// <param name="oauthTokenSecret">EN: OAuth token secret (encrypted) / VI: OAuth token secret (đã mã hóa)</param>
    /// <param name="displayName">EN: Display name / VI: Tên hiển thị</param>
    /// <param name="profileImageUrl">EN: Profile image URL / VI: URL ảnh đại diện</param>
    public TwitterAccount(
        Guid merchantId,
        string twitterUserId,
        string username,
        string oauthToken,
        string oauthTokenSecret,
        string? displayName = null,
        string? profileImageUrl = null) : this()
    {
        if (merchantId == Guid.Empty)
            throw new TwitterAccountDomainException("Merchant ID cannot be empty");
        if (string.IsNullOrWhiteSpace(twitterUserId))
            throw new TwitterAccountDomainException("Twitter user ID cannot be empty");
        if (string.IsNullOrWhiteSpace(username))
            throw new TwitterAccountDomainException("Username cannot be empty");
        if (string.IsNullOrWhiteSpace(oauthToken))
            throw new TwitterAccountDomainException("OAuth token cannot be empty");
        if (string.IsNullOrWhiteSpace(oauthTokenSecret))
            throw new TwitterAccountDomainException("OAuth token secret cannot be empty");

        Id = Guid.NewGuid();
        _merchantId = merchantId;
        _twitterUserId = twitterUserId;
        _username = username;
        _displayName = displayName;
        _profileImageUrl = profileImageUrl;
        _oauthToken = oauthToken;
        _oauthTokenSecret = oauthTokenSecret;
        _status = TwitterAccountStatus.Pending;
        StatusId = TwitterAccountStatus.Pending.Id;
        _connectedAt = DateTime.UtcNow;
        _createdAt = DateTime.UtcNow;

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

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

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

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

    /// <summary>
    /// EN: Set the webhook ID for this account.
    /// VI: Thiết lập webhook ID cho tài khoản này.
    /// </summary>
    public void SetWebhookId(string webhookId)
    {
        if (string.IsNullOrWhiteSpace(webhookId))
            throw new TwitterAccountDomainException("Webhook ID cannot be empty");

        _webhookId = webhookId;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update OAuth credentials.
    /// VI: Cập nhật OAuth credentials.
    /// </summary>
    public void UpdateCredentials(string oauthToken, string oauthTokenSecret)
    {
        if (string.IsNullOrWhiteSpace(oauthToken))
            throw new TwitterAccountDomainException("OAuth token cannot be empty");
        if (string.IsNullOrWhiteSpace(oauthTokenSecret))
            throw new TwitterAccountDomainException("OAuth token secret cannot be empty");

        _oauthToken = oauthToken;
        _oauthTokenSecret = oauthTokenSecret;
        _updatedAt = DateTime.UtcNow;
    }

    /// <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 TwitterAccountDomainException("Username cannot be empty");

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

    /// <summary>
    /// EN: Update account settings.
    /// VI: Cập nhật cài đặt tài khoản.
    /// </summary>
    public void UpdateSettings(Dictionary<string, object> settings)
    {
        _settings = settings ?? new Dictionary<string, object>();
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Mark account as having an error.
    /// VI: Đánh dấu tài khoản có lỗi.
    /// </summary>
    public void MarkAsError()
    {
        var previousStatus = _status;
        _status = TwitterAccountStatus.Error;
        StatusId = TwitterAccountStatus.Error.Id;
        _updatedAt = DateTime.UtcNow;

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

    /// <summary>
    /// EN: Deactivate the account temporarily.
    /// VI: Tạm thời vô hiệu hóa tài khoản.
    /// </summary>
    public void Deactivate()
    {
        if (_status == TwitterAccountStatus.Disconnected)
            throw new TwitterAccountDomainException("Cannot deactivate a disconnected account");

        var previousStatus = _status;
        _status = TwitterAccountStatus.Inactive;
        StatusId = TwitterAccountStatus.Inactive.Id;
        _updatedAt = DateTime.UtcNow;

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

    /// <summary>
    /// EN: Disconnect the account and revoke access.
    /// VI: Ngắt kết nối tài khoản và thu hồi quyền truy cập.
    /// </summary>
    public void Disconnect()
    {
        if (_status == TwitterAccountStatus.Disconnected)
            throw new TwitterAccountDomainException("Account is already disconnected");

        var previousStatus = _status;
        _status = TwitterAccountStatus.Disconnected;
        StatusId = TwitterAccountStatus.Disconnected.Id;
        _webhookId = null;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new TwitterAccountDisconnectedDomainEvent(Id, _merchantId));
    }
}
