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

vi.mock('../../lib/sql.js', () => ({ sql: vi.fn() }));

import { sql } from '../../lib/sql.js';
import listHandler from '../../pages/api/public/games/index.js';
import itemHandler from '../../pages/api/public/games/[id].js';

function createRes() {
  const res = {
    statusCode: 200,
    body: null,
    status(code) {
      res.statusCode = code;
      return res;
    },
    json(data) {
      res.body = data;
      return res;
    },
  };
  return res;
}

describe('/api/public/games', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    sql.mockResolvedValue({ rows: [] });
  });

  it('rejects non-GET methods', async () => {
    const res = createRes();

    await listHandler({ method: 'POST' }, res);

    expect(res.statusCode).toBe(405);
    expect(sql).not.toHaveBeenCalled();
  });

  it('lists public games with author and card counts', async () => {
    sql.mockResolvedValueOnce({
      rows: [{ id: 9, name: 'Aetherfall', author: 'rstillw', card_count: 4 }],
    });
    const res = createRes();

    await listHandler({ method: 'GET' }, res);

    expect(res.statusCode).toBe(200);
    expect(res.body.games).toHaveLength(1);
    const listed = sql.mock.calls[0][0].join('');
    expect(listed).toContain('is_public = true');
  });
});

describe('/api/public/games/[id]', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    sql.mockResolvedValue({ rows: [] });
  });

  it('rejects invalid ids', async () => {
    const res = createRes();

    await itemHandler({ method: 'GET', query: { id: 'abc' } }, res);

    expect(res.statusCode).toBe(400);
  });

  it('404s private or missing games', async () => {
    sql.mockResolvedValueOnce({ rows: [] }); // public filter misses
    const res = createRes();

    await itemHandler({ method: 'GET', query: { id: '9' } }, res);

    expect(res.statusCode).toBe(404);
  });

  it('returns the game and its designs with resolved frames', async () => {
    sql
      .mockResolvedValueOnce({
        rows: [{ id: 9, name: 'Aetherfall', author: 'rstillw' }],
      })
      .mockResolvedValueOnce({
        rows: [
          {
            id: 3,
            name: 'Stormsage',
            frame_pk: 2,
            frame_name: 'Molten',
            frame_palette: { outer: '#111111' },
            frame_texture: null,
          },
        ],
      });
    const res = createRes();

    await itemHandler({ method: 'GET', query: { id: '9' } }, res);

    expect(res.statusCode).toBe(200);
    expect(res.body.game.name).toBe('Aetherfall');
    expect(res.body.designs[0].custom_frame.name).toBe('Molten');
    expect(res.body.designs[0].frame_pk).toBeUndefined();
  });
});
