import { describe, expect, it } from 'vitest';
import { LINES } from '@pintrush/engine';
import {
  LINE_NAMES,
  cellName,
  cellsInLines,
  lineCoordinates,
  nearlyCompleteLines,
  openPositions,
  tileForCategory,
  toggleSelection,
} from '../../components/game/board-model';

const cats = ['music', 'history', 'pop', 'sports', 'geo', 'food', 'film', 'general', 'science'];
const tiles = (lit: number[]) => cats.map((category, position) => ({ position, category, activated: lit.includes(position) }));

describe('board model', () => {
  it('highlights every cell of completed lines', () => {
    expect([...cellsInLines([0])].sort()).toEqual([0, 1, 2]);
    expect([...cellsInLines([0, 4, 6])].sort()).toEqual([0, 1, 2, 4, 7, 8]);
    expect(cellsInLines([]).size).toBe(0);
  });

  it('draws one segment per engine line, inside the board box', () => {
    expect(LINE_NAMES).toHaveLength(LINES.length);
    for (let line = 0; line < LINES.length; line++) {
      const c = lineCoordinates(line);
      expect(c).not.toBeNull();
      for (const v of c!) {
        expect(v).toBeGreaterThanOrEqual(0);
        expect(v).toBeLessThanOrEqual(100);
      }
    }
    expect(lineCoordinates(0)).toEqual([5, 16.5, 95, 16.5]); // top row is horizontal
    expect(lineCoordinates(4)).toEqual([50, 5, 50, 95]); // middle column is vertical
    expect(lineCoordinates(8)).toBeNull();
  });

  it('finds the up-next tile and the open squares', () => {
    expect(tileForCategory(tiles([]), 'geo')).toBe(4);
    expect(tileForCategory(tiles([4]), 'geo')).toBeNull();
    expect(tileForCategory(tiles([]), 'unknown')).toBeNull();
    expect(openPositions(tiles([0, 1, 2, 4]))).toEqual([3, 5, 6, 7, 8]);
  });

  it('lists the squares that would complete a line', () => {
    expect(nearlyCompleteLines(tiles([0, 1]))).toEqual([{ line: 0, missing: 2 }]);
    expect(nearlyCompleteLines(tiles([0, 4]))).toEqual([{ line: 6, missing: 8 }]);
    expect(nearlyCompleteLines(tiles([]))).toEqual([]);
  });

  it('keeps a two-tile selection for Category Swap', () => {
    expect(toggleSelection([], 3)).toEqual([3]);
    expect(toggleSelection([3], 5)).toEqual([3, 5]);
    expect(toggleSelection([3, 5], 5)).toEqual([3]);
    expect(toggleSelection([3, 5], 7)).toEqual([3, 7]);
    expect(toggleSelection([3], 7, 1)).toEqual([7]);
  });

  it('names cells for screen readers', () => {
    expect(cellName(0)).toBe('top left');
    expect(cellName(4)).toBe('centre');
    expect(cellName(8)).toBe('bottom right');
  });
});
