import { User } from '@core/identity/domain/entities/User';
import { UserId } from '@core/identity/domain/value-objects/UserId';
import type { Logger } from '@core/shared/domain/Logger';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { InMemoryPasswordHashingService } from '../../services/InMemoryPasswordHashingService';
import { InMemoryAuthRepository } from './InMemoryAuthRepository';
import { InMemoryUserRepository } from './InMemoryUserRepository';

describe('InMemoryAuthRepository', () => {
  let mockLogger: Logger;

  beforeEach(() => {
    mockLogger = {
      debug: vi.fn(),
      info: vi.fn(),
      warn: vi.fn(),
      error: vi.fn(),
    } as unknown as Logger;
  });

  it('creates and verifies a user password', async () => {
    const userRepo = new InMemoryUserRepository(mockLogger);
    const passwordService = new InMemoryPasswordHashingService();
    const authRepo = new InMemoryAuthRepository(userRepo, passwordService, mockLogger);

    const user = User.create({
      id: UserId.fromString('user-1'),
      displayName: 'John Smith',
      email: 'test@example.com',
    });

    const created = await authRepo.create(user, 'password123');
    expect(created.getEmail()).toBe('test@example.com');

    expect(await authRepo.userExists('test@example.com')).toBe(true);

    const ok = await authRepo.verifyPassword('test@example.com', 'password123');
    expect(ok).not.toBeNull();
    expect(ok?.getId().value).toBe('user-1');

    const bad = await authRepo.verifyPassword('test@example.com', 'wrong');
    expect(bad).toBeNull();
  });

  it('save updates existing user', async () => {
    const userRepo = new InMemoryUserRepository(mockLogger);
    const passwordService = new InMemoryPasswordHashingService();
    const authRepo = new InMemoryAuthRepository(userRepo, passwordService, mockLogger);

    const user = User.create({
      id: UserId.fromString('user-2'),
      displayName: 'Jane Smith',
      email: 'two@example.com',
    });

    await authRepo.create(user, 'pw');

    const updated = User.create({
      id: UserId.fromString('user-2'),
      displayName: 'Jane Smith Updated',
      email: 'two@example.com',
    });

    await authRepo.save(updated);

    const stored = await userRepo.findById('user-2');
    expect(stored?.displayName).toBe('Jane Smith Updated');
  });
});
