using CashLineERP.Domain.Common;

namespace CashLineERP.Domain.Identity;

public sealed class ApplicationUser : Entity
{
    public long Id { get; private set; }

    public long? BranchId { get; private set; }

    public string LoginName { get; private set; } = string.Empty;

    public string DisplayName { get; private set; } = string.Empty;

    public string? Email { get; private set; }

    public string UserTypeCode { get; private set; } = string.Empty;

    public string PasswordHash { get; private set; } = string.Empty;

    public long? PartyId { get; private set; }

    public bool IsActive { get; private set; } = true;

    public bool IsLocked { get; private set; }

    public List<UserRole> Roles { get; private set; } = [];

    public List<UserFunctionAssignment> FunctionAssignments { get; private set; } = [];

    public ApplicationUser(
        long id,
        string loginName,
        string displayName,
        string userTypeCode,
        string passwordHash,
        string? email = null,
        long? branchId = null,
        long? partyId = null)
    {
        Id = id;
        LoginName = loginName;
        DisplayName = displayName;
        UserTypeCode = userTypeCode;
        PasswordHash = passwordHash;
        Email = email;
        BranchId = branchId;
        PartyId = partyId;
    }

    private ApplicationUser()
    {
    }

    public void AssignRole(UserRole role)
    {
        if (Roles.Any(existingRole => existingRole.RoleId == role.RoleId && existingRole.IsActive))
        {
            return;
        }

        Roles.Add(role);
    }

    public void Lock() => IsLocked = true;

    public void Unlock() => IsLocked = false;

    public void Deactivate() => IsActive = false;

    public void Activate() => IsActive = true;

    public void ChangeProfile(string displayName, string? email, long? branchId, long? partyId)
    {
        if (string.IsNullOrWhiteSpace(displayName))
        {
            throw new InvalidOperationException("User display name is required.");
        }

        DisplayName = displayName.Trim();
        Email = string.IsNullOrWhiteSpace(email) ? null : email.Trim();
        BranchId = branchId;
        PartyId = partyId;
    }

    public void ChangePasswordHash(string passwordHash)
    {
        if (string.IsNullOrWhiteSpace(passwordHash))
        {
            throw new InvalidOperationException("User password hash is required.");
        }

        PasswordHash = passwordHash.Trim();
    }
}
