import { describe, it, expect, vi, beforeEach } from 'vitest';

vi.mock('../../src/services/fsScanner', () => ({
  scanDirectory: vi.fn(),
}));

vi.mock('../../src/services/checksumService', () => ({
  computeHashes: vi.fn(),
}));

vi.mock('../../src/plugins/prisma', () => ({
  default: {
    game: { findUnique: vi.fn(), create: vi.fn() },
    romFile: { upsert: vi.fn() },
  },
}));

import { importDirectory, createSlug } from '../../src/services/importService';
import { scanDirectory } from '../../src/services/fsScanner';
import { computeHashes } from '../../src/services/checksumService';
import prisma from '../../src/plugins/prisma';

describe('services/importService', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('exporta createSlug e importDirectory', () => {
    expect(typeof createSlug).toBe('function');
    expect(typeof importDirectory).toBe('function');
  });

  it('cuando hay un archivo y persist:true crea Game y hace romFile.upsert, y devuelve resumen', async () => {
    const files = [
      {
        path: '/roms/Sonic.bin',
        filename: 'Sonic.bin',
        name: 'Sonic.bin',
        size: 123,
        format: 'bin',
        isArchive: false,
      },
    ];

    const hashes = { size: 123, md5: 'md5-abc', sha1: 'sha1-abc', crc32: 'abcd' };

    (scanDirectory as unknown as vi.Mock).mockResolvedValue(files);
    (computeHashes as unknown as vi.Mock).mockResolvedValue(hashes);

    (prisma.game.findUnique as unknown as vi.Mock).mockResolvedValue(null);
    (prisma.game.create as unknown as vi.Mock).mockResolvedValue({
      id: 77,
      title: 'Sonic',
      slug: 'sonic',
    });
    (prisma.romFile.upsert as unknown as vi.Mock).mockResolvedValue({ id: 1 });

    const summary = await importDirectory({ dir: '/roms', persist: true });

    expect((scanDirectory as unknown as vi.Mock).mock.calls[0][0]).toBe('/roms');
    expect((computeHashes as unknown as vi.Mock).mock.calls[0][0]).toBe('/roms/Sonic.bin');

    expect((prisma.game.findUnique as unknown as vi.Mock).mock.calls[0][0]).toEqual({
      where: { slug: 'sonic' },
    });
    expect((prisma.game.create as unknown as vi.Mock).mock.calls[0][0]).toEqual({
      data: { title: 'Sonic', slug: 'sonic' },
    });

    expect((prisma.romFile.upsert as unknown as vi.Mock).mock.calls.length).toBe(1);
    const upsertArgs = (prisma.romFile.upsert as unknown as vi.Mock).mock.calls[0][0];
    expect(upsertArgs.where).toEqual({ checksum: 'md5-abc' });
    expect(upsertArgs.create.gameId).toBe(77);
    expect(upsertArgs.create.filename).toBe('Sonic.bin');
    expect(upsertArgs.create.hashes).toBe(JSON.stringify(hashes));

    expect(summary).toEqual({ processed: 1, createdCount: 1, upserted: 1 });
  });
});
