/* ship-happens.jsx — "Ship Happens!": AIRS across the CI/CD pipeline.
   A tidy, read-only ONE-PAGER (route #/shiphappens, constant key="shiphappens"),
   in the spirit of Chiquitito — the hub card is just a card; ALL the pipeline
   detail lives here, opened when you click it.

   A full MLOps pipeline on GCP Cloud Build with Prisma AIRS at every gate. The
   page reads its stages straight from the PILLARS data (single source of truth)
   and hands off to the real Cloud Build console via ONE primary link-out, read
   from the window.LASTROSE_BACKENDS.cloudBuildUrl SEAM — never a hardcoded URL.
   With no overlay wired the button renders DISABLED, so the export stays
   self-contained. GCP-blue theme; the AIRS gates run a brighter blue, the two
   failure points run red. */

/* ---- GCP-blue palette ---- */
const SH = {
  mono: "'JetBrains Mono', ui-monospace, monospace",
  sans: "'Manrope', system-ui, sans-serif",
  serif: "'Spectral', serif",
  page: "#eef2fb",
  surface: "#ffffff",
  surfaceAlt: "#f4f7fe",
  raised: "#e9f0fc",
  line: "rgba(40,70,130,0.16)",
  lineSoft: "rgba(40,70,130,0.09)",
  ink: "#15233f",
  sub: "#4a5a78",
  faint: "#8593ad",
  blue: "#1a73e8",
  blueDeep: "#1557b0",
  blueInk: "#ffffff",
  blueSoft: "rgba(26,115,232,0.10)",
  blueBorder: "rgba(26,115,232,0.42)",
  danger: "#dc2626",
  dangerSoft: "rgba(220,38,38,0.08)",
  dangerBorder: "rgba(220,38,38,0.4)",
  ambient: "radial-gradient(900px 380px at 50% -10%, rgba(66,133,244,0.16), transparent 70%), radial-gradient(720px 320px at 92% 112%, rgba(26,115,232,0.10), transparent 70%)",
};

function ShSectionLabel({ children }) {
  return (
    <div className="mb-3 flex items-center gap-2.5 text-[11px] font-bold uppercase tracking-[0.18em]" style={{ color: SH.faint, fontFamily: SH.mono }}>
      <span className="inline-block h-px w-7" style={{ background: SH.line }} /> {children}
    </div>
  );
}

/* one step in the vertical pipeline timeline */
function PipelineStep({ s, last }) {
  const guarded = s.airs || s.gate;
  const nodeBg = s.blocked ? SH.danger : s.gate ? SH.surface : s.airs ? SH.blue : SH.surface;
  const nodeFg = s.blocked || s.airs ? "#fff" : SH.sub;
  const nodeBorder = s.blocked ? SH.danger : s.airs ? SH.blue : SH.line;
  return (
    <div className="relative flex gap-4 pb-5 last:pb-0">
      {/* rail */}
      <div className="relative flex w-9 shrink-0 flex-col items-center">
        <span className="flex h-9 w-9 items-center justify-center rounded-full text-[13px] font-bold" style={{ background: nodeBg, color: nodeFg, border: `1.5px solid ${nodeBorder}`, fontFamily: SH.mono }}>{s.n}</span>
        {!last && <span className="mt-1 w-px flex-1" style={{ background: SH.line }} />}
      </div>
      {/* card */}
      <div className="min-w-0 flex-1 rounded-2xl px-4 py-3.5" style={{ background: s.blocked ? SH.dangerSoft : SH.surface, border: `1px solid ${s.blocked ? SH.dangerBorder : guarded ? SH.blueBorder : SH.line}` }}>
        <div className="flex flex-wrap items-center gap-2.5">
          <span className="text-[15.5px] font-extrabold tracking-[-0.01em]" style={{ color: SH.ink, fontFamily: SH.sans }}>{s.label}</span>
          <span className="text-[11px] font-semibold uppercase tracking-[0.1em]" style={{ color: SH.faint, fontFamily: SH.mono }}>{s.sub}</span>
          {s.airs && (
            <span className="inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.1em]" style={{ background: SH.blueSoft, color: SH.blue, border: `1px solid ${SH.blueBorder}`, fontFamily: SH.mono }}>🛡️ AIRS</span>
          )}
          {s.gate && (
            <span className="inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.1em]" style={{ background: SH.raised, color: SH.sub, border: `1px solid ${SH.line}`, fontFamily: SH.mono }}>⛔ Gate</span>
          )}
        </div>
        {s.note && (
          <p className="mt-1.5 text-[13px] leading-relaxed" style={{ color: s.blocked ? SH.danger : SH.sub }}>
            {s.blocked && <span className="font-bold">⛔ </span>}{s.note}
          </p>
        )}
      </div>
    </div>
  );
}

/* the PRIMARY CTA — "Open in Cloud Build" (seam-backed, mock-safe-disabled) */
function OpenInCloudBuild({ item }) {
  const url = (window.LASTROSE_BACKENDS && window.LASTROSE_BACKENDS.cloudBuildUrl) || null;
  const live = !!url;
  return (
    <div className="rounded-2xl px-6 py-6" style={{ background: live ? SH.blueSoft : SH.surfaceAlt, border: `1px solid ${live ? SH.blueBorder : SH.line}` }}>
      <div className="text-[17px] font-extrabold" style={{ color: SH.ink, fontFamily: SH.sans }}>Watch the builds run</div>
      <p className="mt-1 text-[13px] leading-relaxed" style={{ color: SH.sub }}>
        The button opens the <span className="font-semibold">live GCP Cloud Build console</span>, where every stage above runs as a real build — a poisoned model is blocked before it can train, and a tampered build never deploys.
      </p>
      <div className="mt-4">
        {live ? (
          <a href={url} target="_blank" rel="noopener noreferrer"
            className="flex w-full items-center justify-center gap-2.5 rounded-xl px-5 py-3.5 text-[15px] font-bold transition-all hover:-translate-y-0.5 active:scale-[0.99]"
            style={{ background: SH.blue, color: SH.blueInk, boxShadow: "0 14px 32px -16px rgba(26,115,232,0.7)" }}>
            {item.titleImg && <img src={item.titleImg} alt="" className="h-5 w-5" style={{ filter: "brightness(0) invert(1)" }} />}
            {item.cta || "View pipeline in Cloud Build"} <window.Icon name="ArrowUpRight" size={18} />
          </a>
        ) : (
          <div className="flex w-full cursor-not-allowed items-center justify-center gap-2.5 rounded-xl px-5 py-3.5 text-[15px] font-bold opacity-60" style={{ background: SH.raised, color: SH.sub, border: `1px solid ${SH.line}` }} aria-disabled="true" title="No Cloud Build URL wired — running as the self-contained demo">
            <window.Icon name="Lock" size={17} /> Console link not configured yet
          </div>
        )}
      </div>
      {!live && (
        <p className="mt-3 text-[11.5px] leading-relaxed" style={{ color: SH.faint }}>
          No console wired — this export runs as the self-contained demo. Set <span style={{ fontFamily: SH.mono }}>LASTROSE_BACKENDS.cloudBuildUrl</span> in the release overlay to light the button up.
        </p>
      )}
    </div>
  );
}

/* ============================================================ */
function ShipHappens({ navigate, onBack }) {
  const pillar = (window.PILLARS || []).find((p) => p.id === "cicd-mlops");
  const item = pillar ? pillar.items.find((it) => it.type === "cloudBuild") : null;
  const stages = (item && item.stages) || [];
  const failures = stages.filter((s) => s.blocked).length;

  if (!item) return null;

  return (
    <div className="relative flex h-full w-full flex-col overflow-hidden a-fade" style={{ background: SH.page, fontFamily: SH.sans }} data-screen-label="Ship Happens">
      <div className="pointer-events-none absolute inset-0" style={{ background: SH.ambient }} />

      {/* presenter toolbar */}
      <div className="relative z-10 flex h-12 shrink-0 items-center justify-between px-4" style={{ background: "rgba(238,242,251,0.84)", backdropFilter: "blur(14px)", borderBottom: `1px solid ${SH.line}` }}>
        <button onClick={onBack} className="inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-[13px] font-medium" style={{ color: SH.sub }}>
          <window.Icon name="ArrowLeft" size={16} /> Back to hub
        </button>
        <div className="flex items-center gap-2">
          <window.RoseMark size={18} color={SH.blue} petals={6} />
          <span className="hidden text-[12px] sm:inline" style={{ color: SH.faint }}>Last Rose · <span style={{ color: SH.sub }}>Ship Happens!</span></span>
          <window.OpenInNewTab href="#/shiphappens" size={13} className="h-7 w-7" title="Open Ship Happens! in new tab" style={{ color: SH.sub, background: SH.surface, border: `1px solid ${SH.line}` }} />
        </div>
        <span className="inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-[12.5px] font-semibold" style={{ background: SH.blueSoft, color: SH.blue, border: `1px solid ${SH.blueBorder}` }}>
          <window.Icon name="Workflow" size={14} /> CI/CD · MLOps
        </span>
      </div>

      {/* body */}
      <div className="lr-scroll relative z-10 flex-1 overflow-y-auto">
        <div className="mx-auto max-w-[1100px] px-6 py-8 sm:px-9">
          {/* header */}
          <div className="a-fade-up">
            <div className="flex items-center gap-3">
              {item.titleImg && <img src={item.titleImg} alt="" aria-hidden="true" style={{ width: 38, height: 38 }} className="object-contain" />}
              <h1 style={{ fontFamily: SH.serif, color: SH.ink }} className="text-[34px] font-medium leading-none">Ship Happens!</h1>
              <span className="hidden text-[13px] sm:inline" style={{ color: SH.faint, fontFamily: SH.mono }}>· GCP Cloud Build</span>
            </div>
            <p className="mt-3 max-w-3xl text-[15.5px] leading-relaxed" style={{ color: SH.ink }}>
              A full MLOps pipeline on GCP Cloud Build with <span className="font-semibold" style={{ color: SH.blue }}>Prisma AIRS at every gate</span> — a model-scan gauntlet, a fine-tune on Vertex AI, a post-train gate, a red-team on the deployed app, and a runtime guardrail at the Apigee gateway.
            </p>
            <p className="mt-2 text-[13.5px] font-semibold" style={{ color: SH.sub }}>
              {failures} ways to fail, one way to ship.
            </p>
          </div>

          {/* two-column: timeline + action rail */}
          <div className="mt-8 grid grid-cols-1 gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(0,360px)]" style={{ alignItems: "start" }}>
            {/* timeline */}
            <div className="a-fade-up">
              <ShSectionLabel>The pipeline · top to bottom</ShSectionLabel>
              <div className="rounded-2xl px-5 py-5" style={{ background: SH.surfaceAlt, border: `1px solid ${SH.line}` }}>
                {stages.map((s, i) => (
                  <PipelineStep key={s.n} s={s} last={i === stages.length - 1} />
                ))}
                {item.stageCaption && (
                  <p className="mt-2 border-t pt-3.5 text-[12.5px] leading-relaxed" style={{ color: SH.sub, borderColor: SH.lineSoft }}>{item.stageCaption}</p>
                )}
              </div>
            </div>

            {/* action rail */}
            <div className="space-y-5 a-fade-up lg:sticky lg:top-4">
              <OpenInCloudBuild item={item} />
              <div className="rounded-2xl px-5 py-5" style={{ background: SH.surface, border: `1px solid ${SH.line}` }}>
                <ShSectionLabel>Two failures, one ship</ShSectionLabel>
                <ul className="space-y-2.5 text-[13px] leading-relaxed" style={{ color: SH.sub }}>
                  <li className="flex gap-2"><span style={{ color: SH.danger }}>⛔</span><span><span className="font-semibold" style={{ color: SH.ink }}>Poisoned model</span> — a pickle-bomb candidate is caught in the scan gauntlet and never trains.</span></li>
                  <li className="flex gap-2"><span style={{ color: SH.danger }}>⛔</span><span><span className="font-semibold" style={{ color: SH.ink }}>Tampered artifact</span> — a trained model that's been altered is blocked at the post-train gate.</span></li>
                  <li className="flex gap-2"><span style={{ color: SH.blue }}>✓</span><span><span className="font-semibold" style={{ color: SH.ink }}>Clean build</span> — passes every gate, deploys to Cloud Run, and runs behind the AIRS runtime guardrail.</span></li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ShipHappens });
