"use client";

import { useState, useEffect, useCallback, useRef } from "react";
import { TangoPuzzle, Cell } from "@/lib/generators/tango";
import WinBanner from "./WinBanner";

interface Props {
  puzzle: TangoPuzzle;
  date: string;
  onSolve?: (elapsed: number) => void;
}

const MAX_CELL = 68;
const CONSTRAINT_SIZE = 22; // badge diameter

function SunIcon({ size }: { size: number }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40">
      <circle cx="20" cy="20" r="14" fill="#f97316" />
    </svg>
  );
}

function MoonIcon({ size }: { size: number }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40">
      <defs>
        <mask id="moon-mask">
          <rect width="40" height="40" fill="white" />
          <circle cx="27" cy="17" r="12" fill="black" />
        </mask>
      </defs>
      <circle cx="20" cy="20" r="14" fill="#3b82f6" mask="url(#moon-mask)" />
    </svg>
  );
}

const DIAGONAL_ERROR = "repeating-linear-gradient(-45deg, rgba(220,38,38,0.55) 0px, rgba(220,38,38,0.55) 3px, rgba(220,38,38,0.2) 3px, rgba(220,38,38,0.2) 6px)";

function checkWin(grid: Cell[][], puzzle: TangoPuzzle): boolean {
  const { size, hEdges, vEdges } = puzzle;
  for (let r = 0; r < size; r++)
    for (let c = 0; c < size; c++)
      if (!grid[r][c]) return false;
  for (let i = 0; i < size; i++) {
    let rs = 0, rm = 0, cs = 0, cm = 0;
    for (let j = 0; j < size; j++) {
      if (grid[i][j] === "sun") rs++; else rm++;
      if (grid[j][i] === "sun") cs++; else cm++;
    }
    if (rs !== size / 2 || rm !== size / 2 || cs !== size / 2 || cm !== size / 2) return false;
  }
  for (let i = 0; i < size; i++)
    for (let j = 0; j <= size - 3; j++) {
      if (grid[i][j] === grid[i][j + 1] && grid[i][j] === grid[i][j + 2]) return false;
      if (grid[j][i] === grid[j + 1][i] && grid[j][i] === grid[j + 2][i]) return false;
    }
  for (let r = 0; r < size; r++)
    for (let c = 0; c < size - 1; c++) {
      const e = hEdges[r][c]; if (!e) continue;
      const same = grid[r][c] === grid[r][c + 1];
      if ((e === "=" && !same) || (e === "x" && same)) return false;
    }
  for (let r = 0; r < size - 1; r++)
    for (let c = 0; c < size; c++) {
      const e = vEdges[r][c]; if (!e) continue;
      const same = grid[r][c] === grid[r + 1][c];
      if ((e === "=" && !same) || (e === "x" && same)) return false;
    }
  return true;
}

function getErrors(grid: Cell[][], puzzle: TangoPuzzle): Set<string> {
  const { size, hEdges, vEdges } = puzzle;
  const err = new Set<string>();
  for (let i = 0; i < size; i++) {
    let rs = 0, rm = 0, cs = 0, cm = 0;
    for (let j = 0; j < size; j++) {
      if (grid[i][j] === "sun") rs++; if (grid[i][j] === "moon") rm++;
      if (grid[j][i] === "sun") cs++; if (grid[j][i] === "moon") cm++;
    }
    if (rs > size / 2) for (let j = 0; j < size; j++) if (grid[i][j] === "sun") err.add(`${i},${j}`);
    if (rm > size / 2) for (let j = 0; j < size; j++) if (grid[i][j] === "moon") err.add(`${i},${j}`);
    if (cs > size / 2) for (let j = 0; j < size; j++) if (grid[j][i] === "sun") err.add(`${j},${i}`);
    if (cm > size / 2) for (let j = 0; j < size; j++) if (grid[j][i] === "moon") err.add(`${j},${i}`);
  }
  for (let i = 0; i < size; i++)
    for (let j = 0; j <= size - 3; j++) {
      if (grid[i][j] && grid[i][j] === grid[i][j + 1] && grid[i][j] === grid[i][j + 2]) {
        err.add(`${i},${j}`); err.add(`${i},${j + 1}`); err.add(`${i},${j + 2}`);
      }
      if (grid[j][i] && grid[j][i] === grid[j + 1][i] && grid[j][i] === grid[j + 2][i]) {
        err.add(`${j},${i}`); err.add(`${j + 1},${i}`); err.add(`${j + 2},${i}`);
      }
    }
  // Edge constraint violations
  for (let r = 0; r < size; r++)
    for (let c = 0; c < size - 1; c++) {
      const e = hEdges[r][c];
      if (!e || !grid[r][c] || !grid[r][c + 1]) continue;
      const same = grid[r][c] === grid[r][c + 1];
      if ((e === "=" && !same) || (e === "x" && same)) {
        err.add(`${r},${c}`); err.add(`${r},${c + 1}`);
      }
    }
  for (let r = 0; r < size - 1; r++)
    for (let c = 0; c < size; c++) {
      const e = vEdges[r][c];
      if (!e || !grid[r][c] || !grid[r + 1][c]) continue;
      const same = grid[r][c] === grid[r + 1][c];
      if ((e === "=" && !same) || (e === "x" && same)) {
        err.add(`${r},${c}`); err.add(`${r + 1},${c}`);
      }
    }
  return err;
}

const STORAGE_KEY = (d: string) => `tango-${d}`;

export default function TangoBoard({ puzzle, date, onSolve }: Props) {
  const { size, given, hEdges, vEdges } = puzzle;
  const [CELL, setCELL] = useState(() =>
    typeof window === "undefined" ? MAX_CELL : Math.min(MAX_CELL, Math.floor((window.innerWidth - 32) / size))
  );

  const [grid, setGrid] = useState<Cell[][]>(() => {
    if (typeof window !== "undefined") {
      const s = localStorage.getItem(STORAGE_KEY(date));
      if (s) return JSON.parse(s);
    }
    return given.map(r => [...r]);
  });

  const history = useRef<Cell[][][]>([]);
  const errorTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const [shownErrors, setShownErrors] = useState<Set<string>>(new Set());
  const [won, setWon] = useState(false);
  const [elapsed, setElapsed] = useState(0);
  const [t0] = useState(() => Date.now());

  useEffect(() => {
    const update = () => setCELL(Math.min(MAX_CELL, Math.floor((window.innerWidth - 32) / size)));
    window.addEventListener("resize", update);
    return () => window.removeEventListener("resize", update);
  }, [size]);

  useEffect(() => {
    if (won) return;
    const id = setInterval(() => setElapsed(Math.floor((Date.now() - t0) / 1000)), 500);
    return () => clearInterval(id);
  }, [won, t0]);

  useEffect(() => {
    localStorage.setItem(STORAGE_KEY(date), JSON.stringify(grid));
    if (!won && checkWin(grid, puzzle)) { setWon(true); onSolve?.(Math.floor((Date.now() - t0) / 1000)); }
  }, [grid, date, puzzle, won, onSolve, t0]);


  const filled = grid.flat().filter(Boolean).length;
  const fmt = (s: number) => `${String(Math.floor(s / 60)).padStart(2, "0")}:${String(s % 60).padStart(2, "0")}`;

  const undo = useCallback(() => {
    if (won || history.current.length === 0) return;
    setGrid(history.current.pop()!);
  }, [won]);

  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key === "z") { e.preventDefault(); undo(); }
    };
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, [undo]);

  const cycleCell = useCallback((r: number, c: number) => {
    if (won || given[r][c] !== null) return;
    setGrid(prev => {
      history.current.push(prev.map(row => [...row]));
      const next = prev.map(row => [...row]);
      next[r][c] = next[r][c] === null ? "sun" : next[r][c] === "sun" ? "moon" : null;
      return next;
    });
  }, [won, given]);

  const reset = () => { history.current = []; setGrid(given.map(r => [...r])); setWon(false); };

  const handleHint = () => {
    if (won) return;
    for (let r = 0; r < size; r++)
      for (let c = 0; c < size; c++)
        if (!grid[r][c] && !given[r][c]) {
          setGrid(prev => {
            const next = prev.map(row => [...row]);
            next[r][c] = puzzle.solution[r][c];
            return next;
          });
          return;
        }
  };

  const totalW = size * CELL;
  const iconSize = Math.round(CELL * 0.55);

  return (
    <div className="flex flex-col items-center gap-4">
      <div className="flex items-center gap-8 text-sm text-gray-500 font-medium">
        <span>{filled} / {size * size}</span>
        <span className="tabular-nums">{fmt(elapsed)}</span>
      </div>

      {won && <WinBanner game="tango" date={date} elapsed={elapsed} />}

      {/* Board: positioned cells + constraint symbols on borders */}
      <div style={{ position: "relative", width: totalW, height: totalW }}>
        {/* Cells */}
        <div style={{
          display: "grid",
          gridTemplateColumns: `repeat(${size}, ${CELL}px)`,
          border: "1.5px solid #d1d5db",
          borderRadius: 6,
          overflow: "hidden",
        }}>
          {Array.from({ length: size }, (_, r) =>
            Array.from({ length: size }, (_, c) => {
              const val = grid[r][c];
              const isGiven = given[r][c] !== null;
              const err = shownErrors.has(`${r},${c}`);

              let bg = "#ffffff";
              if (isGiven) bg = "#e5e7eb"; // gray for given cells

              const bRight  = c < size - 1 ? "1px solid #d1d5db" : "none";
              const bBottom = r < size - 1 ? "1px solid #d1d5db" : "none";

              return (
                <div
                  key={`${r}-${c}`}
                  onClick={() => cycleCell(r, c)}
                  style={{
                    width: CELL, height: CELL,
                    backgroundColor: bg,
                    backgroundImage: err ? DIAGONAL_ERROR : undefined,
                    borderRight: bRight,
                    borderBottom: bBottom,
                    cursor: (isGiven || won) ? "default" : "pointer",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    userSelect: "none",
                    transition: "background-color 0.1s",
                  }}
                >
                  <span style={{ pointerEvents: "none" }}>
                    {val === "sun" && <SunIcon size={iconSize} />}
                    {val === "moon" && <MoonIcon size={iconSize} />}
                  </span>
                </div>
              );
            })
          )}
        </div>

        {/* Horizontal constraint symbols: between (r,c) and (r,c+1) — on the vertical border */}
        {Array.from({ length: size }, (_, r) =>
          Array.from({ length: size - 1 }, (_, c) => {
            const e = hEdges[r][c];
            if (!e) return null;
            return (
              <div
                key={`h-${r}-${c}`}
                style={{
                  position: "absolute",
                  left: (c + 1) * CELL - CONSTRAINT_SIZE / 2,
                  top: r * CELL + (CELL - CONSTRAINT_SIZE) / 2,
                  width: CONSTRAINT_SIZE,
                  height: CONSTRAINT_SIZE,
                  borderRadius: "50%",
                  background: "#ffffff",
                  border: "1.5px solid #d1d5db",
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  fontSize: 11,
                  fontWeight: 700,
                  color: "#78716c",
                  zIndex: 10,
                  pointerEvents: "none",
                }}
              >
                {e === "=" ? "=" : "×"}
              </div>
            );
          })
        )}

        {/* Vertical constraint symbols: between (r,c) and (r+1,c) — on the horizontal border */}
        {Array.from({ length: size - 1 }, (_, r) =>
          Array.from({ length: size }, (_, c) => {
            const e = vEdges[r][c];
            if (!e) return null;
            return (
              <div
                key={`v-${r}-${c}`}
                style={{
                  position: "absolute",
                  left: c * CELL + (CELL - CONSTRAINT_SIZE) / 2,
                  top: (r + 1) * CELL - CONSTRAINT_SIZE / 2,
                  width: CONSTRAINT_SIZE,
                  height: CONSTRAINT_SIZE,
                  borderRadius: "50%",
                  background: "#ffffff",
                  border: "1.5px solid #d1d5db",
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  fontSize: 11,
                  fontWeight: 700,
                  color: "#78716c",
                  zIndex: 10,
                  pointerEvents: "none",
                }}
              >
                {e === "=" ? "=" : "×"}
              </div>
            );
          })
        )}
      </div>

      <div className="flex gap-3">
        {!won && (
          <>
            <button
              onClick={undo}
              disabled={history.current.length === 0}
              className="px-5 py-2 rounded-full border border-gray-300 text-gray-500 hover:bg-gray-50 text-sm transition-colors disabled:opacity-30"
              title="Annuler (Ctrl+Z)"
            >
              ↺ Annuler
            </button>
            <button onClick={reset}
              className="px-5 py-2 rounded-full border border-gray-300 text-gray-500 hover:bg-gray-50 text-sm transition-colors">
              Recommencer
            </button>
            <button onClick={handleHint}
              className="px-5 py-2 rounded-full border border-gray-900 text-gray-900 hover:bg-gray-50 text-sm font-medium transition-colors">
              Indice
            </button>
          </>
        )}
      </div>

      <div className="flex flex-col items-center gap-1 text-xs text-gray-400">
        <span>1 clic = ☀ · 2 clics = ☽ · 3 clics = effacer</span>
        <span>Autant de soleils que de lunes par ligne et colonne. Pas plus de 2 identiques consécutifs.</span>
      </div>
    </div>
  );
}
