const editorialPalettes = {
  cream: { bg: "#f8f5ef", paper: "#ffffff", ink: "#1a1714", secondary: "#4a4540", muted: "#8b857a", rule: "#e6e0d4", accent: "#8a4b2a" },
  sand:  { bg: "#ece7dc", paper: "#f8f5ef", ink: "#1a1714", secondary: "#4a4540", muted: "#8b857a", rule: "#d8cfbc", accent: "#4a3a1a" },
  bone:  { bg: "#eeeae3", paper: "#ffffff", ink: "#1a1714", secondary: "#4a4540", muted: "#8b857a", rule: "#dcd4c4", accent: "#2a5c4a" },
};

function EditorialVariant({ backend, density, accent, fontPair, bubble }) {
  const { messages, pending, debug, send, reset } = useFetchChat({ backend });
  const suggestions = useRotatingSuggestions({ visible: 3 });
  const [input, setInput] = React.useState("");
  const [showDebug, setShowDebug] = React.useState(false);
  const scrollRef = React.useRef(null);

  const palette = editorialPalettes[accent] || editorialPalettes.cream;

  const gap = density === "compact" ? 16 : density === "cozy" ? 40 : 26;
  const fontSize = density === "compact" ? 16 : density === "cozy" ? 19 : 17.5;

  React.useEffect(() => {
    const el = scrollRef.current;
    if (el) el.scrollTop = el.scrollHeight;
  }, [messages.length, pending]);

  React.useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "d") {
        e.preventDefault(); setShowDebug(s => !s);
      }
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault(); reset();
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [reset]);

  const submit = (e) => {
    e?.preventDefault();
    const v = input.trim();
    if (!v || pending) return;
    setInput("");
    send(v);
  };

  const radii = bubble === "squared" ? 2 : bubble === "tail" ? 18 : 12;

  return (
    <div style={{
      position: "absolute", inset: 0,
      background: palette.bg, color: palette.ink,
      fontFamily: fontPair.body,
      display: "flex", flexDirection: "column",
      overflow: "hidden",
    }}>
      <header style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "18px 32px",
        color: palette.muted, fontSize: 12, letterSpacing: 1.2, textTransform: "uppercase",
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <PawGlyph size={14} color={palette.accent} />
          <span>Fetch Good Boi · Demo, generative</span>
        </div>
        <div style={{ display: "flex", gap: 18, textTransform: "none", letterSpacing: 0 }}>
          <button onClick={reset} style={editLink(palette)}>Clear</button>
          <button onClick={() => setShowDebug(s => !s)} style={editLink(palette)}>Debug</button>
        </div>
      </header>

      <div ref={scrollRef} style={{
        flex: 1, overflowY: "auto",
        display: "flex", justifyContent: "center",
      }}>
        <div style={{
          width: "min(620px, 88%)",
          padding: "24px 0 40px",
        }}>
          <h1 style={{
            fontFamily: fontPair.display, fontWeight: 400,
            fontSize: "clamp(44px, 6vw, 68px)",
            lineHeight: 1.02, letterSpacing: -0.5,
            margin: "16px 0 12px",
          }}>
            This is <em style={{ fontStyle: "italic" }}>Fetch</em>.
          </h1>
          <p style={{
            fontFamily: fontPair.body, fontSize: 14.5, lineHeight: 1.65,
            color: palette.secondary, maxWidth: 640, letterSpacing: "0.015em",
            margin: "0 0 28px",
          }}>
            Fetch is a dog-loving chatbot powered by Meta's blenderbot-400M-distill.
            It has a four-turn context window and a tiny keyword lookup layer.
            Not a smart boi, just a good boi.
          </p>

          <div style={{
            borderTop: `1px solid ${palette.rule}`,
            paddingTop: 8,
          }}>
            {messages.filter(m => !m.pending).map((m, i) => (
              <EditorialTurn
                key={m.id}
                msg={m}
                palette={palette}
                fontPair={fontPair}
                fontSize={fontSize}
                gap={gap}
                isFirst={i === 0}
                radii={radii}
              />
            ))}
            {pending && (
              <div style={{
                color: palette.muted, fontStyle: "italic",
                padding: `${gap / 2}px 0`, fontFamily: fontPair.display,
                fontSize: fontSize + 1,
              }}>
                Fetching an answer<EllipsisAnim />
              </div>
            )}
          </div>
        </div>
      </div>

      <div style={{
        borderTop: `1px solid ${palette.rule}`,
        background: palette.paper,
        padding: "16px 0 22px",
        display: "flex", justifyContent: "center",
      }}>
        <form onSubmit={submit} style={{
          width: "min(620px, 88%)",
          display: "flex", flexDirection: "column", gap: 12,
        }}>
          <EditorialSuggestions
            suggestions={suggestions}
            onPick={(s) => !pending && send(s)}
            palette={palette}
            fontPair={fontPair}
            pending={pending}
          />
          <div style={{
            display: "flex", alignItems: "center", gap: 10,
            borderBottom: `1px solid ${palette.ink}`,
            paddingBottom: 8,
          }}>
            <input
              value={input}
              onChange={e => setInput(e.target.value)}
              placeholder="Ask Fetch something"
              autoFocus
              disabled={pending}
              style={{
                flex: 1, background: "transparent", border: "none", outline: "none",
                color: palette.ink, fontFamily: fontPair.body,
                fontSize: 20,
              }}
            />
            <button type="submit" disabled={pending || !input.trim()} style={{
              background: palette.ink, color: palette.paper,
              border: "none", padding: "10px 20px",
              borderRadius: 999, cursor: pending || !input.trim() ? "default" : "pointer",
              fontFamily: fontPair.body, fontSize: 14, letterSpacing: 0.5,
              opacity: pending || !input.trim() ? 0.4 : 1,
              minHeight: 40,
            }}>Ask →</button>
          </div>
        </form>
      </div>

      {showDebug && (
        <DebugPanel
          debug={debug}
          onClose={() => setShowDebug(false)}
          palette={{ bg: "#1a1714", fg: "#f8f5ef", dim: "#8b857a", accent: palette.accent, muted: "#3a352e" }}
          font={fontPair.mono}
        />
      )}
    </div>
  );
}

function EditorialTurn({ msg, palette, fontPair, fontSize, gap, isFirst, radii }) {
  const isUser = msg.role === "user";
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => {
    const id = requestAnimationFrame(() => setMounted(true));
    return () => cancelAnimationFrame(id);
  }, []);
  return (
    <div style={{
      padding: `${gap / 2}px 0`,
      borderTop: isFirst ? "none" : `1px solid ${palette.rule}`,
      opacity: mounted ? 1 : 0,
      transform: mounted ? "translateY(0)" : "translateY(6px)",
      transition: "opacity .22s ease, transform .22s ease",
    }}>
      <div style={{
        fontFamily: fontPair.body, fontSize: 11, letterSpacing: 1.4,
        textTransform: "uppercase", color: palette.muted,
        marginBottom: 6,
        display: "flex", alignItems: "center", gap: 10,
      }}>
        <span>{isUser ? "You" : "Fetch"}</span>
        {!isUser && msg.fact && msg.source === "fact" && !msg.pending && (
          <span style={{
            background: palette.accent, color: palette.paper,
            padding: "2px 7px", borderRadius: radii,
            fontSize: 10, letterSpacing: 0.6, textTransform: "none",
          }}>fact · {msg.fact.keyword}</span>
        )}
      </div>
      <div style={{
        fontFamily: isUser ? fontPair.body : fontPair.display,
        fontSize: isUser ? fontSize : fontSize + 3,
        lineHeight: 1.5,
        color: palette.ink,
      }}>
        {msg.pending ? <span style={{ color: palette.muted }}>…</span> : msg.content}
      </div>
    </div>
  );
}

function EditorialSuggestions({ suggestions, onPick, palette, fontPair, pending }) {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
      {suggestions.map((s, i) => (
        <button
          key={s}
          type="button"
          onClick={() => onPick(s)}
          disabled={pending}
          style={{
            border: `1px solid ${palette.rule}`,
            background: "transparent", color: palette.ink,
            fontFamily: fontPair.body, fontSize: 13,
            padding: "7px 14px", borderRadius: 999,
            cursor: pending ? "default" : "pointer",
            opacity: pending ? 0.5 : 1,
            animation: `fetch-fadein .4s ease ${i * 60}ms both`,
          }}
        >{s}</button>
      ))}
    </div>
  );
}

function editLink(p) {
  return {
    background: "transparent", border: "none", padding: "4px 0",
    color: p.muted, fontSize: 13, cursor: "pointer", fontFamily: "inherit",
  };
}

function PawGlyph({ size = 14, color = "#8a4b2a" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 20 20" fill={color} aria-hidden="true">
      <circle cx="5" cy="6" r="2"/>
      <circle cx="10" cy="4" r="2"/>
      <circle cx="15" cy="6" r="2"/>
      <circle cx="17" cy="11" r="1.7"/>
      <path d="M10 9c-3 0-5.5 2.2-5.5 5 0 1.9 1.5 3 3.5 3h4c2 0 3.5-1.1 3.5-3 0-2.8-2.5-5-5.5-5z"/>
    </svg>
  );
}

function EllipsisAnim() {
  const [n, setN] = React.useState(1);
  React.useEffect(() => {
    const id = setInterval(() => setN(x => (x % 3) + 1), 380);
    return () => clearInterval(id);
  }, []);
  return <span>{".".repeat(n)}</span>;
}

Object.assign(window, { EditorialVariant });
