using Microsoft.AspNetCore.Identity;
using IamService.Domain.SeedWork;

namespace IamService.Domain.AggregatesModel.UserAggregate;

/// <summary>
/// EN: Application user entity extending ASP.NET Core Identity.
/// VI: Entity user mở rộng từ ASP.NET Core Identity.
/// </summary>
public class ApplicationUser : IdentityUser<Guid>, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private string _firstName = null!;
    private string _lastName = null!;
    private UserStatus _status = null!;
    private DateTime _createdAt;
    private DateTime? _lastLoginAt;
    
    private readonly List<IDomainEvent> _domainEvents = [];

    /// <summary>
    /// EN: User's first name.
    /// VI: Tên người dùng.
    /// </summary>
    public string FirstName => _firstName;

    /// <summary>
    /// EN: User's last name.
    /// VI: Họ người dùng.
    /// </summary>
    public string LastName => _lastName;

    /// <summary>
    /// EN: User's full name.
    /// VI: Tên đầy đủ người dùng.
    /// </summary>
    public string FullName => $"{_firstName} {_lastName}";

    /// <summary>
    /// EN: Current status.
    /// VI: Trạng thái hiện tại.
    /// </summary>
    public UserStatus 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: Creation timestamp.
    /// VI: Thời gian tạo.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: Last login timestamp.
    /// VI: Thời gian đăng nhập cuối.
    /// </summary>
    public DateTime? LastLoginAt => _lastLoginAt;

    /// <summary>
    /// EN: Domain events.
    /// VI: Domain events.
    /// </summary>
    public IReadOnlyCollection<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();

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

    /// <summary>
    /// EN: Create a new user with required information.
    /// VI: Tạo user mới với thông tin bắt buộc.
    /// </summary>
    public ApplicationUser(string email, string firstName, string lastName) : this()
    {
        if (string.IsNullOrWhiteSpace(email))
            throw new ArgumentException("Email cannot be empty", nameof(email));
        if (string.IsNullOrWhiteSpace(firstName))
            throw new ArgumentException("First name cannot be empty", nameof(firstName));
        if (string.IsNullOrWhiteSpace(lastName))
            throw new ArgumentException("Last name cannot be empty", nameof(lastName));

        Id = Guid.NewGuid();
        Email = email;
        UserName = email;
        NormalizedEmail = email.ToUpperInvariant();
        NormalizedUserName = email.ToUpperInvariant();
        _firstName = firstName;
        _lastName = lastName;
        _status = UserStatus.Active;
        StatusId = UserStatus.Active.Id;
        _createdAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update user profile.
    /// VI: Cập nhật thông tin user.
    /// </summary>
    public void UpdateProfile(string firstName, string lastName)
    {
        if (string.IsNullOrWhiteSpace(firstName))
            throw new ArgumentException("First name cannot be empty", nameof(firstName));
        if (string.IsNullOrWhiteSpace(lastName))
            throw new ArgumentException("Last name cannot be empty", nameof(lastName));

        _firstName = firstName;
        _lastName = lastName;
    }

    /// <summary>
    /// EN: Record successful login.
    /// VI: Ghi nhận đăng nhập thành công.
    /// </summary>
    public void RecordLogin()
    {
        _lastLoginAt = DateTime.UtcNow;
        AccessFailedCount = 0;
    }

    /// <summary>
    /// EN: Lock the user account.
    /// VI: Khóa tài khoản user.
    /// </summary>
    public void Lock(DateTimeOffset? until = null)
    {
        _status = UserStatus.Locked;
        StatusId = UserStatus.Locked.Id;
        LockoutEnd = until ?? DateTimeOffset.MaxValue;
    }

    /// <summary>
    /// EN: Unlock the user account.
    /// VI: Mở khóa tài khoản user.
    /// </summary>
    public void Unlock()
    {
        _status = UserStatus.Active;
        StatusId = UserStatus.Active.Id;
        LockoutEnd = null;
        AccessFailedCount = 0;
    }

    /// <summary>
    /// EN: Activate the user account.
    /// VI: Kích hoạt tài khoản user.
    /// </summary>
    public void Activate()
    {
        _status = UserStatus.Active;
        StatusId = UserStatus.Active.Id;
    }

    /// <summary>
    /// EN: Disable the user account.
    /// VI: Vô hiệu hóa tài khoản user.
    /// </summary>
    public void Disable()
    {
        _status = UserStatus.Disabled;
        StatusId = UserStatus.Disabled.Id;
    }

    /// <summary>
    /// EN: Add domain event.
    /// VI: Thêm domain event.
    /// </summary>
    public void AddDomainEvent(IDomainEvent domainEvent)
    {
        _domainEvents.Add(domainEvent);
    }

    /// <summary>
    /// EN: Clear domain events.
    /// VI: Xóa domain events.
    /// </summary>
    public void ClearDomainEvents()
    {
        _domainEvents.Clear();
    }
}
