import { ConflictException } from '@nestjs/common';
import { Kysely, PostgresDialect } from 'kysely';
import { Pool } from 'pg';
import type { Database } from '../../database/src';
import { TripsRepository } from '../src/trips.repository';
import { TripsService } from '../src/trips.service';
import { UsersRepository } from '../../users/src/users.repository';

describe('Trip optimistic locking (integration)', () => {
  let db: Kysely<Database>;
  let tripsService: TripsService;
  let ownerId: string;

  beforeAll(async () => {
    db = new Kysely<Database>({
      dialect: new PostgresDialect({
        pool: new Pool({ connectionString: process.env.DATABASE_URL }),
      }),
    });
    const usersRepository = new UsersRepository(db);
    const owner = await usersRepository.upsertByExternalSubjectId(
      'optimistic-locking-test-sub',
      {
        email: 'owner@example.test',
        displayName: 'Owner',
      },
    );
    ownerId = owner.id;
    tripsService = new TripsService(new TripsRepository(db));
  });

  afterAll(async () => {
    await db.destroy();
  });

  it('rejects a second update that used a stale version', async () => {
    const trip = await tripsService.createTrip(ownerId, {
      name: 'Slovenia 2027',
    });
    expect(trip.version).toBe(1);

    const firstUpdate = await tripsService.updateTrip(trip.id, {
      name: 'Slovenia 2027 (v2)',
      version: 1,
    });
    expect(firstUpdate.version).toBe(2);

    await expect(
      tripsService.updateTrip(trip.id, {
        name: 'Conflicting concurrent edit',
        version: 1,
      }),
    ).rejects.toThrow(ConflictException);
  });
});
