// about.jsx — Diaval's persona dossier.
// Data sources: diaval_about (config), diaval_about_paragraphs, diaval_about_fact_blocks, diaval_about_facts.
// Each major section can be toggled via show_origin / show_dossier / show_footer in diaval_about.

// Tiny inline-HTML renderer — supports <br/>, <span class="bone|ash|accent">…</span> and <accent>…</accent>.
// Lets the database hold simple inline emphasis without exposing real HTML injection.
function renderInline(html, S) {
  if (!html) return null;
  const tokens = [];
  let rest = html;
  let key = 0;
  const tagRegex = /<(\/?)(\w+)(?:\s+class="([^"]*)")?\s*\/?>/i;
  while (rest.length) {
    const m = rest.match(tagRegex);
    if (!m) { tokens.push(rest); break; }
    if (m.index > 0) tokens.push(rest.slice(0, m.index));
    rest = rest.slice(m.index + m[0].length);
    const close = m[1] === "/";
    const tag = m[2].toLowerCase();
    if (tag === "br") { tokens.push(<br key={`br-${key++}`} />); continue; }
    if (close) { tokens.push({ __close: tag }); continue; }
    tokens.push({ __open: tag, cls: m[3] || "" });
  }
  // Fold open/close pairs into spans
  const out = [];
  const stack = [];
  for (const t of tokens) {
    if (typeof t === "string") {
      if (stack.length) stack[stack.length - 1].children.push(t);
      else out.push(t);
    } else if (React.isValidElement(t)) {
      if (stack.length) stack[stack.length - 1].children.push(t);
      else out.push(t);
    } else if (t.__open) {
      stack.push({ tag: t.__open, cls: t.cls, children: [] });
    } else if (t.__close) {
      const node = stack.pop();
      if (!node) continue;
      const colorMap = { bone: S.bone, ash: S.ash, ashdim: S.ashDim, accent: S.bloodHot };
      const tagName = node.tag;
      // Build an inline style based on the semantic tag.
      // - <accent> → red accent color
      // - <em> / <i> → italic
      // - <small> → smaller text
      // - <backstory> → italic + smaller + muted (for sidenote-style flavor text
      //   like "September 6, 2024…" that isn't part of the main bio)
      // - generic <span class="bone|ash|ashdim|accent"> → colored
      let style;
      if (tagName === "accent") {
        style = { color: S.bloodHot };
      } else if (tagName === "em" || tagName === "i") {
        style = { fontStyle: "italic" };
      } else if (tagName === "small") {
        style = { fontSize: "0.85em" };
      } else if (tagName === "backstory") {
        style = { fontStyle: "italic", fontSize: "0.82em", color: S.ash, letterSpacing: "0.01em" };
      } else {
        const color = colorMap[(node.cls || "").toLowerCase()];
        if (color) style = { color };
      }
      const el = <span key={`s-${key++}`} style={style}>{node.children}</span>;
      if (stack.length) stack[stack.length - 1].children.push(el);
      else out.push(el);
    }
  }
  return out;
}

function FactRow({ label, value, accent, last }) {
  const S = window.shellStyles;
  const { isMobile } = (window.useViewport ? window.useViewport() : { isMobile: false });
  return (
    <div style={{
      display: "grid",
      gridTemplateColumns: isMobile ? "1fr" : "200px 1fr",
      padding: isMobile ? "12px 14px" : "10px 16px",
      borderBottom: last ? "none" : `1px dashed ${S.concreteHi}`,
      gap: isMobile ? 4 : 18, alignItems: "baseline",
    }}>
      <div style={{ fontSize: 12, color: S.ashDim, letterSpacing: "0.3em", fontFamily: S.meta }}>
        {label}
      </div>
      <div style={{
        fontSize: 13, color: accent ? S.bloodHot : S.bone,
        fontFamily: S.meta, letterSpacing: "0.02em", lineHeight: 1.4,
      }}>
        {value}
      </div>
    </div>
  );
}

function FactBlock({ block, facts }) {
  const S = window.shellStyles;
  return (
    <div style={{ border: `1px solid ${S.concreteHi}`, background: S.raven }}>
      <div style={{
        padding: "10px 16px", borderBottom: `1px solid ${S.concreteHi}`,
        background: S.concrete,
        display: "flex", justifyContent: "space-between", alignItems: "center",
        fontSize: 12, letterSpacing: "0.3em",
      }}>
        <span style={{ color: S.bloodHot }}>◢ {block.title}</span>
        <span style={{ color: S.ashDim }}>{block.code}</span>
      </div>
      <div>
        {facts.map((row, i) => (
          <FactRow key={row.id} label={row.label} value={row.value}
            accent={block.accent_all || row.accent}
            last={i === facts.length - 1}
          />
        ))}
      </div>
    </div>
  );
}

function AboutPage({ tab, onTabChange }) {
  const S = window.shellStyles;
  const { isMobile } = (window.useViewport ? window.useViewport() : { isMobile: false });
  const [config, setConfig] = React.useState(null);
  const [paragraphs, setParagraphs] = React.useState([]);
  const [factBlocks, setFactBlocks] = React.useState([]);
  const [facts, setFacts] = React.useState([]);
  const [gallery, setGallery] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [loadError, setLoadError] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const sb = window.diavalSupabase;
        const [cfg, paras, blocks, rows, gal] = await Promise.all([
          sb.from("diaval_about").select("*").eq("id", 1).maybeSingle(),
          sb.from("diaval_about_paragraphs").select("id, body, position").eq("is_visible", true).order("position", { ascending: true }),
          sb.from("diaval_about_fact_blocks").select("id, slug, title, code, full_width, accent_all, position").eq("is_visible", true).order("position", { ascending: true }),
          sb.from("diaval_about_facts").select("id, block_id, label, value, accent, position").eq("is_visible", true).order("position", { ascending: true }),
          sb.from("diaval_about_gallery").select("id, image_url, caption, alt_text, position, object_position").eq("is_visible", true).order("position", { ascending: true }),
        ]);
        if (cancelled) return;
        if (cfg.error) throw cfg.error;
        if (paras.error) throw paras.error;
        if (blocks.error) throw blocks.error;
        if (rows.error) throw rows.error;
        if (gal.error) throw gal.error;
        setConfig(cfg.data || null);
        setParagraphs(paras.data || []);
        setFactBlocks(blocks.data || []);
        setFacts(rows.data || []);
        setGallery(gal.data || []);
      } catch (err) {
        if (!cancelled) setLoadError(err.message);
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  if (loading) {
    return (
      <Shell tab={tab} onTabChange={onTabChange} page="002" broadcast="ABOUT · DOSSIER 001 · D//V">
        <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 13, color: S.ashDim, letterSpacing: "0.3em" }}>
          ⸺ TUNING SIGNAL ⸺
        </div>
      </Shell>
    );
  }
  if (loadError || !config) {
    return (
      <Shell tab={tab} onTabChange={onTabChange} page="002" broadcast="ABOUT · DOSSIER 001 · D//V">
        <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 12, padding: 40 }}>
          <div style={{ fontSize: 13, color: S.bloodHot, letterSpacing: "0.3em" }}>◢ DOSSIER FEED CORRUPTED</div>
          <div style={{ fontSize: 13, color: S.ash, fontStyle: "italic", maxWidth: 600, textAlign: "center" }}>{loadError || "no config"}</div>
        </div>
      </Shell>
    );
  }

  return (
    <Shell tab={tab} onTabChange={onTabChange} page="002" broadcast="ABOUT · DOSSIER 001 · D//V">
      <div style={{
        position: isMobile ? "relative" : "absolute",
        inset: isMobile ? "auto" : 0,
        overflow: isMobile ? "visible" : "auto",
      }}>
        {/* page header */}
        <div style={{ padding: isMobile ? "20px 16px 16px" : "32px 56px 20px", borderBottom: `1px solid ${S.concreteHi}` }}>
          <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em", marginBottom: 8 }}>
            {config.hero_eyebrow}
          </div>
          <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", justifyContent: "space-between", alignItems: isMobile ? "flex-start" : "flex-end", gap: isMobile ? 12 : 32 }}>
            <h2 style={{
              margin: 0, fontFamily: S.display, fontSize: isMobile ? 28 : 56, lineHeight: 0.92,
              letterSpacing: "-0.02em", color: S.bone,
            }}>
              {config.hero_title_main}<span style={{ color: S.bloodHot }}>{config.hero_title_accent}</span>
            </h2>
            {config.hero_sidebar && (
              <div style={{ fontSize: 13, color: S.ash, letterSpacing: "0.04em", maxWidth: 360, lineHeight: 1.5 }}>
                {renderInline(config.hero_sidebar, S)}
              </div>
            )}
          </div>
        </div>

        {/* PART ONE — narrative backstory */}
        {config.show_origin && (
        <section style={{
          padding: isMobile ? "32px 16px 28px" : "48px 56px 40px",
          display: "grid",
          gridTemplateColumns: isMobile ? "1fr" : "300px 1fr",
          gap: isMobile ? 24 : 56,
        }}>
          {/* portrait column */}
          <div style={{ maxWidth: isMobile ? 240 : "100%", margin: isMobile ? "0 auto" : 0 }}>
            <div style={{
              position: "relative", aspectRatio: "3 / 4",
              border: `1px solid ${S.concreteHi}`, overflow: "hidden",
              background: `linear-gradient(180deg, #1a1014 0%, #050505 100%)`,
            }}>
              {config.portrait_url ? (
                <img
                  src={config.portrait_url}
                  alt={config.portrait_top_label || "portrait"}
                  style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", opacity: 0.9 }}
                />
              ) : (
                <svg viewBox="0 0 300 400" style={{ position: "absolute", inset: 0, width: "100%", height: "100%" }}>
                  <defs>
                    <radialGradient id="portrait-glow" cx="50%" cy="35%" r="60%">
                      <stop offset="0%" stopColor="#be211e" stopOpacity="0.35" />
                      <stop offset="100%" stopColor="#be211e" stopOpacity="0" />
                    </radialGradient>
                  </defs>
                  <rect width="300" height="400" fill="url(#portrait-glow)" />
                  <path d="M30 400 L30 320 Q60 290 110 280 L110 230 Q90 215 90 180 Q90 130 150 125 Q210 130 210 180 Q210 215 190 230 L190 280 Q240 290 270 320 L270 400 Z"
                    fill="#0a0a0a" stroke="#e8e2d0" strokeWidth="0.5" strokeOpacity="0.3" />
                  <ellipse cx="150" cy="170" rx="55" ry="62" fill="#1a1014" stroke="#e8e2d0" strokeWidth="0.3" strokeOpacity="0.4" />
                  <ellipse cx="130" cy="165" rx="3" ry="2" fill="#e8e2d0" />
                  <ellipse cx="170" cy="165" rx="3" ry="2" fill="#e8e2d0" />
                  <line x1="125" y1="160" x2="138" y2="160" stroke="#be211e" strokeWidth="0.8" />
                  <line x1="162" y1="160" x2="175" y2="160" stroke="#be211e" strokeWidth="0.8" />
                  {Array.from({ length: 16 }).map((_, i) => (
                    <path key={i} d={`M${100 + i * 6} 110 Q${110 + i * 6} ${100 - (i % 3) * 8} ${120 + i * 6} 130`}
                      stroke="#0a0a0a" strokeWidth="3" fill="none" strokeLinecap="round" />
                  ))}
                  <rect x="0" y="180" width="300" height="2" fill="#be211e" opacity="0.5" />
                  <rect x="0" y="240" width="300" height="1" fill="#e8e2d0" opacity="0.3" />
                  <g stroke="#be211e" strokeWidth="0.6" fill="none">
                    <line x1="20" y1="20" x2="40" y2="20" />
                    <line x1="30" y1="10" x2="30" y2="30" />
                  </g>
                  <g stroke="#be211e" strokeWidth="0.6" fill="none">
                    <line x1="260" y1="380" x2="280" y2="380" />
                    <line x1="270" y1="370" x2="270" y2="390" />
                  </g>
                </svg>
              )}
              <div style={{ position: "absolute", inset: 0, filter: "url(#ind-noise)", opacity: 0.5, mixBlendMode: "overlay", pointerEvents: "none" }} />
              <div style={{ position: "absolute", top: 14, left: 14, fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em", textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>
                {config.portrait_top_label}
              </div>
              <div style={{ position: "absolute", bottom: 14, left: 14, fontSize: 12, color: S.bone, letterSpacing: "0.25em", lineHeight: 1.7, textShadow: "0 1px 4px rgba(0,0,0,0.7)" }}>
                {renderInline(config.portrait_bottom_html, S)}
              </div>
            </div>
            <div style={{ marginTop: 14, fontSize: 12, color: S.ashDim, letterSpacing: "0.3em", display: "flex", justifyContent: "space-between" }}>
              <span>{config.portrait_id}</span>
              <span>{config.portrait_confidence}</span>
            </div>
          </div>

          {/* narrative column */}
          <div>
            <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.4em", marginBottom: 8 }}>
              {config.origin_eyebrow}
            </div>
            <h3 style={{
              margin: 0, fontFamily: S.display, fontSize: isMobile ? 22 : 36, color: S.bone,
              letterSpacing: "-0.01em", lineHeight: 1, marginBottom: isMobile ? 16 : 24,
            }}>
              {config.origin_title}
            </h3>

            <div style={{ fontFamily: S.meta, fontSize: 14, lineHeight: 1.85, color: S.bone, letterSpacing: "0.005em" }}>
              {paragraphs.map((p, i) => (
                <p key={p.id} style={{ margin: 0, marginBottom: 18 }}>
                  {i === 0 && (
                    <span style={{
                      fontFamily: S.display, fontSize: isMobile ? 40 : 56, color: S.bloodHot,
                      float: "left", lineHeight: 0.85, marginRight: 10, marginTop: 4,
                    }}>{(p.body || "").trim().charAt(0).toUpperCase()}</span>
                  )}
                  {i === 0 ? renderInline((p.body || "").replace(/^./, ""), S) : renderInline(p.body, S)}
                </p>
              ))}

              {config.origin_quote_body && (
                <p style={{ margin: 0, color: S.ash, borderLeft: `2px solid ${S.bloodHot}`, paddingLeft: 14, fontStyle: "italic" }}>
                  {config.origin_quote_body}
                  <span style={{ display: "block", marginTop: 8, fontSize: 13, color: S.ashDim, letterSpacing: "0.25em", fontStyle: "normal" }}>
                    {config.origin_quote_author}
                  </span>
                </p>
              )}
            </div>
          </div>
        </section>
        )}

        {/* PART TWO — dossier facts */}
        {config.show_dossier && (
        <section style={{
          padding: isMobile ? "32px 16px 32px" : "48px 56px 56px",
          borderTop: `1px solid ${S.concreteHi}`,
          background: `linear-gradient(180deg, ${S.raven} 0%, #050505 100%)`,
        }}>
          <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", justifyContent: "space-between", alignItems: isMobile ? "flex-start" : "baseline", marginBottom: isMobile ? 18 : 28, gap: isMobile ? 12 : 24 }}>
            <div>
              <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.4em", marginBottom: 8 }}>
                {config.dossier_eyebrow}
              </div>
              <h3 style={{
                margin: 0, fontFamily: S.display, fontSize: isMobile ? 22 : 36, color: S.bone,
                letterSpacing: "-0.01em", lineHeight: 1,
              }}>
                {config.dossier_title_main}<span style={{ color: S.bloodHot }}>{config.dossier_title_accent}</span>
              </h3>
            </div>
            <div style={{ textAlign: isMobile ? "left" : "right", fontSize: 12, color: S.ashDim, letterSpacing: "0.3em", lineHeight: 1.7, whiteSpace: "pre-line" }}>
              {config.dossier_meta}
            </div>
          </div>

          <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: isMobile ? 16 : 24 }}>
            {factBlocks.map((b) => {
              const blockFacts = facts.filter(f => f.block_id === b.id);
              return (
                <div key={b.id} style={b.full_width ? { gridColumn: "1 / -1" } : undefined}>
                  <FactBlock block={b} facts={blockFacts} />
                </div>
              );
            })}
          </div>

          {/* footer note */}
          {config.show_footer && (
            <div style={{
              marginTop: 32, padding: "20px 24px", border: `1px solid ${S.concreteHi}`,
              borderLeft: `3px solid ${S.bloodHot}`, background: "rgba(255,255,255,0.02)",
              display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 18, alignItems: "center",
            }}>
              <div style={{ fontFamily: S.display, fontSize: 36, color: S.bloodHot, letterSpacing: "-0.02em", lineHeight: 1 }}>
                ⌬
              </div>
              <div style={{ fontSize: 12, color: S.ash, fontFamily: S.meta, lineHeight: 1.65, letterSpacing: "0.01em" }}>
                {renderInline(config.footer_html, S)}
              </div>
              <div style={{ fontSize: 12, color: S.ashDim, letterSpacing: "0.3em", textAlign: "right" }}>
                {config.footer_signoff}<br/>
                <span style={{ color: S.bloodHot }}>STAY CORRUPTED.</span>
              </div>
            </div>
          )}
        </section>
        )}

        {/* PART FOUR — gallery carousel (horizontal scroll strip with snap) */}
        {config.show_gallery && gallery.length > 0 && (
          <GallerySection config={config} gallery={gallery} S={S} isMobile={isMobile} />
        )}

        {/* PART FIVE — social links. SocialIcons returns null when nothing's set,
            so this section quietly disappears if no platforms have URLs. */}
        <FindHimSection S={S} isMobile={isMobile} />
      </div>
    </Shell>
  );
}

// Renders only if at least one social row has is_visible + url set.
function FindHimSection({ S, isMobile }) {
  const Socials = window.SocialIcons;
  const [hasAny, setHasAny] = React.useState(false);
  React.useEffect(() => {
    let cancelled = false;
    window.diavalSupabase.from("diaval_socials").select("url, is_visible")
      .eq("is_visible", true).then(({ data }) => {
        if (cancelled) return;
        setHasAny((data || []).some(r => r.url && String(r.url).trim()));
      });
    return () => { cancelled = true; };
  }, []);
  if (!hasAny || !Socials) return null;
  return (
    <section style={{
      padding: isMobile ? "32px 16px" : "48px 56px 56px",
      borderTop: `1px solid ${S.concreteHi}`,
    }}>
      <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.4em", marginBottom: 8 }}>
        ⸺ SECTION 05 ⸺
      </div>
      <h3 style={{
        margin: 0, fontFamily: S.display, fontSize: isMobile ? 22 : 32, color: S.bone,
        letterSpacing: "-0.01em", marginBottom: 18,
      }}>
        FIND <span style={{ color: S.bloodHot }}>HIM.</span>
      </h3>
      <Socials S={S} />
    </section>
  );
}

// Horizontal scroll-snap carousel. Renders at the bottom of the About page.
function GallerySection({ config, gallery, S, isMobile }) {
  const stripRef = React.useRef(null);

  const scrollByCards = (dir) => {
    const el = stripRef.current;
    if (!el) return;
    // Step is the width of one card + gap. We measure the first child.
    const first = el.firstElementChild;
    const step = first ? first.getBoundingClientRect().width + 14 : 320;
    el.scrollBy({ left: dir * step, behavior: "smooth" });
  };

  const cardW = isMobile ? 240 : 320;
  const cardH = isMobile ? 240 : 320;

  return (
    <section style={{
      padding: isMobile ? "32px 16px 32px" : "48px 56px 56px",
      borderTop: `1px solid ${S.concreteHi}`,
    }}>
      <div style={{
        display: "flex", flexDirection: isMobile ? "column" : "row", justifyContent: "space-between",
        alignItems: isMobile ? "flex-start" : "baseline",
        gap: isMobile ? 12 : 24, marginBottom: isMobile ? 18 : 28,
      }}>
        <div>
          <div style={{ fontSize: 12, color: S.bloodHot, letterSpacing: "0.3em", marginBottom: 8 }}>
            {config.gallery_eyebrow || "// V. ARCHIVE / FRAGMENTS"}
          </div>
          <h3 style={{
            margin: 0, fontFamily: S.display, fontSize: isMobile ? 22 : 36, color: S.bone,
            letterSpacing: "-0.01em", lineHeight: 1,
          }}>
            {config.gallery_title_main || "MORE "}
            <span style={{ color: S.bloodHot }}>{config.gallery_title_accent || "FRAGMENTS"}</span>
          </h3>
        </div>
        {!isMobile && gallery.length > 1 && (
          <div style={{ display: "flex", gap: 8 }}>
            <button onClick={() => scrollByCards(-1)} aria-label="scroll left" style={{
              background: "transparent", border: `1px solid ${S.concreteHi}`, color: S.bone,
              padding: "8px 14px", fontFamily: S.meta, fontSize: 14, letterSpacing: "0.2em", cursor: "pointer",
            }}>←</button>
            <button onClick={() => scrollByCards(1)} aria-label="scroll right" style={{
              background: "transparent", border: `1px solid ${S.concreteHi}`, color: S.bone,
              padding: "8px 14px", fontFamily: S.meta, fontSize: 14, letterSpacing: "0.2em", cursor: "pointer",
            }}>→</button>
          </div>
        )}
      </div>

      <div
        ref={stripRef}
        style={{
          display: "flex", gap: 14, overflowX: "auto", overflowY: "hidden",
          scrollSnapType: "x mandatory", WebkitOverflowScrolling: "touch",
          paddingBottom: 8,
          // hide native scrollbar but keep functional — clean industrial look
          scrollbarWidth: "thin", scrollbarColor: `${S.concreteHi} transparent`,
        }}
      >
        {gallery.map((g, i) => (
          <figure key={g.id} style={{
            margin: 0, flex: `0 0 ${cardW}px`, scrollSnapAlign: "start",
            display: "flex", flexDirection: "column", gap: 10,
          }}>
            <div style={{
              width: cardW, height: cardH, position: "relative", overflow: "hidden",
              border: `1px solid ${S.concreteHi}`, background: S.raven,
            }}>
              <img src={g.image_url} alt={g.alt_text || g.caption || ""} loading="lazy"
                style={{
                  width: "100%", height: "100%", objectFit: "cover", display: "block",
                  objectPosition: g.object_position || "center",
                }} />
              <div style={{
                position: "absolute", top: 8, left: 10, fontSize: 10, color: S.ash,
                letterSpacing: "0.3em", fontFamily: S.meta, mixBlendMode: "difference",
              }}>
                FILE {String(i + 1).padStart(2, "0")} / {String(gallery.length).padStart(2, "0")}
              </div>
            </div>
            {g.caption && (
              <figcaption style={{
                fontSize: 11, color: S.ash, fontFamily: S.meta, letterSpacing: "0.18em",
                lineHeight: 1.5, maxWidth: cardW,
              }}>
                {g.caption}
              </figcaption>
            )}
          </figure>
        ))}
      </div>
    </section>
  );
}

window.AboutPage = AboutPage;
window.renderAboutInline = renderInline;
