// BUILDER VIEW — for developers studying the design pattern
const { useState } = React;

const LAYERS = [
  {
    id: "interfaces",
    label: "interfaces/",
    sub: "Discord · API · Web",
    color: "#38d4c8",
    bg: "rgba(56,212,200,0.06)",
    desc: "Adapter layer. Swappable without touching core/ or agents/. Discord today, REST API in the fork.",
    files: ["discord/bot.py", "discord/commands.py", "discord/voice.py"],
    forkable: false,
  },
  {
    id: "agents",
    label: "agents/",
    sub: "Orchestrator · Specialists",
    color: "#e8a84c",
    bg: "rgba(232,168,76,0.06)",
    desc: "Implementation-specific personas and domain logic. Entirely replaced in a fork. No framework code lives here.",
    files: ["orchestrator.py", "specialist_a.py", "specialist_b.py"],
    forkable: false,
  },
  {
    id: "core",
    label: "core/",
    sub: "Orchestrator · ABAC · Memory",
    color: "#9d7ee8",
    bg: "rgba(157,126,232,0.08)",
    desc: "Context-agnostic. No personas, no domain logic. This is what gets forked for professional deployments.",
    files: ["graph/client.py", "graph/abac.py", "orchestrator/base.py", "orchestrator/memory.py", "specialists/base.py"],
    forkable: true,
  },
  {
    id: "services",
    label: "services/",
    sub: "Write Worker · Auditor · Cataloger",
    color: "#9d7ee8",
    bg: "rgba(157,126,232,0.05)",
    desc: "Stateless, horizontally scalable workers. Domain-agnostic chunking and embedding. The write worker cluster is universal across all deployments.",
    files: ["cara/main.py", "cara/chunker.py", "cara/embedder.py", "cara/writer.py"],
    forkable: true,
  },
  {
    id: "graph",
    label: "FalkorDB",
    sub: "Graph + Vector · OpenCypher",
    color: "#9d7ee8",
    bg: "rgba(157,126,232,0.04)",
    desc: "Graph storage with native vector search. 384-dim embeddings. Relationships are first-class primitives.",
    files: ["schema: Chunk · Context · Topic · Entity · Insight"],
    forkable: true,
  },
];

const DECISIONS = [
  {
    q: "Why graph over vector DB?",
    color: "#9d7ee8",
    a: "Relationships matter. A vector DB finds similar chunks; a graph knows who said what, when, in what context, across sessions. Memory is relational — retrieval needs to traverse those relationships, not just rank by similarity.",
  },
  {
    q: "Why append-only writes?",
    color: "#38d4c8",
    a: "Trust requires auditability. Modifying records destroys the provenance chain. Corrections are new nodes that supersede old ones — linked, not overwritten. The historical record is always intact.",
  },
  {
    q: "Why fire-and-forget for the write worker?",
    color: "#e8a84c",
    a: "Memory consolidation must never slow a conversation. The orchestrator fires the write worker payload after the response is sent. If the write worker is down, the conversation continues unaffected. Memory is important — but never in the critical path.",
  },
  {
    q: "Why structural ABAC?",
    color: "#9d7ee8",
    a: "Policy engines can be misconfigured. Graph topology cannot. A chunk tagged only to `personal` context has no traversal path from a `trade` query origin — not by rule enforced at runtime, but by the shape of the data itself.",
  },
  {
    q: "Why human adjudication at limits?",
    color: "#38d4c8",
    a: "The system is honest about where its competence ends. When the Validator cannot resolve a classification edge case, it creates a structured escalation record and suspends automated action. Human judgment is the accountability mechanism.",
  },
  {
    q: "Why one-step-behind cataloger?",
    color: "#e8a84c",
    a: "The cataloger processes the previous exchange's data, never the current one. It is always one step behind by design. Speed and safety are maintained structurally — discipline cannot guarantee what architecture can.",
  },
];

const PATTERNS = [
  { label: "Append-only", color: "#38d4c8", icon: "→+", desc: "All writes additive. Tombstones retire, never delete. Corrections supersede." },
  { label: "Structural ABAC", color: "#9d7ee8", icon: "⬡", desc: "Topology enforces access. No traversal path = no access." },
  { label: "Fire & Forget", color: "#e8a84c", icon: "⤳", desc: "Memory writes are async. Response path is never blocked." },
  { label: "Stateless Workers", color: "#38d4c8", icon: "≡", desc: "Any write worker instance handles any request. Horizontal scale." },
  { label: "Human Ceiling", color: "#e8a84c", icon: "△", desc: "Edge cases escalate to human review. Automation knows its limits." },
];

function LayerStack({ activeLayer, setActiveLayer }) {
  return (
    <div style={{ position: "relative" }}>
      {/* Fork annotation */}
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8, paddingLeft: 4 }}>
        <div style={{ fontSize: 9, color: "var(--muted)", fontFamily: "JetBrains Mono, monospace", letterSpacing: "0.1em" }}>REPLACE ON FORK</div>
        <div style={{ flex: 1, height: 1, background: "var(--border)" }}/>
      </div>

      {/* Replaceable layers */}
      {LAYERS.filter(l => !l.forkable).map((layer, i) => (
        <LayerRow key={layer.id} layer={layer} active={activeLayer === layer.id}
          onClick={() => setActiveLayer(activeLayer === layer.id ? null : layer.id)} isLast={i === 1}/>
      ))}

      {/* Fork line */}
      <div style={{ display: "flex", alignItems: "center", gap: 10, margin: "4px 0" }}>
        <div style={{ flex: 1, height: 1, background: "linear-gradient(90deg, transparent, #9d7ee8, transparent)" }}/>
        <div style={{ fontSize: 9, fontFamily: "JetBrains Mono, monospace", color: "#9d7ee8", letterSpacing: "0.1em", padding: "2px 8px", border: "1px solid #9d7ee840", borderRadius: 3 }}>FORK BOUNDARY</div>
        <div style={{ flex: 1, height: 1, background: "linear-gradient(90deg, transparent, #9d7ee8, transparent)" }}/>
      </div>

      {/* Forkable layers */}
      <div style={{ display: "flex", alignItems: "center", gap: 8, margin: "4px 0 8px", paddingLeft: 4 }}>
        <div style={{ fontSize: 9, color: "var(--muted)", fontFamily: "JetBrains Mono, monospace", letterSpacing: "0.1em" }}>KEEP UNTOUCHED</div>
        <div style={{ flex: 1, height: 1, background: "var(--border)" }}/>
      </div>
      {LAYERS.filter(l => l.forkable).map((layer) => (
        <LayerRow key={layer.id} layer={layer} active={activeLayer === layer.id}
          onClick={() => setActiveLayer(activeLayer === layer.id ? null : layer.id)}/>
      ))}
    </div>
  );
}

function LayerRow({ layer, active, onClick }) {
  return (
    <div onClick={onClick} style={{
      background: active ? layer.bg : "var(--surface)",
      border: `1px solid ${active ? layer.color + "50" : "var(--border)"}`,
      borderRadius: 6, marginBottom: 4, padding: "12px 14px",
      cursor: "pointer", transition: "all 0.2s",
    }}
      onMouseEnter={e => { if (!active) e.currentTarget.style.borderColor = layer.color + "30"; }}
      onMouseLeave={e => { if (!active) e.currentTarget.style.borderColor = "var(--border)"; }}
    >
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <div>
          <span style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 12, color: layer.color, fontWeight: 500 }}>{layer.label}</span>
          <span style={{ fontSize: 11, color: "var(--muted)", marginLeft: 10 }}>{layer.sub}</span>
        </div>
        <div style={{ fontSize: 10, color: "var(--dim)", transform: active ? "rotate(180deg)" : "rotate(0)", transition: "transform 0.2s" }}>▾</div>
      </div>
      {active && (
        <div style={{ marginTop: 10, paddingTop: 10, borderTop: `1px solid ${layer.color}20` }}>
          <p style={{ fontSize: 12, color: "var(--muted)", lineHeight: 1.65, marginBottom: 8 }}>{layer.desc}</p>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 5 }}>
            {layer.files.map(f => (
              <span key={f} style={{
                fontFamily: "JetBrains Mono, monospace", fontSize: 10, color: layer.color,
                background: `${layer.color}12`, padding: "2px 7px", borderRadius: 3,
              }}>{f}</span>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

function DataFlowDiagram() {
  const steps = [
    { label: "EXCHANGE", sub: "user message + agent response", color: "#38d4c8", side: "left" },
    { label: "ORCHESTRATOR", sub: "fire-and-forget → write worker", color: "#e8a84c", side: "right", async: true },
    { label: "WRITE WORKER", sub: "decompose · tag · embed", color: "#38d4c8", side: "right" },
    { label: "CHUNK NODES", sub: "written with context + topic + entity edges", color: "#9d7ee8", side: "right" },
    { label: "FALKORDB", sub: "permanent graph write · 384-dim vector stored", color: "#9d7ee8", side: "right" },
  ];

  return (
    <div style={{ padding: "16px 0" }}>
      {steps.map((s, i) => (
        <div key={i} style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: i < steps.length - 1 ? 0 : 0 }}>
          <div style={{ flex: 1 }}>
            {s.side === "left" ? (
              <div style={{
                background: "var(--surface2)", border: `1px solid ${s.color}40`,
                borderRadius: 6, padding: "10px 14px",
              }}>
                <div style={{ fontFamily: "Space Grotesk, sans-serif", fontWeight: 600, fontSize: 12, color: s.color }}>{s.label}</div>
                <div style={{ fontSize: 11, color: "var(--muted)", marginTop: 2 }}>{s.sub}</div>
              </div>
            ) : <div/>}
          </div>

          <div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: 30 }}>
            {i === 0 ? (
              <div style={{ width: 8, height: 8, borderRadius: "50%", background: s.color }}/>
            ) : null}
            {i > 0 && <div style={{ width: 1, height: 18, background: `linear-gradient(${steps[i-1].color}, ${s.color})` }}/>}
            {i > 0 && <div style={{ width: 6, height: 6, borderRadius: "50%", background: s.color }}/>}
            {i < steps.length - 1 && <div style={{ width: 1, height: 18, background: s.color, opacity: 0.3 }}/>}
          </div>

          <div style={{ flex: 1 }}>
            {s.side === "right" ? (
              <div style={{
                background: "var(--surface2)", border: `1px solid ${s.color}40`,
                borderRadius: 6, padding: "10px 14px", position: "relative",
              }}>
                {s.async && (
                  <span style={{ position: "absolute", top: -9, right: 10, fontSize: 9, fontFamily: "JetBrains Mono, monospace",
                    background: "var(--bg)", color: "#e8a84c", padding: "1px 6px", border: "1px solid #e8a84c40", borderRadius: 3 }}>
                    async
                  </span>
                )}
                <div style={{ fontFamily: "Space Grotesk, sans-serif", fontWeight: 600, fontSize: 12, color: s.color }}>{s.label}</div>
                <div style={{ fontSize: 11, color: "var(--muted)", marginTop: 2 }}>{s.sub}</div>
              </div>
            ) : <div/>}
          </div>
        </div>
      ))}
    </div>
  );
}

function BuilderView() {
  const [activeLayer, setActiveLayer] = useState("core");
  const [openDecision, setOpenDecision] = useState(null);

  return (
    <div style={{ height: "100%", overflowY: "auto", padding: "40px 48px 60px" }}>
      <div style={{ maxWidth: 1000, margin: "0 auto" }}>

        {/* Header */}
        <div style={{ marginBottom: 36 }}>
          <p style={{ fontFamily: "Space Grotesk, sans-serif", fontSize: 11, letterSpacing: "0.16em", color: "var(--muted)", marginBottom: 12, textTransform: "uppercase" }}>Design Pattern</p>
          <h1 style={{ fontFamily: "Space Grotesk, sans-serif", fontWeight: 300, fontSize: "clamp(24px, 3vw, 40px)", color: "var(--text)", lineHeight: 1.25, marginBottom: 10 }}>
            A forkable framework with a<br/>
            <span style={{ color: "#9d7ee8", fontWeight: 500 }}>context-agnostic core.</span>
          </h1>
          <p style={{ fontSize: 14, color: "var(--muted)", lineHeight: 1.7, maxWidth: 580 }}>
            The architecture separates what changes per deployment from what never changes. Fork the implementation. Keep the framework.
          </p>
        </div>

        {/* Main two-column layout */}
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 28, marginBottom: 36 }}>

          {/* Left: Layer Stack */}
          <div>
            <div style={{ fontSize: 10, fontFamily: "Space Grotesk, sans-serif", letterSpacing: "0.14em", color: "var(--dim)", marginBottom: 14, textTransform: "uppercase" }}>Layer Separation — click to expand</div>
            <LayerStack activeLayer={activeLayer} setActiveLayer={setActiveLayer}/>
          </div>

          {/* Right: Data Flow */}
          <div>
            <div style={{ fontSize: 10, fontFamily: "Space Grotesk, sans-serif", letterSpacing: "0.14em", color: "var(--dim)", marginBottom: 14, textTransform: "uppercase" }}>Memory Write Path</div>
            <div style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 8, padding: "20px 20px" }}>
              <DataFlowDiagram/>
            </div>

            {/* Key patterns */}
            <div style={{ marginTop: 16 }}>
              <div style={{ fontSize: 10, fontFamily: "Space Grotesk, sans-serif", letterSpacing: "0.14em", color: "var(--dim)", marginBottom: 12, textTransform: "uppercase" }}>Core Patterns</div>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
                {PATTERNS.map(p => (
                  <div key={p.label} style={{
                    background: "var(--surface)", border: `1px solid var(--border)`,
                    borderRadius: 6, padding: "10px 13px", display: "flex", alignItems: "center", gap: 10,
                    flex: "1 1 calc(50% - 4px)", minWidth: 180,
                  }}>
                    <span style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 14, color: p.color, minWidth: 16, textAlign: "center" }}>{p.icon}</span>
                    <div>
                      <div style={{ fontFamily: "Space Grotesk, sans-serif", fontWeight: 600, fontSize: 11, color: p.color }}>{p.label}</div>
                      <div style={{ fontSize: 10, color: "var(--muted)", lineHeight: 1.5, marginTop: 2 }}>{p.desc}</div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>

        {/* Design Decisions */}
        <div>
          <div style={{ fontSize: 10, fontFamily: "Space Grotesk, sans-serif", letterSpacing: "0.14em", color: "var(--dim)", marginBottom: 14, textTransform: "uppercase" }}>Design Decisions — click to read rationale</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 10 }}>
            {DECISIONS.map((d, i) => (
              <div key={i}
                onClick={() => setOpenDecision(openDecision === i ? null : i)}
                style={{
                  background: openDecision === i ? "var(--surface2)" : "var(--surface)",
                  border: `1px solid ${openDecision === i ? d.color + "50" : "var(--border)"}`,
                  borderRadius: 7, padding: "14px 16px", cursor: "pointer",
                  transition: "all 0.2s",
                }}
                onMouseEnter={e => { if (openDecision !== i) e.currentTarget.style.borderColor = d.color + "30"; }}
                onMouseLeave={e => { if (openDecision !== i) e.currentTarget.style.borderColor = "var(--border)"; }}
              >
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 8 }}>
                  <div style={{ fontFamily: "Space Grotesk, sans-serif", fontWeight: 500, fontSize: 12, color: d.color, lineHeight: 1.4 }}>{d.q}</div>
                  <span style={{ fontSize: 12, color: "var(--dim)", flexShrink: 0, transform: openDecision === i ? "rotate(180deg)" : "none", transition: "transform 0.2s", marginTop: 2 }}>▾</span>
                </div>
                {openDecision === i && (
                  <div style={{ marginTop: 12, paddingTop: 12, borderTop: `1px solid ${d.color}20`, fontSize: 12, color: "var(--muted)", lineHeight: 1.7 }}>
                    {d.a}
                  </div>
                )}
              </div>
            ))}
          </div>
        </div>

      </div>
    </div>
  );
}

window.BuilderView = BuilderView;
