// src/tests/integration/db.integration.test.ts
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as db from '../../services/db/index.db';
import * as bcrypt from 'bcrypt';
import { logger } from '../../services/logger.server';
import type { UserProfile } from '../../types';
import { cleanupDb } from '../utils/cleanup';
import { poll } from '../utils/poll';

describe('Database Service Integration Tests', () => {
  let testUser: UserProfile;
  let testUserEmail: string;

  beforeEach(async () => {
    // Arrange: Use a unique email for each test run to ensure isolation.
    testUserEmail = `test.user-${Date.now()}@example.com`;
    const password = 'password123';
    const fullName = 'Test User';
    const saltRounds = 10;
    const passwordHash = await bcrypt.hash(password, saltRounds);

    // Act: Call the createUser function
    testUser = await db.userRepo.createUser(
      testUserEmail,
      passwordHash,
      { full_name: fullName },
      logger,
    );

    // Poll to ensure the user record is findable before tests run.
    await poll(
      () => db.userRepo.findUserByEmail(testUserEmail, logger),
      (foundUser) => !!foundUser,
      { timeout: 5000, interval: 500, description: `user ${testUserEmail} to be findable` },
    );
  });

  afterEach(async () => {
    // Ensure the created user is cleaned up after each test.
    if (testUser?.user.user_id) {
      await cleanupDb({ userIds: [testUser.user.user_id] });
    }
  });

  it('should create a new user and have a corresponding profile', async () => {
    // Assert: Check that the user was created with the correct details
    expect(testUser).toBeDefined();
    expect(testUser.user.email).toBe(testUserEmail);
    expect(testUser.user.user_id).toBeTypeOf('string');

    // Also, verify the profile was created by the trigger
    const profile = await db.userRepo.findUserProfileById(testUser.user.user_id, logger);
    expect(profile).toBeDefined();
    expect(profile?.full_name).toBe('Test User');
  });

  it('should be able to find the created user by email', async () => {
    // Act: Try to find the user we just created
    const foundUser = await db.userRepo.findUserByEmail(testUserEmail, logger);

    // Assert: Check that the found user matches the created user
    expect(foundUser).toBeDefined();
    expect(foundUser?.user_id).toBe(testUser.user.user_id);
    expect(foundUser?.email).toBe(testUserEmail);
  });
});
