/**
 * Pure 3×3 board geometry shared by every board renderer (phone, TV, host). Line ids follow the
 * engine's LINES order: 0-2 rows, 3-5 columns, 6-7 diagonals.
 */
import { LINES } from '@pintrush/engine';

export const LINE_NAMES: readonly string[] = [
  'Top row',
  'Middle row',
  'Bottom row',
  'Left column',
  'Middle column',
  'Right column',
  'Diagonal ↘',
  'Diagonal ↙',
];

const CELL_NAMES = ['top left', 'top middle', 'top right', 'middle left', 'centre', 'middle right', 'bottom left', 'bottom middle', 'bottom right'];

/** "top left", "centre", … for screen-reader labels. */
export function cellName(position: number): string {
  return CELL_NAMES[position] ?? `square ${position + 1}`;
}

/** Positions covered by any of the given lines. */
export function cellsInLines(lines: readonly number[]): Set<number> {
  const cells = new Set<number>();
  for (const line of lines) for (const p of LINES[line] ?? []) cells.add(p);
  return cells;
}

/**
 * Line endpoints in a 0-100 box laid over the grid (cell centres sit at ~16.5 / 50 / 83.5 with the
 * board's gap); lines overshoot the end cells slightly so they read as a strike-through.
 */
export function lineCoordinates(line: number): [x1: number, y1: number, x2: number, y2: number] | null {
  const c = [16.5, 50, 83.5] as const;
  const lo = 5;
  const hi = 95;
  if (line >= 0 && line <= 2) return [lo, c[line]!, hi, c[line]!];
  if (line >= 3 && line <= 5) return [c[line - 3]!, lo, c[line - 3]!, hi];
  if (line === 6) return [7, 7, 93, 93];
  if (line === 7) return [93, 7, 7, 93];
  return null;
}

export interface TileLike {
  position: number;
  category: string;
  activated: boolean;
}

/** The unactivated tile whose category matches the upcoming question (one per category on a board). */
export function tileForCategory(tiles: readonly TileLike[], category: string): number | null {
  return tiles.find((t) => t.category === category && !t.activated)?.position ?? null;
}

/** Positions a player may pick (wildcard claim, Category Swap): every unactivated tile. */
export function openPositions(tiles: readonly TileLike[]): number[] {
  return tiles.filter((t) => !t.activated).map((t) => t.position);
}

/** Lines still missing exactly one tile — the squares that would complete a line right now. */
export function nearlyCompleteLines(tiles: readonly TileLike[]): { line: number; missing: number }[] {
  const lit = new Set(tiles.filter((t) => t.activated).map((t) => t.position));
  const result: { line: number; missing: number }[] = [];
  LINES.forEach((cells, line) => {
    const missing = cells.filter((p) => !lit.has(p));
    if (missing.length === 1) result.push({ line, missing: missing[0]! });
  });
  return result;
}

/**
 * Two-tile picker used by Category Swap: tapping a selected tile clears it, a third pick replaces
 * the second so the player can change their mind without a reset button.
 */
export function toggleSelection(selected: readonly number[], position: number, max = 2): number[] {
  if (selected.includes(position)) return selected.filter((p) => p !== position);
  if (selected.length < max) return [...selected, position];
  return [...selected.slice(0, max - 1), position];
}
