/* global React */
const { useState: useStateUI } = React;

// ============ V4 "HIPSTER BRUTALIST" PRIMITIVES ============
// Heavy black borders, offset shadows, italic accents, lowercase, rotated stickers.
// Default ink color is #0a0a0a — kept in sync with app.jsx tokens via theme.fg.

const HALFTONE_BG = "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8'><circle cx='1' cy='1' r='1' fill='%23000' opacity='.18'/></svg>\")";

// ----- Hairline rule (used in editorial layouts that survive in some screens)
function Rule({ theme, vertical, style, dashed }) {
  return (
    <div style={{
      background: dashed ? "transparent" : theme.fg,
      borderTop: dashed ? `2px dashed ${theme.fg}` : "none",
      width: vertical ? 2 : "100%",
      height: vertical ? "100%" : (dashed ? 0 : 2),
      ...style,
    }} />
  );
}

// ----- Mono uppercase "eyebrow" / kicker
function Eyebrow({ children, theme, style, color }) {
  return (
    <div style={{
      fontFamily: theme.fonts.mono,
      fontSize: 13,
      fontWeight: 700,
      letterSpacing: "0.08em",
      textTransform: "uppercase",
      color: color || theme.fgDim,
      ...style,
    }}>{children}</div>
  );
}

// ----- Display headline — adapts text transform + weight to branding
function Display({ children, size = 64, theme, italic, style, as }) {
  const Tag = as || "h1";
  const b = theme?.brand;
  return (
    <Tag style={{
      fontFamily: theme.fonts.display,
      fontSize: size,
      fontWeight: b?.fontWeight ?? 800,
      fontStyle: italic ? "italic" : "normal",
      letterSpacing: b?.letterSpacing ?? "-0.04em",
      lineHeight: 0.92,
      textTransform: b?.textTransform ?? "lowercase",
      margin: 0,
      ...style,
    }}>{children}</Tag>
  );
}

// ----- Block: card with border + shadow (adapts to branding)
function Block({ theme, children, style, bg, shadow, hover, onClick }) {
  const [h, setH] = useStateUI(false);
  const ink = theme?.fg || "#0a0a0a";
  const b = theme?.brand;
  const bw = b?.borderWidth ?? 2;
  const sh = shadow ?? (b?.shadowOffset ?? 6);
  const r = b?.radius ?? 0;
  const borderColor = theme?.branding === "playful" ? (theme?.rule || ink) : ink;
  return (
    <div
      onClick={onClick}
      onMouseEnter={() => hover && setH(true)}
      onMouseLeave={() => hover && setH(false)}
      style={{
        background: bg || theme?.card || "#fff8ec",
        border: `${bw}px solid ${borderColor}`,
        borderRadius: r,
        boxShadow: theme?.branding === "playful"
          ? (hover && h ? `0 2px 8px rgba(0,0,0,0.10)` : `0 ${sh}px ${sh * 2.5}px rgba(0,0,0,0.08)`)
          : `${sh}px ${sh}px 0 0 ${ink}`,
        transform: hover && h ? "translate(-2px, -2px)" : "translate(0,0)",
        transition: "transform .12s, box-shadow .12s",
        cursor: hover || onClick ? "pointer" : "default",
        ...style,
      }}
    >{children}</div>
  );
}

// ----- Tag: small mono pill with shadow
function Tag({ theme, children, bg, style, rotate = 0 }) {
  const ink = theme?.fg || "#0a0a0a";
  const playful = theme?.branding === "playful";
  const borderColor = playful ? (theme?.rule || ink) : ink;
  return (
    <span style={{
      display: "inline-block",
      background: bg || theme?.tones?.yellow || "#ffe14a",
      color: ink,
      border: `${playful ? 1.5 : 2}px solid ${borderColor}`,
      borderRadius: playful ? 20 : 0,
      padding: playful ? "4px 14px" : "4px 11px",
      fontFamily: theme?.fonts?.mono || "monospace",
      fontSize: 11, fontWeight: 700,
      letterSpacing: "0.06em", textTransform: "uppercase",
      transform: rotate && !playful ? `rotate(${rotate}deg)` : "none",
      boxShadow: playful ? "0 1px 3px rgba(0,0,0,0.08)" : `2px 2px 0 0 ${ink}`,
      ...style,
    }}>{children}</span>
  );
}

// ----- Sticker: rotated display text, used as kicker
function Sticker({ theme, children, bg, rotate = -4, size = 14, style }) {
  const ink = theme?.fg || "#0a0a0a";
  const playful = theme?.branding === "playful";
  const borderColor = playful ? (theme?.rule || ink) : ink;
  return (
    <span style={{
      display: "inline-block",
      background: bg || theme?.tones?.pink || "#ff3d8a",
      color: playful ? "#fff" : ink,
      border: `${playful ? 0 : 2.5}px solid ${borderColor}`,
      borderRadius: playful ? 8 : 0,
      boxShadow: playful ? "0 2px 8px rgba(0,0,0,0.12)" : `3px 3px 0 0 ${ink}`,
      padding: playful ? "8px 16px" : "6px 14px",
      fontFamily: theme?.fonts?.display || "sans-serif",
      fontWeight: playful ? 700 : 800, fontSize: size,
      textTransform: "uppercase",
      letterSpacing: "0.02em",
      transform: playful ? "none" : `rotate(${rotate}deg)`,
      ...style,
    }}>{children}</span>
  );
}

// ----- Button: adapts border, shadow, radius to branding
function Btn({ theme, children, onClick, variant = "solid", size = "md", style, type, disabled, full, icon }) {
  const [hover, setHover] = useStateUI(false);
  // Fallback: als geen theme is meegegeven, gebruik CSS-variabelen die de App
  // op :root heeft gezet. Zo crasht Btn niet als hij vanuit een sub-component
  // zonder expliciete theme-prop wordt aangeroepen.
  if (!theme) {
    theme = {
      fg: "var(--fg, #0a0a0a)",
      accent: "var(--accent, #2540ff)",
      card: "var(--card, #fff8ec)",
      rule: "var(--rule, #0a0a0a)",
      cream: "var(--cream, #fff8ec)",
      tones: { yellow: "#ffe14a" },
      brand: { radius: 0, borderWidth: 2, shadowOffset: 6, fontWeight: 800 },
      fonts: {
        display: "var(--font-display, 'Bricolage Grotesque', sans-serif)",
        body: "var(--font-body, 'DM Sans', sans-serif)",
        mono: "var(--font-mono, 'Space Mono', monospace)",
        pixel: "var(--font-mono, 'VT323', monospace)",
      },
      branding: "brut",
    };
  }
  const ink = theme.fg;
  const playful = theme?.branding === "playful";
  const b = theme?.brand;
  const r = b?.radius ?? 0;
  const bw = b?.borderWidth ?? 2;
  const sizes = {
    xs: { padding: playful ? "4px 10px" : "4px 8px",   fontSize: 11 },
    sm: { padding: playful ? "8px 16px" : "8px 14px",  fontSize: 13 },
    md: { padding: playful ? "12px 24px" : "12px 22px", fontSize: 15 },
    lg: { padding: playful ? "18px 36px" : "18px 32px", fontSize: 18 },
  };
  // Defensief: onbekende size → val terug op md.
  if (!sizes[size]) size = "md";
  let bg2, color;
  if (variant === "solid")        { bg2 = theme.accent;            color = "#fff"; }
  else if (variant === "ink")     { bg2 = ink;                     color = theme.cream || "#fff8ec"; }
  else if (variant === "yellow")  { bg2 = theme.tones?.yellow;     color = ink; }
  else if (variant === "outline") { bg2 = "transparent";           color = ink; }
  else if (variant === "ghost")   { bg2 = "transparent";           color = ink; }
  else                            { bg2 = theme.card || "#fff8ec"; color = ink; }
  const press = hover && !disabled;
  const borderColor = playful ? (variant === "ghost" || variant === "outline" ? (theme.rule || ink) : "transparent") : ink;
  return (
    <button
      type={type || "button"}
      disabled={disabled}
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        background: bg2, color,
        border: `${bw}px solid ${borderColor}`,
        borderRadius: playful ? (size === "lg" ? r : r * 0.7) : 0,
        boxShadow: variant === "ghost" ? "none" : (
          playful
            ? (press ? "0 1px 2px rgba(0,0,0,0.08)" : "0 2px 8px rgba(0,0,0,0.10)")
            : (press ? `2px 2px 0 0 ${ink}` : `5px 5px 0 0 ${ink}`)
        ),
        transform: press && variant !== "ghost" && !playful ? "translate(3px, 3px)" : (press && playful ? "translateY(1px)" : "translate(0,0)"),
        transition: "all .12s",
        padding: sizes[size].padding,
        fontSize: sizes[size].fontSize,
        fontFamily: theme.fonts.display,
        fontWeight: b?.fontWeight ?? 800,
        textTransform: playful ? "none" : "lowercase",
        letterSpacing: playful ? "0" : "-0.005em",
        cursor: disabled ? "not-allowed" : "pointer",
        opacity: disabled ? 0.4 : 1,
        display: "inline-flex",
        alignItems: "center",
        gap: 8,
        width: full ? "100%" : "auto",
        justifyContent: full ? "center" : "flex-start",
        ...style,
      }}
    >
      {children}
      {icon && <span style={{ fontFamily: theme.fonts.mono, opacity: 0.85 }}>{icon}</span>}
    </button>
  );
}

// ----- Field: adapts border/shadow/radius to branding
function Field({ theme, value, onChange, placeholder, type = "text", autoFocus, name, label, hint }) {
  const ink = theme.fg;
  const playful = theme?.branding === "playful";
  const b = theme?.brand;
  const bw = b?.borderWidth ?? 2;
  const r = b?.radius ?? 0;
  const borderColor = playful ? (theme.rule || ink) : ink;
  return (
    <label style={{ display: "block" }}>
      {label && (
        <div style={{
          fontFamily: theme.fonts.mono, fontSize: 13, fontWeight: playful ? 600 : 700,
          letterSpacing: "0.08em", textTransform: "uppercase",
          marginBottom: 8, color: theme.fgDim,
        }}>{label}</div>
      )}
      <input
        type={type}
        name={name}
        autoFocus={autoFocus}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        style={{
          width: "100%",
          background: theme.card || "#fff8ec",
          color: ink,
          border: `${bw}px solid ${borderColor}`,
          borderRadius: playful ? r * 0.6 : 0,
          boxShadow: playful ? "0 1px 4px rgba(0,0,0,0.06)" : `4px 4px 0 0 ${ink}`,
          padding: "14px 16px",
          fontFamily: theme.fonts.body,
          fontSize: 18, fontWeight: 500,
          outline: "none",
        }}
      />
      {hint && (
        <div style={{ fontFamily: theme.fonts.mono, fontSize: 13, color: theme.fgDim, marginTop: 6 }}>{hint}</div>
      )}
    </label>
  );
}

// ----- Wordmark: official KwistHet logo image (stacked KWIST / HET! design).
// `size` is the rendered height in pixels.
function Wordmark({ size = 80, style }) {
  return (
    <img
      src="/assets/logo.png"
      alt="Kwist het!"
      style={{
        height: size,
        width: "auto",
        display: "inline-block",
        verticalAlign: "middle",
        ...style,
      }}
    />
  );
}

// ----- Monogram: avatar with branding-aware styling
function Monogram({ theme, text, size = 42, color }) {
  const ink = theme.fg;
  const cream = theme.cream || "#fff8ec";
  const playful = theme?.branding === "playful";
  return (
    <div style={{
      width: size, height: size,
      background: color || theme.accent,
      color: "#fff",
      border: playful ? "none" : `2px solid ${ink}`,
      borderRadius: playful ? "50%" : 0,
      boxShadow: playful ? "0 2px 6px rgba(0,0,0,0.12)" : `3px 3px 0 0 ${ink}`,
      display: "grid", placeItems: "center",
      fontFamily: theme.fonts.display, fontWeight: playful ? 700 : 800,
      fontSize: size * 0.36, fontStyle: playful ? "normal" : "italic",
      transform: playful ? "none" : "rotate(-3deg)",
      flexShrink: 0,
    }}>{text}</div>
  );
}

// ----- FigureNum: oversized italic display number
function FigureNum({ theme, children, size = 32, accent }) {
  return (
    <span style={{
      fontFamily: theme.fonts.display,
      fontWeight: 800,
      fontStyle: "italic",
      fontSize: size,
      letterSpacing: "-0.05em",
      lineHeight: 1,
      color: accent ? theme.accent : theme.fg,
    }}>{children}</span>
  );
}

// ----- Masthead: section header with thick rule, replaces editorial Rule sandwich
function Masthead({ theme, eyebrow, title, right }) {
  return (
    <div style={{ marginBottom: 24 }}>
      <div style={{
        display: "flex", justifyContent: "space-between",
        alignItems: "flex-end",
        padding: "14px 0 16px",
        borderBottom: `2.5px solid ${theme.fg}`,
      }}>
        <div>
          {eyebrow && <Eyebrow theme={theme} style={{ marginBottom: 8 }}>{eyebrow}</Eyebrow>}
          <Display theme={theme} size={48} style={{ letterSpacing: "-0.04em" }}>{title}</Display>
        </div>
        {right}
      </div>
    </div>
  );
}

// ----- AppHeader: nav bar that adapts to branding
function AppHeader({ theme, user, onLogout, current, onNav, onAdmin, onSettings }) {
  const ink = theme.fg;
  const cream = theme.cream || "#fff8ec";
  const playful = theme?.branding === "playful";
  const b = theme?.brand;
  const navItems = [
    { id: "dashboard", label: playful ? "Mijn quizzes" : "mijn quizzes", always: true },
    { id: "library",   label: playful ? "Bibliotheek" : "bibliotheek", flag: "nav.library" },
    { id: "stats",     label: playful ? "Resultaten" : "resultaten",  flag: "nav.stats" },
    { id: "trending",  label: playful ? "Trending" : "trending",    flag: "nav.trending" },
    { id: "team",      label: playful ? "Team" : "team",        flag: "nav.team" },
    { id: "training",  label: playful ? "Leertraject" : "leertraject", org: true },
    { id: "reports",   label: playful ? "Rapporten" : "rapporten",   orgRole: ["org_admin", "trainer"] },
    { id: "org-admin", label: playful ? "Organisatie" : "organisatie", orgRole: ["org_admin"] },
  ].filter((n) => {
    if (n.always) return true;
    if (n.flag) return theme.features?.[n.flag];
    if (n.org) return !!user?.organizationId;
    if (n.orgRole) return user?.organizationId && n.orgRole.includes(user?.orgRole);
    return true;
  });

  return (
    <header style={{
      borderBottom: playful ? `1px solid ${theme.rule}` : `2.5px solid ${ink}`,
      background: playful ? theme.card : theme.bg,
      padding: playful ? "12px 32px" : "14px 32px",
      display: "flex", justifyContent: "space-between", alignItems: "center",
      position: "relative",
      boxShadow: playful ? "0 1px 4px rgba(0,0,0,0.04)" : "none",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 24 }}>
        <Wordmark size={playful ? 160 : 200} />
        {!playful && <span style={{ fontFamily: theme.fonts.pixel || theme.fonts.mono, fontSize: 22, color: ink, opacity: 0.5, marginTop: 4 }}>//</span>}
        <nav style={{ display: "flex", gap: playful ? 2 : 4 }}>
          {navItems.map((n) => {
            const active = current === n.id;
            return (
              <button key={n.id} onClick={() => onNav?.(n.id)} style={{
                padding: playful ? "8px 16px" : "6px 12px",
                background: active ? (playful ? `${theme.accent}12` : ink) : "transparent",
                color: active ? (playful ? theme.accent : cream) : (playful ? theme.fgDim : ink),
                fontFamily: theme.fonts.display,
                fontSize: 13, fontWeight: active ? 700 : (playful ? 500 : 700),
                textTransform: playful ? "none" : "lowercase",
                letterSpacing: playful ? "0" : "-0.01em",
                fontStyle: active && !playful ? "italic" : "normal",
                borderRadius: playful ? 8 : 0,
                cursor: "pointer", border: "none",
              }}>{n.label}</button>
            );
          })}
        </nav>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
        {onAdmin && <Btn theme={theme} size="sm" variant="yellow" onClick={onAdmin}>{playful ? "Admin" : "admin ↗"}</Btn>}
        <Btn theme={theme} size="sm" variant={playful ? "outline" : "paper"} onClick={onLogout}>{playful ? "Uitloggen" : "uitloggen"}</Btn>
        <div onClick={() => onNav?.("settings")} title="Instellingen" style={{
          width: 42, height: 42,
          background: theme.accent, color: "#fff",
          border: playful ? "none" : `2.5px solid ${ink}`,
          borderRadius: playful ? "50%" : 0,
          boxShadow: playful ? "0 2px 6px rgba(0,0,0,0.12)" : `3px 3px 0 0 ${ink}`,
          display: "grid", placeItems: "center",
          fontFamily: theme.fonts.display, fontWeight: playful ? 700 : 800, fontSize: 14,
          fontStyle: playful ? "normal" : "italic",
          transform: playful ? "none" : "rotate(-3deg)",
          flexShrink: 0, cursor: "pointer",
        }}>{user.initials}</div>
      </div>
    </header>
  );
}

// ----- Subtle dotted column divider (kept for layouts that still use it)
function DottedCol({ theme, height = "100%" }) {
  return (
    <div style={{
      width: 1, height,
      backgroundImage: `linear-gradient(to bottom, ${theme.fg} 50%, transparent 50%)`,
      backgroundSize: "1px 8px",
      backgroundRepeat: "repeat-y",
    }} />
  );
}

// ----- Animated loader for AI generation wait screens
const GEN_MESSAGES = [
  "De redactie buigt zich over je onderwerp...",
  "Koffie is gezet, vragen worden geschreven...",
  "Onze slimste quizmaster is aan het nadenken...",
  "Even checken of het antwoord klopt...",
  "Afleidende opties verzinnen — dat is een kunst...",
  "Bijna klaar, nog even de puntjes op de i...",
  "We maken het nét iets moeilijker dan je verwacht...",
  "Geen zorgen, de quiz komt eraan...",
  "Wist je dat? De eerste pubquiz was in 1959 in Bolton...",
  "Fun fact: de gemiddelde Belg drinkt 74 liter bier per jaar...",
  "Wist je dat flamingo's alleen roze zijn door hun dieet?",
  "Even geduld — Rome is ook niet op een dag gebouwd...",
  "De vragen worden extra gecontroleerd op correctheid...",
  "Weetje: een groep flamingo's heet een 'flamboyance'...",
  "We zijn bijna klaar, beloofd!",
];

function GeneratingLoader({ theme, elapsed, topic }) {
  const [msgIndex, setMsgIndex] = React.useState(0);
  const [fade, setFade] = React.useState(true);

  React.useEffect(() => {
    const interval = setInterval(() => {
      setFade(false);
      setTimeout(() => {
        setMsgIndex((i) => (i + 1) % GEN_MESSAGES.length);
        setFade(true);
      }, 300);
    }, 3500);
    return () => clearInterval(interval);
  }, []);

  const dots = Math.floor((elapsed * 2) % 4);
  const progress = Math.min(elapsed / 25, 0.95);

  return (
    <div style={{
      padding: "32px 28px",
      border: `2px solid ${theme.fg}`,
      background: theme.bg2,
      position: "relative",
      overflow: "hidden",
    }}>
      {/* progress bar */}
      <div style={{
        position: "absolute", top: 0, left: 0,
        height: 3, background: theme.accent,
        width: `${progress * 100}%`,
        transition: "width 0.5s ease-out",
      }} />

      <div style={{ display: "flex", alignItems: "center", gap: 16, marginBottom: 20 }}>
        <div style={{
          width: 28, height: 28,
          border: `2.5px solid ${theme.rule}`,
          borderTopColor: theme.accent,
          borderRadius: "50%",
          animation: "spin 0.8s linear infinite",
          flexShrink: 0,
        }} />
        <div>
          <div style={{
            fontFamily: theme.fonts.display, fontSize: 22,
            letterSpacing: "-0.02em",
          }}>
            Genereren{".".repeat(dots)}
          </div>
          <Eyebrow theme={theme} style={{ marginTop: 2 }}>
            {elapsed.toFixed(1)} SEC · {(topic || "QUIZ").toUpperCase().slice(0, 40)}
          </Eyebrow>
        </div>
      </div>

      <div style={{
        fontFamily: theme.fonts.body,
        fontSize: 15,
        color: theme.fgDim,
        lineHeight: 1.5,
        minHeight: 24,
        opacity: fade ? 1 : 0,
        transition: "opacity 0.3s ease",
      }}>
        {GEN_MESSAGES[msgIndex]}
      </div>

      <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
    </div>
  );
}

// ── Simple primitives for CORP screens ──

function Card({ theme, children, style, onClick }) {
  const t = theme || {};
  return React.createElement("div", {
    onClick,
    style: {
      background: t.card || "#fff8ec",
      border: `var(--border-width, 2px) solid ${t.rule || "#0a0a0a"}`,
      borderRadius: "var(--radius, 0)",
      boxShadow: `var(--shadow-offset, 6px) var(--shadow-offset, 6px) 0 0 ${t.rule || "#0a0a0a"}`,
      ...style,
    },
  }, children);
}

function H2({ children, style }) {
  return React.createElement("h2", { style: { fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 24, margin: "0 0 4px", letterSpacing: "-0.02em", ...style } }, children);
}

function H3({ children, style }) {
  return React.createElement("h3", { style: { fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 17, margin: "0 0 4px", letterSpacing: "-0.01em", ...style } }, children);
}

function Body({ children, style }) {
  return React.createElement("p", { style: { margin: 0, fontSize: 15, lineHeight: 1.5, ...style } }, children);
}

function Small({ children, style }) {
  return React.createElement("span", { style: { fontSize: 12, opacity: 0.7, lineHeight: 1.4, ...style } }, children);
}

function Input({ style, ...props }) {
  return React.createElement("input", {
    ...props,
    style: {
      padding: "8px 12px", fontSize: 14, fontFamily: "var(--font-body)",
      border: "var(--border-width, 2px) solid var(--rule, #0a0a0a)",
      background: "var(--card, #fff8ec)", color: "var(--fg, #0a0a0a)",
      borderRadius: "var(--radius, 0)", outline: "none",
      ...style,
    },
  });
}

function TabBar({ tabs, activeTab, onTab, theme }) {
  return React.createElement("div", {
    role: "tablist",
    style: {
      display: "flex", gap: 0, borderBottom: `2px solid ${theme?.rule || "#0a0a0a"}`,
    },
  }, tabs.map((t) => React.createElement("button", {
    key: t.id,
    role: "tab",
    "aria-selected": activeTab === t.id,
    onClick: () => onTab(t.id),
    style: {
      padding: "10px 20px", fontSize: 13, fontWeight: activeTab === t.id ? 700 : 500,
      fontFamily: "var(--font-display)", textTransform: "uppercase", letterSpacing: "0.02em",
      background: activeTab === t.id ? (theme?.accent || "#2540ff") : "transparent",
      color: activeTab === t.id ? "#fff" : (theme?.fg || "#0a0a0a"),
      border: "none", borderBottom: activeTab === t.id ? `2px solid ${theme?.accent || "#2540ff"}` : "2px solid transparent",
      cursor: "pointer", marginBottom: -2,
    },
  }, t.label)));
}

window.GeneratingLoader = GeneratingLoader;
window.Rule = Rule;
window.Eyebrow = Eyebrow;
window.Display = Display;
window.Block = Block;
window.Tag = Tag;
window.Sticker = Sticker;
window.Btn = Btn;
window.Field = Field;
window.Wordmark = Wordmark;
window.Monogram = Monogram;
window.FigureNum = FigureNum;
window.Masthead = Masthead;
window.AppHeader = AppHeader;
window.DottedCol = DottedCol;
window.HALFTONE_BG = HALFTONE_BG;
window.Card = Card;
window.H2 = H2;
window.H3 = H3;
window.Body = Body;
window.Small = Small;
window.Input = Input;
window.TabBar = TabBar;
