// EN: Merchant aggregate root.
// VI: Aggregate root Merchant.

using MerchantService.Domain.Events;
using MerchantService.Domain.Exceptions;
using MerchantService.Domain.SeedWork;

namespace MerchantService.Domain.AggregatesModel.MerchantAggregate;

/// <summary>
/// EN: Merchant aggregate root - represents a shop owner who can own multiple shops.
/// VI: Aggregate root Merchant - đại diện cho chủ shop có thể sở hữu nhiều shop.
/// </summary>
public class Merchant : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _userId;
    private string _businessName = null!;
    private MerchantType _type = null!;
    private MerchantStatus _status = null!;
    private VerificationStatus _verificationStatus = null!;
    private BusinessInfo _businessInfo = null!;
    private SettlementConfig _settlementConfig = null!;
    private DateTime _createdAt;
    private int _subscriptionPlanId;
    private DateTime? _updatedAt;
    private bool _isDeleted;

    /// <summary>
    /// EN: Reference to IAM User (Owner).
    /// VI: Tham chiếu đến IAM User (Chủ sở hữu).
    /// </summary>
    public Guid UserId => _userId;

    /// <summary>
    /// EN: Business/Company name.
    /// VI: Tên doanh nghiệp/công ty.
    /// </summary>
    public string BusinessName => _businessName;

    /// <summary>
    /// EN: Merchant type (Individual or Company).
    /// VI: Loại merchant (Cá nhân hoặc Doanh nghiệp).
    /// </summary>
    public MerchantType Type => _type;

    /// <summary>
    /// EN: Merchant type ID for EF Core mapping.
    /// VI: Type ID cho EF Core mapping.
    /// </summary>
    public int TypeId { get; private set; }

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

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

    /// <summary>
    /// EN: Verification status.
    /// VI: Trạng thái xác minh.
    /// </summary>
    public VerificationStatus VerificationStatus => _verificationStatus;

    /// <summary>
    /// EN: Verification status ID for EF Core mapping.
    /// VI: Verification status ID cho EF Core mapping.
    /// </summary>
    public int VerificationStatusId { get; private set; }

    /// <summary>
    /// EN: Business information for verification.
    /// VI: Thông tin doanh nghiệp để xác minh.
    /// </summary>
    public BusinessInfo BusinessInfo => _businessInfo;

    /// <summary>
    /// EN: Settlement configuration.
    /// VI: Cấu hình thanh toán.
    /// </summary>
    public SettlementConfig SettlementConfig => _settlementConfig;

    /// <summary>
    /// EN: When merchant was verified.
    /// VI: Thời điểm merchant được xác minh.
    /// </summary>
    public DateTime? VerifiedAt { get; private set; }

    /// <summary>
    /// EN: Who verified the merchant.
    /// VI: Ai đã xác minh merchant.
    /// </summary>
    public Guid? VerifiedBy { get; private set; }

    /// <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: Subscription plan ID (0=Starter, 1=Growth, 2=Pro, 3=Enterprise).
    /// VI: ID gói đăng ký (0=Starter, 1=Growth, 2=Pro, 3=Enterprise).
    /// </summary>
    public int SubscriptionPlanId => _subscriptionPlanId;

    /// <summary>
    /// EN: Soft delete flag.
    /// VI: Cờ xóa mềm.
    /// </summary>
    public bool IsDeleted => _isDeleted;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected Merchant()
    {
        _businessInfo = BusinessInfo.Empty;
        _settlementConfig = SettlementConfig.Default;
    }

    /// <summary>
    /// EN: Factory method to register a new merchant.
    /// VI: Factory method để đăng ký merchant mới.
    /// </summary>
    /// <param name="userId">IAM User ID / ID người dùng IAM</param>
    /// <param name="businessName">Business name / Tên doanh nghiệp</param>
    /// <param name="type">Merchant type / Loại merchant</param>
    /// <returns>New Merchant instance / Instance Merchant mới</returns>
    public static Merchant Register(Guid userId, string businessName, MerchantType type)
    {
        if (userId == Guid.Empty)
            throw new DomainException("User ID cannot be empty");
        if (string.IsNullOrWhiteSpace(businessName))
            throw new DomainException("Business name cannot be empty");
        ArgumentNullException.ThrowIfNull(type, nameof(type));

        var merchant = new Merchant
        {
            Id = Guid.NewGuid(),
            _userId = userId,
            _businessName = businessName.Trim(),
            _type = type,
            TypeId = type.Id,
            _status = MerchantStatus.Active,  // EN: Auto-activate for MVP dev flow / VI: Tự kích hoạt cho MVP dev
            StatusId = MerchantStatus.Active.Id,
            _verificationStatus = VerificationStatus.Unverified,
            VerificationStatusId = VerificationStatus.Unverified.Id,
            _businessInfo = BusinessInfo.Empty,
            _settlementConfig = SettlementConfig.Default,
            _createdAt = DateTime.UtcNow
        };

        merchant.AddDomainEvent(new MerchantRegisteredDomainEvent(merchant));
        return merchant;
    }

    /// <summary>
    /// EN: Update business name.
    /// VI: Cập nhật tên doanh nghiệp.
    /// </summary>
    public void UpdateBusinessName(string businessName)
    {
        if (string.IsNullOrWhiteSpace(businessName))
            throw new DomainException("Business name cannot be empty");

        _businessName = businessName.Trim();
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update business information.
    /// VI: Cập nhật thông tin doanh nghiệp.
    /// </summary>
    public void UpdateBusinessInfo(BusinessInfo businessInfo)
    {
        _businessInfo = businessInfo ?? BusinessInfo.Empty;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update settlement configuration.
    /// VI: Cập nhật cấu hình thanh toán.
    /// </summary>
    public void UpdateSettlementConfig(SettlementConfig config)
    {
        _settlementConfig = config ?? SettlementConfig.Default;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Submit verification documents.
    /// VI: Nộp tài liệu xác minh.
    /// </summary>
    public void SubmitForVerification()
    {
        if (!_businessInfo.IsCompleteForVerification)
            throw new DomainException("Business information is incomplete for verification");

        _verificationStatus = VerificationStatus.Pending;
        VerificationStatusId = VerificationStatus.Pending.Id;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new MerchantVerificationSubmittedDomainEvent(this));
    }

    /// <summary>
    /// EN: Approve merchant and activate account.
    /// VI: Phê duyệt merchant và kích hoạt tài khoản.
    /// </summary>
    /// <param name="approvedBy">Admin user ID who approved / ID admin phê duyệt</param>
    public void Approve(Guid approvedBy)
    {
        if (!_status.CanBeActivated)
            throw new DomainException($"Cannot approve merchant with status {_status.Name}");

        _status = MerchantStatus.Active;
        StatusId = MerchantStatus.Active.Id;
        _verificationStatus = VerificationStatus.Verified;
        VerificationStatusId = VerificationStatus.Verified.Id;
        VerifiedAt = DateTime.UtcNow;
        VerifiedBy = approvedBy;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new MerchantApprovedDomainEvent(this, approvedBy));
    }

    /// <summary>
    /// EN: Suspend merchant.
    /// VI: Tạm ngưng merchant.
    /// </summary>
    /// <param name="reason">Reason for suspension / Lý do tạm ngưng</param>
    public void Suspend(string reason)
    {
        if (!_status.CanBeSuspended)
            throw new DomainException($"Cannot suspend merchant with status {_status.Name}");

        _status = MerchantStatus.Suspended;
        StatusId = MerchantStatus.Suspended.Id;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new MerchantSuspendedDomainEvent(this, reason));
    }

    /// <summary>
    /// EN: Reactivate suspended merchant.
    /// VI: Kích hoạt lại merchant bị tạm ngưng.
    /// </summary>
    public void Reactivate()
    {
        if (_status != MerchantStatus.Suspended)
            throw new DomainException("Can only reactivate suspended merchants");

        _status = MerchantStatus.Active;
        StatusId = MerchantStatus.Active.Id;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Ban merchant permanently.
    /// VI: Cấm merchant vĩnh viễn.
    /// </summary>
    /// <param name="reason">Reason for ban / Lý do cấm</param>
    public void Ban(string reason)
    {
        if (_status == MerchantStatus.Banned)
            throw new DomainException("Merchant is already banned");

        _status = MerchantStatus.Banned;
        StatusId = MerchantStatus.Banned.Id;
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new MerchantBannedDomainEvent(this, reason));
    }

    /// <summary>
    /// EN: Update subscription plan.
    /// VI: Cập nhật gói đăng ký.
    /// </summary>
    /// <param name="planId">Plan ID (0=Starter, 1=Growth, 2=Pro, 3=Enterprise) / ID gói (0=Starter, 1=Growth, 2=Pro, 3=Enterprise)</param>
    public void UpdateSubscriptionPlan(int planId)
    {
        if (planId < 0 || planId > 3)
            throw new DomainException("Invalid subscription plan ID. Must be 0-3.");

        _subscriptionPlanId = planId;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Soft delete merchant.
    /// VI: Xóa mềm merchant.
    /// </summary>
    public void Delete()
    {
        if (_isDeleted)
            throw new DomainException("Merchant is already deleted");

        _isDeleted = true;
        _updatedAt = DateTime.UtcNow;
    }
}
