import fs from 'fs';
import os from 'os';
import path from 'path';
import { execSync } from 'child_process';
import { describe, beforeAll, afterAll, it, expect } from 'vitest';
// Import PrismaClient dynamically after running `prisma generate`
// to allow the test setup to run `prisma generate`/`prisma migrate` first.

// Nota: Estos tests siguen TDD. Al principio deben FALLAR hasta que se creen migraciones.

describe('Prisma / Game model', () => {
  const tmpDir = os.tmpdir();
  const dbFile = path.join(
    tmpDir,
    `quasar-test-${Date.now()}-${Math.random().toString(36).slice(2)}.db`
  );
  const databaseUrl = `file:${dbFile}`;
  let prisma: any;

  beforeAll(async () => {
    // Asegurarse de que la DB de prueba no exista antes de empezar
    try {
      fs.unlinkSync(dbFile);
    } catch (e) {
      /* ignore */
    }

    // Apuntar Prisma a la DB temporal
    process.env.DATABASE_URL = databaseUrl;

    // Ejecutar migraciones contra la DB de prueba
    // Esto fallará si no hay migraciones: esperado en la fase TDD inicial
    execSync('yarn prisma migrate deploy --schema=./prisma/schema.prisma', {
      stdio: 'inherit',
      cwd: path.resolve(__dirname, '..', '..'),
    });

    // Intentar requerir el cliente generado; si no existe, intentar generarlo (fallback)
    let GeneratedPrismaClient;
    try {
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      GeneratedPrismaClient = require('@prisma/client').PrismaClient;
    } catch (e) {
      try {
        execSync('yarn prisma generate --schema=./prisma/schema.prisma', {
          stdio: 'inherit',
          cwd: path.resolve(__dirname, '..', '..'),
        });
        // eslint-disable-next-line @typescript-eslint/no-var-requires
        GeneratedPrismaClient = require('@prisma/client').PrismaClient;
      } catch (err) {
        // Si generation falla (por ejemplo PnP), reintentar require para mostrar mejor error
        // eslint-disable-next-line @typescript-eslint/no-var-requires
        GeneratedPrismaClient = require('@prisma/client').PrismaClient;
      }
    }
    prisma = new GeneratedPrismaClient();
    await prisma.$connect();
  });

  afterAll(async () => {
    if (prisma) {
      await prisma.$disconnect();
    }
    try {
      fs.unlinkSync(dbFile);
    } catch (e) {
      /* ignore */
    }
  });

  it('can create a Game and read title/slug', async () => {
    const created = await prisma.game.create({ data: { title: 'Test Game', slug: 'test-game' } });
    const found = await prisma.game.findUnique({ where: { id: created.id } });
    expect(found).toBeTruthy();
    expect(found?.title).toBe('Test Game');
    expect(found?.slug).toBe('test-game');
  });

  it('enforces unique slug constraint', async () => {
    const slug = `unique-${Date.now()}`;
    await prisma.game.create({ data: { title: 'G1', slug } });

    let threw = false;
    try {
      await prisma.game.create({ data: { title: 'G2', slug } });
    } catch (err) {
      threw = true;
    }
    expect(threw).toBe(true);
  });
});
