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

import { buildCatalogSyncQueue, runUnifiedCatalogSync } from '../../lib/card-import/sync-catalog.js';
import { runBulkMtgSync } from '../../lib/card-import/bulk-sync.js';
import { runBulkPokemonSync } from '../../lib/card-import/pokemon-bulk.js';
import { runBulkLorcanaSync } from '../../lib/card-import/lorcana-bulk.js';

vi.mock('../../lib/card-import/bulk-sync.js', () => ({
  runBulkMtgSync: vi.fn(),
}));

vi.mock('../../lib/card-import/pokemon-bulk.js', () => ({
  runBulkPokemonSync: vi.fn(),
}));

vi.mock('../../lib/card-import/lorcana-bulk.js', () => ({
  runBulkLorcanaSync: vi.fn(),
}));

vi.mock('../../lib/sql.js', () => ({
  sql: vi.fn(() => Promise.resolve({ rows: [] })),
}));

describe('buildCatalogSyncQueue', () => {
  it('merges MTG and Pokémon missing sets by release date, newest first', () => {
    const queue = buildCatalogSyncQueue(
      [
        { code: 'fin', name: 'Final Fantasy', releasedAt: '2026-05-01' },
        { code: 'dsk', name: 'Duskmourn', releasedAt: '2024-09-27' },
      ],
      [
        { id: 'sv10', name: 'Perfect Order', releasedAt: '2026-03-27' },
        { id: 'sv9', name: 'Journey Together', releasedAt: '2025-03-28' },
      ],
      3
    );

    expect(queue).toEqual([
      {
        game: 'mtg',
        setCode: 'fin',
        name: 'Final Fantasy',
        releasedAt: '2026-05-01',
      },
      {
        game: 'pokemon',
        setCode: 'sv10',
        name: 'Perfect Order',
        releasedAt: '2026-03-27',
      },
      {
        game: 'pokemon',
        setCode: 'sv9',
        name: 'Journey Together',
        releasedAt: '2025-03-28',
      },
    ]);
  });
});

describe('runUnifiedCatalogSync', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('runs all three games and isolates per-game failures', async () => {
    runBulkMtgSync.mockResolvedValue({ mode: 'bulk', upserted: 36000, errors: 0 });
    runBulkPokemonSync.mockRejectedValue(new Error('Pokemon API down'));
    runBulkLorcanaSync.mockResolvedValue({ mode: 'bulk', upserted: 2283, errors: 0 });

    const summary = await runUnifiedCatalogSync();

    expect(summary.mode).toBe('unified');
    expect(summary.mtg.upserted).toBe(36000);
    expect(summary.pokemon.error).toBe('Pokemon API down');
    expect(summary.lorcana.upserted).toBe(2283);
    expect(summary.errors).toEqual([{ game: 'pokemon', message: 'Pokemon API down' }]);
    expect(summary.durationMs).toBeGreaterThanOrEqual(0);
    expect(runBulkMtgSync).toHaveBeenCalledOnce();
    expect(runBulkPokemonSync).toHaveBeenCalledOnce();
    expect(runBulkLorcanaSync).toHaveBeenCalledOnce();
  });
});
