/* global React, ReactDOM, WordSearch, MOCKUP_GRID, MOCKUP_PLACED, placeWords, normalize */
/* global TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakColor, TweakToggle, TweakText */

const { useState, useEffect, useRef, useMemo } = React;

const Logo99 = ({ height = 80, color = "#000" }) => (
  <span className="logo-99" aria-label="99">
    <svg viewBox="0 0 226.1 156.3" style={{ height, width: "auto", fill: color }}>
      <path d="M108.7,52.3c-.4-11.3-4.3-21.8-10.6-30.3C88.2,8.6,72.4,0,54.5,0S20.8,8.7,10.9,22C4.6,30.5.8,40.9.4,52.3h0v2c0,25.7,17.9,47.3,42,52.8l-30,45.8c-1,1.5,0,3.5,1.9,3.5h36.9c.9,0,1.7-.5,2.2-1.2l1.2-1.9h0c0,0,45.3-69.1,45.3-69.1,5.7-8.6,9-18.9,9-29.9v-2h0ZM71.9,61.9l-1.5,2.3c-3.6,4.8-9.4,8-15.9,8-11,0-19.8-8.9-19.8-19.8s0,0,0,0c0-10.9,8.9-19.8,19.8-19.8s19.8,8.9,19.8,19.8c0,0,0,0,0,0,0,3.5-.9,6.7-2.5,9.6Z" />
      <path d="M225.7,52.3c-.4-11.3-4.3-21.8-10.6-30.3C205.2,8.6,189.4,0,171.5,0s-33.7,8.7-43.6,22c-6.3,8.5-10.2,19-10.6,30.3h0v2c0,25.7,17.9,47.3,42,52.8l-30,45.8c-1,1.5,0,3.5,1.9,3.5h36.9c.9,0,1.7-.5,2.2-1.2l1.2-1.9h0c0,0,45.3-69.1,45.3-69.1,5.7-8.6,9-18.9,9-29.9v-2h0ZM188.9,61.9l-1.5,2.3c-3.6,4.8-9.4,8-15.9,8-11,0-19.8-8.9-19.8-19.8s0,0,0,0c0-10.9,8.9-19.8,19.8-19.8s19.8,8.9,19.8,19.8c0,0,0,0,0,0,0,3.5-.9,6.7-2.5,9.6Z" />
    </svg>
  </span>
);

const LikeIcon = () => (
  <img className="like-icon" src="assets/like-icon.svg" alt="" aria-hidden="true" draggable={false} />
);

const ShieldIcon = () => (
  <svg className="shield-icon" viewBox="0 0 24 24" aria-hidden="true">
    <path
      fill="var(--orange)"
      d="M12 2 4 5v6c0 5 3.5 9.4 8 11 4.5-1.6 8-6 8-11V5l-8-3z"
    />
    <path
      fill="none"
      stroke="#fff"
      strokeWidth="2.2"
      strokeLinecap="round"
      strokeLinejoin="round"
      d="m9 12 2 2 4-4"
    />
  </svg>
);

const SAFETY_TIPS = [
  "Frear no momento certo <em>protege</em> você e todo mundo que está na rua.",
  "Acelerar com equilíbrio e <em>respeitar os limites</em> faz diferença no dia a dia.",
  "Curvas com <em>cuidado e respeito às faixas</em> reduzem riscos no trânsito.",
  "Acompanhe seu desempenho no <em>Relatório de Direção</em>, direto no app da 99.",
];

const SAFETY_TIP_INTERVAL_MS = 6000;
const SAFETY_TIP_FADE_MS = 320;

function SafetyTipCard({ tips }) {
  const [index, setIndex] = useState(0);
  const [fading, setFading] = useState(false);
  const len = tips.length;

  useEffect(() => {
    const id = window.setInterval(() => {
      setFading(true);
      window.setTimeout(() => {
        setIndex((i) => (i + 1) % len);
        setFading(false);
      }, SAFETY_TIP_FADE_MS);
    }, SAFETY_TIP_INTERVAL_MS);
    return () => window.clearInterval(id);
  }, [len]);

  return (
    <div className="hint-card" aria-live="polite">
      <span className="badge"><ShieldIcon /></span>
      <span
        className={"hint-card__text" + (fading ? " is-fading" : "")}
        dangerouslySetInnerHTML={{ __html: tips[index] }}
      />
    </div>
  );
}

// ---------- Background letter pattern (grid of cells, one letter each) ----------
const BG_LETTERS = [
  "CATYMOTZSECATYMO",
  "ONKEYQAMLMONKEYQ",
  "FLAMINGOOIFLAMIN",
  "OTSFPZIUHLOTSFPZ",
  "XETIGERSPEXETIGE",
  "UKCSIHAEAHUKCSIH",
  "PSOHMLFNNAPSOHML",
  "IEBASRFODXIEBASR",
  "EBRAQSEWAZEBRAQS",
  "JMACELXAWEJMACEL",
];

function BgPattern() {
  const cols = BG_LETTERS[0].length;
  const rows = BG_LETTERS.length;
  return (
    <div
      className="bg-pattern"
      aria-hidden="true"
      style={{
        gridTemplateColumns: `repeat(${cols}, 1fr)`,
        gridTemplateRows: `repeat(${rows}, 1fr)`,
      }}
    >
      {BG_LETTERS.flatMap((row, ri) =>
        row.split("").map((ch, ci) => (
          <div className="bg-cell" key={ri + "_" + ci}>
            <span>{ch}</span>
          </div>
        ))
      )}
    </div>
  );
}

// ---------- Confetti ----------
function Confetti({ count = 80 }) {
  const pieces = useMemo(() => {
    const colors = ["#ffdd04", "#e85623", "#000", "#ffffff"];
    return Array.from({ length: count }, (_, i) => ({
      left: Math.random() * 100,
      delay: Math.random() * 0.6,
      duration: 1.6 + Math.random() * 1.8,
      bg: colors[i % colors.length],
      rot: Math.random() * 360,
    }));
  }, [count]);
  return (
    <div className="confetti" aria-hidden="true">
      {pieces.map((p, i) => (
        <span
          key={i}
          style={{
            left: `${p.left}%`,
            background: p.bg,
            animationDuration: `${p.duration}s`,
            animationDelay: `${p.delay}s`,
            transform: `rotate(${p.rot}deg)`,
          }}
        />
      ))}
    </div>
  );
}

// ---------- Splash ----------
function Splash({ tweaks, onStart }) {
  return (
    <div className="splash fade-in">
      <Logo99 height={77} />
      <p className="eyebrow">Caça-Palavras</p>
      <h1>{tweaks.title}</h1>
      <p className="lede" dangerouslySetInnerHTML={{ __html: tweaks.lede }} />
      <button className="btn" onClick={onStart}>Começar</button>
    </div>
  );
}

const WORD_FOUND_POPUP_MS = 2000;

function WordFoundPopup({ onDismiss }) {
  return (
    <div
      className="word-found-overlay"
      role="dialog"
      aria-live="polite"
      aria-label="Palavra encontrada"
      onClick={onDismiss}
    >
      <div className="word-found-popup">
        <span className="word-found-popup__badge" aria-hidden="true">
          <LikeIcon />
        </span>
        <p className="word-found-popup__text">
          Conte com a
          <img className="word-found-popup__logo" src="assets/99-icon.png" alt="99" draggable={false} />
        </p>
      </div>
    </div>
  );
}

// ---------- Game ----------
function Game({ tweaks, onWin }) {
  const [hintTick, setHintTick] = useState(0);
  const [found, setFound] = useState([]);
  const [wordPopup, setWordPopup] = useState(false);
  const wordPopupTimer = useRef(null);

  const { grid, placed, rows, cols, words } = useMemo(() => {
    const words = tweaks.words.split(",").map(w => w.trim()).filter(Boolean);
    const size = tweaks.gridSize;
    let attempt = null;
    for (let i = 0; i < 30 && !attempt; i++) {
      attempt = placeWords(size, size, words, tweaks.diagonals);
    }
    if (!attempt) {
      // last resort: mockup-faithful grid
      return { grid: MOCKUP_GRID, placed: MOCKUP_PLACED, rows: 9, cols: 9, words };
    }
    return { grid: attempt.grid, placed: attempt.placed, rows: size, cols: size, words };
  }, [tweaks.words, tweaks.gridSize, tweaks.diagonals]);

  // Reset found list whenever grid is regenerated
  useEffect(() => {
    setFound([]);
    setWordPopup(false);
    if (wordPopupTimer.current) {
      clearTimeout(wordPopupTimer.current);
      wordPopupTimer.current = null;
    }
  }, [grid]);

  const dismissWordPopup = () => {
    if (wordPopupTimer.current) {
      clearTimeout(wordPopupTimer.current);
      wordPopupTimer.current = null;
    }
    setWordPopup(false);
  };

  const showWordFoundPopup = () => {
    setWordPopup(true);
    if (wordPopupTimer.current) clearTimeout(wordPopupTimer.current);
    wordPopupTimer.current = setTimeout(dismissWordPopup, WORD_FOUND_POPUP_MS);
  };

  useEffect(() => () => {
    if (wordPopupTimer.current) clearTimeout(wordPopupTimer.current);
  }, []);

  const handleWordFound = (w) => {
    setFound((prev) => (prev.includes(w) ? prev : [...prev, w]));
    showWordFoundPopup();
  };

  return (
    <div className="game fade-in">
      <div className="game-left">
        <div className="game-intro">
          <h2 className="game-title">{tweaks.title}</h2>
          <div className="game-find">
            <p className="game-sub">
              Encontre as <em>{placed.length} palavras</em> escondidas!
            </p>
            <div className="word-list">
              {placed.map((p, i) => {
              const isFound = found.includes(p.word);
              const w = p.word.toUpperCase();
              return (
                <div key={i} className={"word-pill " + (isFound ? "found" : "")}>
                  {w.split("").map((ch, j) => (
                    <span
                      key={j}
                      className={"bead " + (isFound ? "flip" : "")}
                      style={{ animationDelay: `${j * 40}ms` }}
                    >
                      {ch}
                    </span>
                  ))}
                </div>
              );
              })}
            </div>
          </div>
        </div>
        <div className="game-left-lower">
          <SafetyTipCard tips={SAFETY_TIPS} />
          <div className="brand-99"><Logo99 height={41} /></div>
        </div>
      </div>

      <div className="grid-wrap">
        <WordSearch
          rows={rows}
          cols={cols}
          grid={grid}
          placed={placed}
          words={words}
          hintTrigger={hintTick}
          onWordFound={handleWordFound}
          onAllFound={onWin}
        />
        <div className="game-actions">
          <button className="btn" onClick={() => setHintTick(t => t + 1)}>Dica</button>
        </div>
      </div>
      {wordPopup && <WordFoundPopup onDismiss={dismissWordPopup} />}
    </div>
  );
}

const WIN_STEPS = [
  { n: 1, html: "Abra o <strong>app da 99</strong>" },
  { n: 2, html: "Vá em <strong>Perfil</strong>" },
  { n: 3, html: "Toque em <strong>Relatório de Direção</strong>" },
];

// ---------- Win ----------
function Win({ onRestart }) {
  return (
    <div className="win fade-in">
      <div className="win-left">
        <h1 className="win-title">{"Você\ncompletou\no desafio!"}</h1>
        <p className="win-lede">
          Cada corrida <em>mais segura</em> faz diferença para você, para quem vai com você e para toda a comunidade.
        </p>
        <button type="button" className="btn win-cta" onClick={onRestart}>
          Jogue novamente
        </button>
      </div>
      <div className="win-phone-wrap">
        <div className="win-phone" aria-label="Como acessar o Relatório de Direção">
          <p className="win-phone__heading">Como acessar seu Relatório de Direção:</p>
          <div className="win-phone__steps-wrap">
            <ol className="win-steps">
              {WIN_STEPS.map((step) => (
                <li key={step.n} className="win-step">
                  <span className="win-step__num" aria-hidden="true">{step.n}</span>
                  <span className="win-step__text" dangerouslySetInnerHTML={{ __html: step.html }} />
                </li>
              ))}
            </ol>
          </div>
          <div className="win-phone__logo"><Logo99 height={56} /></div>
        </div>
        <img
          className="win-phone__frame"
          src="assets/frame-celular.svg"
          alt=""
          aria-hidden="true"
          draggable={false}
        />
      </div>
    </div>
  );
}

// ---------- Idle reset hook ----------
function useIdleReset(active, onIdle, ms = 60000) {
  useEffect(() => {
    if (!active) return;
    let t;
    const bump = () => {
      clearTimeout(t);
      t = setTimeout(onIdle, ms);
    };
    bump();
    const evs = ["pointerdown", "pointermove", "keydown"];
    evs.forEach(e => window.addEventListener(e, bump));
    return () => {
      clearTimeout(t);
      evs.forEach(e => window.removeEventListener(e, bump));
    };
  }, [active, onIdle, ms]);
}

// ---------- Root ----------
const DEFAULT_TWEAKS = /*EDITMODE-BEGIN*/{
  "theme": "transito",
  "title": "Trânsito\nConsciente",
  "lede": "Encontre as palavras escondidas e descubra como o <em>Relatório de Direção da 99</em> pode deixar suas corridas mais seguras.",
  "words": "TRÂNSITO, FRENAGEM, SEGURANÇA",
  "gridSize": 9,
  "diagonals": false,
  "palette": "yellow",
  "idleReset": true
}/*EDITMODE-END*/;

function applyPalette(p) {
  const root = document.documentElement;
  if (p === "yellow") {
    root.style.setProperty("--yellow", "#ffdd04");
    root.style.setProperty("--orange", "#e85623");
    root.style.setProperty("--orange-dark", "#c44619");
  } else if (p === "orange") {
    root.style.setProperty("--yellow", "#ffb627");
    root.style.setProperty("--orange", "#e85623");
    root.style.setProperty("--orange-dark", "#c44619");
  } else if (p === "dark") {
    root.style.setProperty("--yellow", "#111111");
    root.style.setProperty("--orange", "#ffdd04");
    root.style.setProperty("--orange-dark", "#d4b700");
  }
}

function App() {
  const [tweaks, setTweak] = useTweaks(DEFAULT_TWEAKS);
  const [screen, setScreen] = useState("splash"); // splash | game | win

  // Title supports literal newlines (rendered via white-space: pre-line)
  const tweaksForUi = tweaks;

  useEffect(() => { applyPalette(tweaks.palette); }, [tweaks.palette]);

  // Idle reset (kiosk)
  useIdleReset(
    screen !== "splash" && tweaks.idleReset,
    () => setScreen("splash"),
    90000
  );

  // Background body tint per screen
  useEffect(() => {
    document.body.style.background = "var(--yellow)";
  }, [screen]);

  return (
    <React.Fragment>
      <BgPattern />
      <div className="app" onClick={(e) => {
        // splash: tap anywhere also starts
        if (screen === "splash" && e.target.closest(".splash") && !e.target.closest("button")) {
          // let button handle its own click; don't double-fire
        }
      }}>
        {screen === "splash" && <Splash tweaks={tweaksForUi} onStart={() => setScreen("game")} />}
        {screen === "game"   && <Game   tweaks={tweaksForUi} onWin={() => setScreen("win")} />}
        {screen === "win"    && <Win onRestart={() => setScreen("splash")} />}
      </div>

      <TweaksPanel title="Tweaks" defaultOpen={false}>
        <TweakSection label="Conteúdo">
          <TweakText label="Título"
            value={tweaks.title} onChange={(v) => setTweak("title", v)}
          />
          <TweakText label="Subtítulo (splash)"
            value={tweaks.lede} onChange={(v) => setTweak("lede", v)}
          />
          <TweakText label="Palavras"
            value={tweaks.words} onChange={(v) => setTweak("words", v)}
          />
        </TweakSection>

        <TweakSection label="Jogo">
          <TweakRadio label="Tamanho do grid"
            value={tweaks.gridSize}
            options={[
              { label: "8", value: 8 },
              { label: "9", value: 9 },
              { label: "10", value: 10 },
              { label: "12", value: 12 },
            ]}
            onChange={(v) => setTweak("gridSize", v)}
          />
          <TweakToggle label="Diagonais"
            value={tweaks.diagonals} onChange={(v) => setTweak("diagonals", v)}
          />
          <TweakToggle label="Reset por inatividade"
            value={tweaks.idleReset} onChange={(v) => setTweak("idleReset", v)}
          />
        </TweakSection>

        <TweakSection label="Visual">
          <TweakRadio label="Paleta"
            value={tweaks.palette}
            options={[
              { label: "Amarelo", value: "yellow" },
              { label: "Quente", value: "orange" },
              { label: "Escuro", value: "dark" },
            ]}
            onChange={(v) => setTweak("palette", v)}
          />
        </TweakSection>
      </TweaksPanel>
    </React.Fragment>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
