import type { FC } from "hono/jsx";

export interface LayerData {
  name: string;
  tech: string;
  state: "healthy" | "watched";
  detail: string;
  facts: string[];
  fix?: string;
}

export interface ProductionLayersProps {
  layers?: LayerData[];
  user?: any;
}

const DEFAULT_LAYERS: LayerData[] = [
  {
    name: "Frontend foundation",
    tech: "Hono JSX, server-rendered · zero client framework",
    state: "healthy",
    detail:
      "Every page is server-rendered from the same box that serves git. No SPA bundle to break, no hydration drift — first paint is the page.",
    facts: ["p75 paint 240ms", "0 client deps", "themes: light/dark"],
  },
  {
    name: "Request routing",
    tech: "Caddy · TLS termination · path-based routing",
    state: "healthy",
    detail:
      "Caddy terminates TLS and routes by path prefix — no gateway DSL to learn. Certificates auto-renew; routing changes take effect on config reload with zero dropped connections.",
    facts: ["2 edge nodes", "certs auto-renew 71d", "failover < 3s"],
  },
  {
    name: "Auth & identity",
    tech: "Sessions, PATs, OAuth2, passkeys, OIDC SSO",
    state: "healthy",
    detail:
      "Every credential type funnels through one permission resolver. Org/team roles, branch protection, and CODEOWNERS all evaluate in the same place — one model to audit.",
    facts: ["2FA + WebAuthn", "SSO: Okta/Azure/Google", "token scopes: 6"],
  },
  {
    name: "Repo storage",
    tech: "Postgres (Neon) + Drizzle · git objects on disk",
    state: "healthy",
    detail:
      "108 migrations, all additive-first. Git object storage stays plain files on disk — recoverable with nothing but git itself.",
    facts: ["4ms median query", "0 lock waits 24h", "108 migrations"],
  },
  {
    name: "Git protocol",
    tech: "Smart HTTP · pack negotiation · push-time hooks",
    state: "healthy",
    detail:
      "Git Smart HTTP served directly from Bun. Pack negotiation handles shallow clones and partial fetches; post-receive hooks trigger gates and webhooks inline on every push.",
    facts: ["clone p50 1.2s", "push gate: sync", "protocol v2"],
  },
  {
    name: "AI orchestration",
    tech: "Local LLM router · private cloud burst · MCP server",
    state: "healthy",
    detail:
      "PR sandboxes and repair loops run on our own compute pool. The model router prefers local inference and bursts to private cloud only under load — spend is metered per repo.",
    facts: ["62% local inference", "24s sandbox boot", "pool: 8 workers"],
  },
  {
    name: "Gate engine",
    tech: "Push-time gates · 15-pattern secret scan · AI review",
    state: "watched",
    detail:
      "Gates run at the moment of push, not minutes later. 15-pattern secret scan plus AI security review on every push. One policy gap on the new flywheel_telemetry table has a drafted fix awaiting apply.",
    facts: ["gate p99 38s", "0 secrets leaked", "advisory scan: nightly"],
    fix: "Apply RLS policy to flywheel_telemetry",
  },
  {
    name: "Workflow runner",
    tech: ".gluecron/workflows · per-step timeouts · size-capped logs",
    state: "healthy",
    detail:
      "The workflow runner executes .gluecron/workflows with per-step timeouts and size-capped logs. No YAML knowledge required — steps are plain shell commands annotated with timeouts.",
    facts: ["1,412 merges/mo", "0 YAML required", "log cap: 1 MB/step"],
  },
  {
    name: "Package registry",
    tech: "npm-compatible · LRU cache · packuments · tarballs",
    state: "healthy",
    detail:
      "npm-compatible registry served from the same Bun process. Packuments and tarballs are LRU-cached in-process; publish gated by the same permission model as git push.",
    facts: ["hit rate 94%", "publish: gated", "compat: npm/pnpm/yarn"],
  },
  {
    name: "Notification bus",
    tech: "Webhooks · HMAC-SHA256 · event fan-out · retry queue",
    state: "healthy",
    detail:
      "Outbound webhooks sign every payload with HMAC-SHA256. A retry queue handles transient failures; the delivery log is queryable from the repo settings page.",
    facts: ["retry: 3× exp backoff", "HMAC-SHA256", "events: 8 types"],
  },
  {
    name: "Search & index",
    tech: "Full-text · semantic index · code search · regex",
    state: "healthy",
    detail:
      "Full-text search over commit messages, issue bodies, and file contents. Semantic index rebuilt on push; code search supports regex and filename filters with sub-second latency.",
    facts: ["index lag < 5s", "regex: yes", "semantic: per-repo"],
  },
  {
    name: "Telemetry",
    tech: "Request-ID tracing · /metrics · audit log",
    state: "healthy",
    detail:
      "Every request carries an ID from edge to database. Errors correlate to audit entries and gate runs automatically — the support console reads the same trail.",
    facts: ["trace coverage 100%", "retention 90d", "/healthz /readyz"],
  },
  {
    name: "Availability & recovery",
    tech: "Air-gapped region sync · hourly bare-metal replicas",
    state: "watched",
    detail:
      "Repo state, semantic indices, and the package registry replicate hourly to an offline array (0083 data-region rails). EU shard backfill completed; replica lag briefly above target during it — recovering.",
    facts: ["RPO 1h · RTO 15m", "replica lag 4m (target 2m)", "last drill: Jun 20 ✓"],
    fix: "Flush EU shard backlog · estimated 18 min",
  },
];

export const ProductionLayers: FC<ProductionLayersProps> = (props) => {
  const layers = props.layers ?? DEFAULT_LAYERS;
  const watchedCount = layers.filter((l) => l.state === "watched").length;
  const healthyCount = layers.filter((l) => l.state === "healthy").length;

  return (
    <>
      <style dangerouslySetInnerHTML={{ __html: css }} />
      <div class="pl-root">
        <header class="pl-header">
          <a href="/" class="pl-logo">
            <span class="pl-logo-mark"></span>
            gluecron
            <span class="pl-logo-eyebrow">admin</span>
          </a>
          <span class="pl-sep">/</span>
          <span class="pl-breadcrumb">Production layers</span>
          <div class="pl-header-right">
            <span class="pl-summary">
              <span class="pl-summary-dot"></span>
              {layers.length} layers &middot; {healthyCount} healthy &middot; {watchedCount} watched
            </span>
            <span class="pl-avatar">C</span>
          </div>
        </header>

        <main class="pl-main">
          <div class="pl-intro">
            <div class="pl-eyebrow">Infrastructure sovereignty &middot; every layer self-owned</div>
            <h1 class="pl-heading">The whole stack, one board.</h1>
            <p class="pl-desc">
              Thirteen production layers, no magic edge proxies, no external runtime dependencies.
              Each layer is watched by the same repair engine that heals customer pushes &mdash; click
              a layer for its live detail.
            </p>
          </div>

          <div class="pl-rows" id="pl-rows">
            {layers.map((layer, i) => {
              const num = String(i + 1).padStart(2, "0");
              const watched = layer.state === "watched";
              return (
                <div
                  class={`pl-item${watched ? " pl-item--watched" : ""}`}
                  data-index={String(i)}
                >
                  <button
                    type="button"
                    class={`pl-row${watched ? " pl-row--watched" : ""}`}
                    data-index={String(i)}
                    aria-expanded="false"
                    aria-controls={`pl-detail-${i}`}
                  >
                    <span class="pl-row-num">{num}</span>
                    <span class="pl-row-name">{layer.name}</span>
                    <span class="pl-row-tech">{layer.tech}</span>
                    <span class={`pl-row-status${watched ? " pl-row-status--watched" : ""}`}>
                      <span class={`pl-dot${watched ? " pl-dot--watched" : ""}`}></span>
                      {watched ? "watched" : "healthy"}
                    </span>
                    <span class="pl-caret" aria-hidden="true">&#9660;</span>
                  </button>

                  {watched && (
                    <div class="pl-fix-callout">
                      <span class="pl-fix-label">drafted fix</span>
                      <span class="pl-fix-sep">&mdash;</span>
                      <span class="pl-fix-text">{layer.fix}</span>
                    </div>
                  )}

                  <div
                    class="pl-detail"
                    id={`pl-detail-${i}`}
                    role="region"
                    hidden={true}
                  >
                    <p class="pl-detail-desc">{layer.detail}</p>
                    <div class="pl-facts">
                      {layer.facts.map((f, fi) => (
                        <span class="pl-fact">{f}</span>
                      ))}
                    </div>
                    {watched && (
                      <div class="pl-apply-wrap">
                        <button
                          type="button"
                          class="pl-apply-btn"
                          data-fix={layer.fix ?? ""}
                          data-layer={layer.name}
                        >
                          Apply fix
                        </button>
                      </div>
                    )}
                  </div>
                </div>
              );
            })}
          </div>

          <div class="pl-footer">
            <p class="pl-footer-text">
              Watched layers have a drafted fix or an active mitigation &mdash; nothing here requires
              a terminal. Air-gapped replicas sync all thirteen layers to bare-metal arrays on the hour.
            </p>
            <a href="/admin" class="pl-footer-link">Open diagnostics &rarr;</a>
          </div>
        </main>
      </div>
      <script dangerouslySetInnerHTML={{ __html: js }} />
    </>
  );
};

export default ProductionLayers;

const css = `
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;450;500;600;700&family=Inter+Tight:wght@500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');

@keyframes gcPulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.35; }
}

/* ── Root ── */
.pl-root {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.55;
  letter-spacing: -0.008em;
  color: #16181d;
  background: #fcfcfd;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ── Header ── */
.pl-header {
  height: 56px;
  border-bottom: 1px solid rgba(22,24,29,0.07);
  background: #fcfcfd;
  display: flex;
  align-items: center;
  padding: 0 28px;
  gap: 20px;
  position: sticky;
  top: 0;
  z-index: 50;
  box-sizing: border-box;
}

.pl-logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'Inter Tight', sans-serif;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.02em;
  color: #16181d;
  text-decoration: none;
  flex-shrink: 0;
}

.pl-logo-mark {
  width: 16px;
  height: 16px;
  border-radius: 5px;
  background: #4353c9;
  display: inline-block;
  flex-shrink: 0;
}

.pl-logo-eyebrow {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #8a8d99;
  font-weight: 500;
  margin-left: 2px;
}

.pl-sep {
  color: #c4c6cf;
  flex-shrink: 0;
}

.pl-breadcrumb {
  font-size: 13px;
  color: #16181d;
  font-weight: 500;
}

.pl-header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}

.pl-summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: #6b7080;
  white-space: nowrap;
}

.pl-summary-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #1e7f5c;
  flex-shrink: 0;
}

.pl-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #16181d;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* ── Main ── */
.pl-main {
  flex: 1;
  max-width: 1100px;
  width: 100%;
  margin: 0 auto;
  padding: 44px 32px 88px;
  box-sizing: border-box;
}

/* ── Intro ── */
.pl-intro {
  max-width: 680px;
  margin-bottom: 36px;
}

.pl-eyebrow {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #8a8d99;
  margin-bottom: 10px;
}

.pl-heading {
  font-family: 'Inter Tight', sans-serif;
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.15;
  margin: 0 0 8px;
  color: #111318;
}

.pl-desc {
  font-size: 14px;
  color: #6b7080;
  margin: 0;
  line-height: 1.6;
}

/* ── Layer rows stack ── */
.pl-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pl-item {
  display: flex;
  flex-direction: column;
}

/* ── Row button ── */
.pl-row {
  display: grid;
  grid-template-columns: 32px minmax(140px, 1.3fr) minmax(0, 2fr) minmax(110px, 0.9fr) 20px;
  gap: 16px;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: 14px 20px;
  border: 1px solid rgba(22,24,29,0.07);
  border-radius: 12px;
  background: #ffffff;
  cursor: pointer;
  font-family: inherit;
  box-sizing: border-box;
  transition: border-color 0.15s ease;
  outline: none;
}

.pl-row:hover {
  border-color: rgba(22,24,29,0.22);
}

.pl-row:focus-visible {
  box-shadow: 0 0 0 3px rgba(67,83,201,0.18);
}

.pl-row--watched {
  border-color: rgba(180,83,9,0.28);
  border-left: 3px solid rgba(180,83,9,0.65);
  padding-left: 18px;
  border-radius: 12px 12px 4px 4px;
}

.pl-row--watched:hover {
  border-color: rgba(180,83,9,0.45);
  border-left-color: rgba(180,83,9,0.85);
}

.pl-row-num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: #c4c6cf;
  font-weight: 400;
  line-height: 1;
}

.pl-row-name {
  font-family: 'Inter Tight', sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #16181d;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.012em;
}

.pl-row-tech {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  color: #6b7080;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 400;
}

.pl-row-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: #1e7f5c;
  font-weight: 500;
  white-space: nowrap;
}

.pl-row-status--watched {
  color: #b45309;
}

.pl-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #1e7f5c;
  flex-shrink: 0;
  display: inline-block;
}

.pl-dot--watched {
  background: #b45309;
  animation: gcPulse 1.4s ease-in-out infinite;
}

.pl-caret {
  color: #c4c6cf;
  font-size: 10px;
  text-align: center;
  display: block;
  transition: transform 0.2s ease;
  line-height: 1;
}

.pl-row[aria-expanded="true"] .pl-caret {
  transform: rotate(180deg);
}

/* ── Fix callout (always visible for watched rows) ── */
.pl-fix-callout {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 20px 8px 22px;
  background: rgba(180,83,9,0.04);
  border: 1px solid rgba(180,83,9,0.18);
  border-top: none;
  border-radius: 0 0 8px 8px;
  margin-bottom: 2px;
}

.pl-fix-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #b45309;
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
}

.pl-fix-sep {
  color: rgba(180,83,9,0.35);
  font-size: 11px;
  flex-shrink: 0;
}

.pl-fix-text {
  font-size: 12.5px;
  color: #6b7080;
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Detail panel ── */
.pl-detail {
  margin-top: 6px;
  padding: 18px 22px 18px 68px;
  border: 1px solid rgba(22,24,29,0.05);
  border-radius: 12px;
  background: rgba(22,24,29,0.015);
  box-sizing: border-box;
}

.pl-detail[hidden] {
  display: none !important;
}

.pl-detail-desc {
  font-size: 13px;
  color: #6b7080;
  margin: 0 0 12px;
  line-height: 1.65;
  max-width: 72ch;
}

.pl-facts {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  color: #8a8d99;
  font-weight: 400;
}

.pl-fact {
  white-space: nowrap;
}

.pl-apply-wrap {
  margin-top: 16px;
}

.pl-apply-btn {
  background: #16181d;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  letter-spacing: -0.008em;
  cursor: pointer;
  transition: background 0.15s ease, opacity 0.15s ease;
  outline: none;
}

.pl-apply-btn:hover:not(:disabled) {
  background: #2a2d36;
}

.pl-apply-btn:focus-visible {
  box-shadow: 0 0 0 3px rgba(67,83,201,0.18);
}

.pl-apply-btn:disabled {
  cursor: default;
  opacity: 0.75;
}

/* ── Footer ── */
.pl-footer {
  border-top: 1px solid rgba(22,24,29,0.07);
  margin-top: 36px;
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  align-items: flex-start;
}

.pl-footer-text {
  font-size: 12.5px;
  color: #8a8d99;
  margin: 0;
  max-width: 62ch;
  line-height: 1.6;
}

.pl-footer-link {
  font-size: 13px;
  color: #4353c9;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
}

.pl-footer-link:hover {
  text-decoration: underline;
}

/* ── Responsive ── */
@media (max-width: 720px) {
  .pl-header {
    padding: 0 16px;
    gap: 12px;
  }
  .pl-summary {
    display: none;
  }
  .pl-main {
    padding: 28px 16px 60px;
  }
  .pl-row {
    grid-template-columns: 28px minmax(0, 1fr) auto 16px;
    gap: 10px;
    padding: 12px 16px;
  }
  .pl-row--watched {
    padding-left: 14px;
  }
  .pl-row-tech {
    display: none;
  }
  .pl-detail {
    padding: 14px 16px 14px 20px;
  }
  .pl-fix-callout {
    padding: 7px 16px;
  }
  .pl-facts {
    gap: 14px;
  }
}
`;

const js = `
(function () {
  // Toggle expand / collapse for each layer row
  document.querySelectorAll('.pl-row').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var idx = btn.getAttribute('data-index');
      var detail = document.getElementById('pl-detail-' + idx);
      if (!detail) return;

      var isOpen = btn.getAttribute('aria-expanded') === 'true';
      if (isOpen) {
        btn.setAttribute('aria-expanded', 'false');
        detail.hidden = true;
      } else {
        btn.setAttribute('aria-expanded', 'true');
        detail.hidden = false;
      }
    });
  });

  // Apply fix buttons
  document.querySelectorAll('.pl-apply-btn').forEach(function (applyBtn) {
    applyBtn.addEventListener('click', function (e) {
      e.stopPropagation();
      if (applyBtn.disabled) return;

      applyBtn.disabled = true;
      applyBtn.textContent = 'Applying…';

      setTimeout(function () {
        applyBtn.textContent = 'Fix applied ✓';
        applyBtn.style.background = '#1e7f5c';
        applyBtn.style.cursor = 'default';

        var item = applyBtn.closest('.pl-item');
        if (!item) return;

        // Swap dot from watched (amber pulse) to healthy (green)
        var dot = item.querySelector('.pl-dot--watched');
        if (dot) {
          dot.classList.remove('pl-dot--watched');
          dot.style.background = '#1e7f5c';
          dot.style.animation = 'none';
        }

        // Swap status label colour + text
        var status = item.querySelector('.pl-row-status--watched');
        if (status) {
          status.classList.remove('pl-row-status--watched');
          status.style.color = '#1e7f5c';
          // Last child is the text node "watched"
          var nodes = status.childNodes;
          for (var n = 0; n < nodes.length; n++) {
            if (nodes[n].nodeType === 3 /* TEXT_NODE */) {
              nodes[n].textContent = 'healthy';
              break;
            }
          }
        }

        // Remove amber border from the row button
        var rowBtn = item.querySelector('.pl-row--watched');
        if (rowBtn) {
          rowBtn.classList.remove('pl-row--watched');
        }

        // Fade and remove the fix callout strip
        var callout = item.querySelector('.pl-fix-callout');
        if (callout) {
          callout.style.transition = 'opacity 0.35s ease';
          callout.style.opacity = '0';
          setTimeout(function () {
            callout.style.display = 'none';
          }, 350);
        }
      }, 1400);
    });
  });
})();
`;
