"use client";
import { useEffect, useRef, useState } from "react";
import { getSocket } from "../lib/socket-client";
import { useGame } from "../lib/store";
import ChatBox from "./ChatBox";
import PlayerList from "./PlayerList";

const PALETTE = [
  "#2D2D2D","#FFFFFF","#FF5C5C","#FFD23F","#4ECDC4","#A593E0","#5BCEFA",
  "#1F8FFF","#1AAE56","#A35924","#FF8FB1","#7B3F00","#888888"
];
const SIZES = [3, 6, 12];

export default function SkribblGame() {
  const room = useGame((s) => s.room);
  const myId = useGame((s) => s.myId);
  const [choices, setChoices] = useState<string[]|null>(null);
  const [endsAt, setEndsAt] = useState<number>(0);
  const [now, setNow] = useState(Date.now());
  const [color, setColor] = useState("#2D2D2D");
  const [size, setSize] = useState(6);
  const [tool, setTool] = useState<"brush"|"eraser">("brush");
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const stageRef = useRef<HTMLDivElement | null>(null);
  const drawingRef = useRef(false);
  const lastRef = useRef<{x:number;y:number}|null>(null);
  const broadcastBufRef = useRef<any[]>([]);
  const lastBroadcastRef = useRef(0);

  // Listen for skribbl-specific events
  useEffect(() => {
    const socket = getSocket();
    const onChoices = (c: string[]) => setChoices(c);
    const onRoundStart = (d: any) => {
      setChoices(null);
      setEndsAt(Date.now() + d.durationMs);
      clearLocalCanvas();
    };
    const onHint = () => {/* server pushes new room state */};
    const onRoundEnd = () => { setEndsAt(0); };
    const onStroke = (s: any) => {
      drawSegment(s.prevX, s.prevY, s.x, s.y, s.color, s.size, s.tool);
    };
    const onClear = () => clearLocalCanvas();
    socket.on("skribbl:wordChoices", onChoices);
    socket.on("skribbl:roundStart", onRoundStart);
    socket.on("skribbl:hint", onHint);
    socket.on("skribbl:roundEnd", onRoundEnd);
    socket.on("skribbl:stroke", onStroke);
    socket.on("skribbl:clear", onClear);
    return () => {
      socket.off("skribbl:wordChoices", onChoices);
      socket.off("skribbl:roundStart", onRoundStart);
      socket.off("skribbl:hint", onHint);
      socket.off("skribbl:roundEnd", onRoundEnd);
      socket.off("skribbl:stroke", onStroke);
      socket.off("skribbl:clear", onClear);
    };
  }, []);

  // Use endsAt from room.skribbl too, in case we joined mid-round
  useEffect(() => {
    if (room?.skribbl?.endsAt) setEndsAt(room.skribbl.endsAt);
  }, [room?.skribbl?.endsAt]);

  // Tick
  useEffect(() => {
    const t = setInterval(() => setNow(Date.now()), 250);
    return () => clearInterval(t);
  }, []);

  // Resize canvas
  useEffect(() => {
    const resize = () => {
      const canvas = canvasRef.current;
      const stage = stageRef.current;
      if (!canvas || !stage) return;
      const rect = stage.getBoundingClientRect();
      const dpr = window.devicePixelRatio || 1;
      canvas.width = Math.max(100, rect.width * dpr);
      canvas.height = Math.max(100, rect.height * dpr);
      canvas.style.width = rect.width + "px";
      canvas.style.height = rect.height + "px";
      const ctx = canvas.getContext("2d");
      if (ctx) ctx.scale(dpr, dpr);
    };
    resize();
    window.addEventListener("resize", resize);
    return () => window.removeEventListener("resize", resize);
  }, []);

  const drawSegment = (px:number, py:number, x:number, y:number, c:string, sz:number, tl:string) => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.strokeStyle = tl === "eraser" ? "#FFF8E7" : c;
    ctx.lineWidth = sz;
    ctx.beginPath();
    ctx.moveTo(px, py);
    ctx.lineTo(x, y);
    ctx.stroke();
  };

  const clearLocalCanvas = () => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  };

  const sk = room?.skribbl;
  const isDrawer = sk?.drawerId === myId;
  const drawerName = room?.players.find(p => p.id === sk?.drawerId)?.nickname || "?";

  const getPos = (e: React.PointerEvent<HTMLCanvasElement>) => {
    const canvas = canvasRef.current!;
    const rect = canvas.getBoundingClientRect();
    return { x: e.clientX - rect.left, y: e.clientY - rect.top };
  };

  const onDown = (e: React.PointerEvent<HTMLCanvasElement>) => {
    if (!isDrawer || sk?.phase !== "drawing") return;
    e.preventDefault();
    drawingRef.current = true;
    const p = getPos(e);
    lastRef.current = p;
    drawSegment(p.x, p.y, p.x, p.y, color, size, tool);
    queueStroke({ prevX: p.x, prevY: p.y, x: p.x, y: p.y, color, size, tool });
  };
  const onMove = (e: React.PointerEvent<HTMLCanvasElement>) => {
    if (!drawingRef.current || !isDrawer) return;
    const p = getPos(e);
    const last = lastRef.current!;
    drawSegment(last.x, last.y, p.x, p.y, color, size, tool);
    queueStroke({ prevX: last.x, prevY: last.y, x: p.x, y: p.y, color, size, tool });
    lastRef.current = p;
  };
  const onUp = () => {
    drawingRef.current = false;
    lastRef.current = null;
    flushStrokes();
  };

  const queueStroke = (s: any) => {
    broadcastBufRef.current.push(s);
    const now = Date.now();
    if (now - lastBroadcastRef.current > 33) {
      flushStrokes();
    }
  };
  const flushStrokes = () => {
    const buf = broadcastBufRef.current;
    if (!buf.length) return;
    const socket = getSocket();
    for (const s of buf) socket.emit("skribbl:stroke", s);
    broadcastBufRef.current = [];
    lastBroadcastRef.current = Date.now();
  };

  const pickWord = (word: string) => {
    getSocket().emit("skribbl:pickWord", { word }, () => {});
  };
  const clearAll = () => {
    if (!isDrawer) return;
    clearLocalCanvas();
    getSocket().emit("skribbl:clear");
  };

  const remaining = Math.max(0, Math.ceil((endsAt - now) / 1000));
  const totalSec = (room?.settings?.drawTimeSec || 80) as number;
  const ringPct = endsAt ? Math.max(0, Math.min(1, (endsAt - now) / (totalSec * 1000))) : 0;
  const dashTotal = 165;
  const dashOff = dashTotal * (1 - ringPct);

  const wordMask = sk?.wordMask || "";

  return (
    <div className="grid gap-5 max-[1100px]:grid-cols-1" style={{gridTemplateColumns:"220px 1fr 280px"}}>
      <aside className="panel" data-testid="scoreboard">
        <div className="text-xs font-bold uppercase tracking-wider mb-3 px-1" style={{color:"rgba(45,45,45,0.6)"}}>Scoreboard</div>
        <PlayerList highlightDrawerId={sk?.drawerId} />
      </aside>

      <section className="flex flex-col gap-3.5">
        <div className="flex items-center justify-between gap-4 panel" style={{padding:"14px 18px"}}>
          <div className="relative w-[60px] h-[60px] flex-shrink-0" data-testid="timer-ring">
            <svg width="60" height="60" style={{transform:"rotate(-90deg)"}}>
              <circle cx="30" cy="30" r="26" fill="none" stroke="rgba(45,45,45,0.12)" strokeWidth="6"/>
              <circle cx="30" cy="30" r="26" fill="none" stroke="var(--coral)" strokeWidth="6" strokeLinecap="round" strokeDasharray={dashTotal} strokeDashoffset={dashOff} style={{transition:"stroke-dashoffset 1s linear"}}/>
            </svg>
            <div className="absolute inset-0 grid place-items-center font-bold text-base">{remaining}</div>
          </div>
          <div className="flex-1 text-center">
            <div className="text-xs font-bold uppercase tracking-wider" style={{color:"rgba(45,45,45,0.55)"}}>
              {isDrawer ? "Your secret word" : `${drawerName} is drawing`}
            </div>
            <div className="text-xl font-bold tracking-[6px] mt-1" data-testid="word-mask">
              {isDrawer && sk?.phase === "drawing" ? (sk as any)?.word || wordMask : wordMask || "_____"}
            </div>
          </div>
          <div className="pill" style={{background:"var(--lavender)", color:"white"}}>
            Round {sk?.roundIndex || 0}/{sk?.totalRounds || 0}
          </div>
        </div>

        <div className="panel relative" style={{padding:16, aspectRatio:"16/10", minHeight:380, display:"flex", flexDirection:"column", gap:12}}>
          {isDrawer && <div className="absolute top-3.5 left-3.5 px-3 py-1.5 rounded-full text-white border-2 border-dark text-xs font-bold flex items-center gap-1.5 z-10" style={{background:"var(--coral)", boxShadow:"0 3px 0 rgba(0,0,0,0.15)"}}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/></svg>
            You're drawing
          </div>}
          <div ref={stageRef} className="flex-1 rounded-2xl overflow-hidden relative" style={{background:"#FFF8E7", border:"2px dashed rgba(45,45,45,0.18)"}}>
            <canvas
              ref={canvasRef}
              data-testid="draw-canvas"
              onPointerDown={onDown}
              onPointerMove={onMove}
              onPointerUp={onUp}
              onPointerLeave={onUp}
              style={{ touchAction: "none", cursor: isDrawer ? "crosshair" : "default", display:"block" }}
            />
          </div>
          {isDrawer && <div className="flex items-center gap-3.5 p-3 rounded-2xl flex-wrap justify-center" style={{background:"var(--cream)"}}>
            <div className="flex gap-1.5 flex-wrap">
              {PALETTE.map(c => (
                <button type="button" key={c} onClick={()=>{setColor(c); setTool("brush");}}
                  data-testid={`color-${c}`}
                  className="w-7 h-7 rounded-lg border-2 border-dark shadow-chunky transition-transform hover:-translate-y-0.5"
                  style={{background:c, outline: color===c ? "3px solid var(--dark)" : undefined, outlineOffset: color===c ? 2 : undefined}}/>
              ))}
            </div>
            <div className="w-0.5 h-7" style={{background:"rgba(45,45,45,0.15)"}}/>
            <div className="flex gap-1.5">
              {SIZES.map((sz, i) => (
                <button type="button" key={sz} onClick={()=>setSize(sz)} data-testid={`size-${sz}`} className="w-9 h-9 rounded-xl border-2 border-dark grid place-items-center shadow-chunky" style={{background: size===sz ? "var(--mint)" : "white"}}>
                  <span className="rounded-full bg-dark" style={{width: 4 + i*4, height: 4 + i*4}}/>
                </button>
              ))}
            </div>
            <div className="w-0.5 h-7" style={{background:"rgba(45,45,45,0.15)"}}/>
            <button type="button" onClick={()=>setTool(tool==="eraser"?"brush":"eraser")} data-testid="tool-eraser" className="w-9 h-9 rounded-xl border-2 border-dark grid place-items-center shadow-chunky" style={{background: tool==="eraser" ? "var(--yellow)" : "white"}}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M20 20H7l-4-4 8-8 12 12-3 0z"/></svg>
            </button>
            <button type="button" onClick={clearAll} data-testid="tool-clear" className="px-3 h-9 rounded-xl border-2 border-dark font-bold text-xs shadow-chunky" style={{background:"white"}}>Clear</button>
          </div>}
        </div>
      </section>

      <aside className="panel flex flex-col" style={{minHeight:500}}>
        <div className="text-xs font-bold uppercase tracking-wider mb-2 px-1" style={{color:"rgba(45,45,45,0.6)"}}>Guesses</div>
        <ChatBox placeholder={isDrawer ? "You're drawing!" : "Type your guess..."}/>
      </aside>

      {choices && (
        <Modal>
          <h2 className="font-bold text-2xl text-center mb-1">Pick a word to draw</h2>
          <p className="text-center font-medium text-sm mb-5" style={{color:"rgba(45,45,45,0.65)"}}>Choose one of the three. 15s timer.</p>
          <div className="flex gap-3 justify-center flex-wrap">
            {choices.map(w => (
              <button key={w} onClick={()=>pickWord(w)} className="btn btn-yellow" data-testid={`pick-${w}`} style={{padding:"14px 22px"}}>{w}</button>
            ))}
          </div>
        </Modal>
      )}
    </div>
  );
}

function Modal({ children }: { children: React.ReactNode }) {
  return (
    <div className="fixed inset-0 z-50 grid place-items-center px-4" style={{background:"rgba(45,45,45,0.55)"}}>
      <div className="panel max-w-[520px] w-full" data-testid="modal">{children}</div>
    </div>
  );
}
