import { describe, it, expect, beforeEach } from 'vitest';
import { UserEntity } from '../entities/user.entity';
import { UserRegisteredEvent } from '../events/user-registered.event';
import { Email } from '../value-objects/email.vo';
import { HashedPassword } from '../value-objects/hashed-password.vo';
import { Phone } from '../value-objects/phone.vo';

describe('UserEntity', () => {
  let phone: Phone;
  let passwordHash: HashedPassword;

  beforeEach(async () => {
    phone = Phone.create('0912345678').unwrap();
    passwordHash = (await HashedPassword.fromPlain('Password123')).unwrap();
  });

  it('should create a new user with domain event', () => {
    const user = UserEntity.createNew('user-1', phone, 'Nguyễn Văn A', passwordHash);

    expect(user.id).toBe('user-1');
    expect(user.phone.value).toBe('+84912345678');
    expect(user.fullName).toBe('Nguyễn Văn A');
    expect(user.role).toBe('BUYER');
    expect(user.kycStatus).toBe('NONE');
    expect(user.isActive).toBe(true);
    expect(user.email).toBeNull();

    const events = user.domainEvents;
    expect(events).toHaveLength(1);
    expect(events[0]).toBeInstanceOf(UserRegisteredEvent);
    expect((events[0] as UserRegisteredEvent).phone).toBe('+84912345678');
  });

  it('should create a user with email', () => {
    const email = Email.create('test@example.com').unwrap();
    const user = UserEntity.createNew('user-2', phone, 'Trần Thị B', passwordHash, email);

    expect(user.email?.value).toBe('test@example.com');
  });

  it('should update KYC status and emit UserKycUpdatedEvent', () => {
    const user = UserEntity.createNew('user-3', phone, 'Lê Văn C', passwordHash);
    user.clearDomainEvents();
    user.updateKycStatus('PENDING', { idCard: '123456789' });

    expect(user.kycStatus).toBe('PENDING');
    expect(user.kycData).toEqual({ idCard: '123456789' });

    const events = user.domainEvents;
    expect(events).toHaveLength(1);
    expect(events[0].eventName).toBe('user.kyc_updated');
  });

  it('should deactivate user and emit UserDeactivatedEvent', () => {
    const user = UserEntity.createNew('user-4', phone, 'Phạm Thị D', passwordHash);
    user.clearDomainEvents();
    expect(user.isActive).toBe(true);

    user.deactivate();
    expect(user.isActive).toBe(false);

    const events = user.domainEvents;
    expect(events).toHaveLength(1);
    expect(events[0].eventName).toBe('user.deactivated');
  });

  it('should clear domain events', () => {
    const user = UserEntity.createNew('user-5', phone, 'Hoàng Văn E', passwordHash);
    expect(user.domainEvents).toHaveLength(1);

    const cleared = user.clearDomainEvents();
    expect(cleared).toHaveLength(1);
    expect(user.domainEvents).toHaveLength(0);
  });
});
