import type { Logger } from '@core/shared/domain/Logger';
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
import { User } from '../../domain/entities/User';
import { StoredUser, type UserRepository } from '../../domain/repositories/UserRepository';
import { GetCurrentSessionUseCase } from './GetCurrentSessionUseCase';

describe('GetCurrentSessionUseCase', () => {
  let useCase: GetCurrentSessionUseCase;
  let mockUserRepo: {
    findByEmail: Mock;
    findById: Mock;
    create: Mock;
    update: Mock;
    emailExists: Mock;
  };
  let logger: Logger;

  beforeEach(() => {
    mockUserRepo = {
      findByEmail: vi.fn(),
      findById: vi.fn(),
      create: vi.fn(),
      update: vi.fn(),
      emailExists: vi.fn(),
    };
    logger = {
      debug: vi.fn(),
      info: vi.fn(),
      warn: vi.fn(),
      error: vi.fn(),
    } as unknown as Logger;
    useCase = new GetCurrentSessionUseCase(
      mockUserRepo as UserRepository,
      logger,
    );
  });

  it('should return User when user exists', async () => {
    const userId = 'user-123';
    const storedUser: StoredUser = {
      id: userId,
      email: 'test@example.com',
      displayName: 'John Smith',
      passwordHash: 'hash',
      primaryDriverId: 'driver-123',
      createdAt: new Date(),
    };
    mockUserRepo.findById.mockResolvedValue(storedUser);

    const result = await useCase.execute({ userId });

    expect(mockUserRepo.findById).toHaveBeenCalledWith(userId);
    expect(result.isOk()).toBe(true);
    const sessionResult = result.unwrap();
    expect(sessionResult.user).toBeInstanceOf(User);
    expect(sessionResult.user.getId().value).toBe(userId);
    expect(sessionResult.user.getDisplayName()).toBe('John Smith');
  });

  it('should return error when user does not exist', async () => {
    const userId = 'user-123';
    mockUserRepo.findById.mockResolvedValue(null);

    const result = await useCase.execute({ userId });

    expect(mockUserRepo.findById).toHaveBeenCalledWith(userId);
    expect(result.isErr()).toBe(true);
    expect(result.unwrapErr().code).toBe('USER_NOT_FOUND');
  });
});