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

export interface FleetItem {
  repo: string;
  pr: string;
  added: number;
  removed: number;
  gates: string;
  sandboxUrl: string;
  status: string;
}

export interface FleetRefactorProps {
  fleet?: FleetItem[];
  user?: any;
}

const DEFAULT_FLEET: FleetItem[] = [
  {
    repo: "gluecron",
    pr: "PR №220 · feat/auth-header",
    added: 34,
    removed: 30,
    gates: "4/4 green",
    sandboxUrl: "pr-220.preview",
    status: "Ready",
  },
  {
    repo: "gluecron-cli",
    pr: "PR №221 · feat/auth-header",
    added: 12,
    removed: 12,
    gates: "3/3 green",
    sandboxUrl: "pr-221.preview",
    status: "Ready",
  },
  {
    repo: "editor-extensions",
    pr: "PR №222 · feat/auth-header",
    added: 18,
    removed: 16,
    gates: "4/5 running",
    sandboxUrl: "pr-222.preview",
    status: "Gating",
  },
  {
    repo: "gatetest",
    pr: "PR №223 · feat/auth-header",
    added: 6,
    removed: 6,
    gates: "rebasing",
    sandboxUrl: "pr-223.preview",
    status: "Rebasing",
  },
];

export const FleetRefactor: FC<FleetRefactorProps> = (props) => {
  const fleet = props.fleet ?? DEFAULT_FLEET;
  const user = props.user;
  const avatarLabel = user?.username?.[0]?.toUpperCase() ?? "C";

  return (
    <>
      <style dangerouslySetInnerHTML={{ __html: css }} />
      <div class="fr-root">
        <header class="fr-header">
          <a href="/" class="fr-logo">
            <span class="fr-logo-mark" />
            gluecron
          </a>
          <span class="fr-header-sep">/</span>
          <span class="fr-header-breadcrumb">Refactors</span>
          <div class="fr-header-right">
            <span class="fr-avatar">{avatarLabel}</span>
          </div>
        </header>

        <main class="fr-main">
          <div class="fr-hero">
            <div class="fr-hero-text">
              <div class="fr-eyebrow">Fleet refactor №7</div>
              <h1 class="fr-title">Rename API auth header across every repo</h1>
              <p class="fr-subtitle">
                One spec, four repos, one reviewed changeset. Each repo gets its own PR and sandbox; they merge together or not at all.
              </p>
            </div>
            <div class="fr-hero-actions">
              <a href="#" class="fr-btn-secondary">Review combined diff</a>
              <button
                type="button"
                id="fr-merge-btn"
                class="fr-btn-primary fr-btn-disabled"
                data-ready="false"
                data-merged="false"
              >
                Waiting on gates…
              </button>
            </div>
          </div>

          <div class="fr-board">
            <div class="fr-board-header">
              <span>Repository</span>
              <span>Changes</span>
              <span>Gates</span>
              <span>Sandbox</span>
              <span>Status</span>
            </div>

            {fleet.map((f, i) => (
              <div class="fr-board-row" data-row-index={String(i)}>
                <span class="fr-repo-cell">
                  <span class="fr-repo-name">{f.repo}</span>
                  <span class="fr-pr-label">{f.pr}</span>
                </span>
                <span class="fr-diff-cell">
                  <span class="fr-diff-add">+{f.added}</span>{" "}
                  <span class="fr-diff-del">−{f.removed}</span>
                </span>
                <span class="fr-gate-cell" data-gate-index={String(i)}>
                  <span class="fr-gate-dot" data-dot-index={String(i)} />
                  <span class="fr-gate-text" data-gate-text={String(i)}>{f.gates}</span>
                </span>
                <a
                  href="#"
                  class="fr-sandbox-link"
                >
                  {f.sandboxUrl}
                </a>
                <span
                  class="fr-status-chip"
                  data-status-index={String(i)}
                >
                  {f.status}
                </span>
              </div>
            ))}

            <div class="fr-atomic-note">
              <span class="fr-atomic-dot" id="fr-atomic-dot" />
              <span class="fr-atomic-text" id="fr-atomic-text">
                Atomic changeset: all four merge together, or none do. Waiting for 2 repos to finish gating.
              </span>
            </div>
          </div>

          <div class="fr-lower">
            <section class="fr-diff-section">
              <h2 class="fr-section-heading">The change — same pattern, every repo</h2>
              <div class="fr-diff-card">
                <div class="fr-diff-card-header">
                  <span>gluecron-cli · src/http.ts</span>
                  <span>
                    <span class="fr-diff-add">+2</span>{" "}
                    <span class="fr-diff-del">−2</span>
                  </span>
                </div>
                <div class="fr-diff-body">
                  <div class="fr-diff-line fr-diff-ctx">{"  const headers = {"}</div>
                  <div class="fr-diff-line fr-diff-rem">{'−   "X-Gluecron-Token": token,'}</div>
                  <div class="fr-diff-line fr-diff-ins">{'+   "Authorization": `Bearer $' + '{token}`,'}</div>
                  <div class="fr-diff-line fr-diff-ctx">{'    "Content-Type": "application/json",'}</div>
                  <div class="fr-diff-line fr-diff-ctx">{"  };"}</div>
                </div>
              </div>
              <p class="fr-diff-note">
                41 call sites matched across the fleet. The server accepts both headers for 30 days (compatibility shim in step 1), so repos can merge in any order without breaking each other — but the changeset still merges atomically by default.
              </p>
            </section>

            <aside class="fr-aside">
              <div class="fr-aside-block">
                <h3 class="fr-aside-eyebrow">Conflicts</h3>
                <div class="fr-aside-card">
                  <p class="fr-aside-body">
                    <strong class="fr-aside-strong">Zero, by design.</strong>{" "}
                    All four branches are continuously rebased in their sandboxes. A conflicting push to gluecron/main at 11:32 was absorbed and re-tested automatically — you never saw it.
                  </p>
                </div>
              </div>

              <div class="fr-aside-block">
                <h3 class="fr-aside-eyebrow">How this reverses</h3>
                <div class="fr-aside-card">
                  <p class="fr-aside-body">
                    One click reverts all four merges together. The 30-day compatibility shim means a revert is safe at any point in the window.
                  </p>
                </div>
              </div>

              <div class="fr-aside-footer">
                <p class="fr-aside-footer-text">
                  Prefer to do one repo by hand? Detach it from the changeset and its PR becomes a normal manual PR — the rest still merge atomically.
                </p>
              </div>
            </aside>
          </div>
        </main>
      </div>

      <script dangerouslySetInnerHTML={{
        __html: `
(function() {
  var step = 0;
  var merged = false;

  var GREEN = "#1e7f5c";
  var AMBER = "#b45309";
  var BLUE  = "#4353c9";
  var PULSE = "gcPulse 1.4s ease-in-out infinite";

  function getRowState(rowIndex, step, merged) {
    var green = GREEN, amber = AMBER, blue = BLUE;
    var pulse = PULSE;
    if (rowIndex === 0) {
      return {
        gates: "4/4 green",
        gateDotColor: green,
        gateAnim: "none",
        gateTextColor: green,
        status: merged ? "Merged" : "Ready",
        statusColor: merged ? blue : green,
      };
    }
    if (rowIndex === 1) {
      return {
        gates: "3/3 green",
        gateDotColor: green,
        gateAnim: "none",
        gateTextColor: green,
        status: merged ? "Merged" : "Ready",
        statusColor: merged ? blue : green,
      };
    }
    if (rowIndex === 2) {
      var ready2 = step >= 1;
      return {
        gates: ready2 ? "5/5 green" : "4/5 running",
        gateDotColor: ready2 ? green : amber,
        gateAnim: ready2 ? "none" : pulse,
        gateTextColor: ready2 ? green : amber,
        status: merged ? "Merged" : ready2 ? "Ready" : "Gating",
        statusColor: merged ? blue : ready2 ? green : amber,
      };
    }
    if (rowIndex === 3) {
      var ready3 = step >= 2;
      return {
        gates: ready3 ? "3/3 green" : "rebasing",
        gateDotColor: ready3 ? green : amber,
        gateAnim: ready3 ? "none" : pulse,
        gateTextColor: ready3 ? green : amber,
        status: merged ? "Merged" : ready3 ? "Ready" : "Rebasing",
        statusColor: merged ? blue : ready3 ? green : amber,
      };
    }
    return {};
  }

  function isAllReady(step) {
    return step >= 2;
  }

  function render() {
    var ready = isAllReady(step);

    // Update each row
    for (var i = 0; i < 4; i++) {
      var state = getRowState(i, step, merged);

      var dotEl = document.querySelector('[data-dot-index="' + i + '"]');
      var gateTextEl = document.querySelector('[data-gate-text="' + i + '"]');
      var statusEl = document.querySelector('[data-status-index="' + i + '"]');

      if (dotEl) {
        dotEl.style.background = state.gateDotColor;
        dotEl.style.animation = state.gateAnim;
      }
      if (gateTextEl) {
        gateTextEl.textContent = state.gates;
        gateTextEl.style.color = state.gateTextColor;
      }
      if (statusEl) {
        statusEl.textContent = state.status;
        statusEl.style.color = state.statusColor;
      }
    }

    // Atomic note
    var atomicDot = document.getElementById('fr-atomic-dot');
    var atomicText = document.getElementById('fr-atomic-text');
    if (atomicDot) {
      atomicDot.style.background = merged ? BLUE : ready ? GREEN : AMBER;
    }
    if (atomicText) {
      if (merged) {
        atomicText.textContent = "All four merged atomically at 12:41 — one revert restores the whole fleet.";
      } else if (ready) {
        atomicText.textContent = "Atomic changeset: all four merge together, or none do. Everything is green — one approval merges the fleet.";
      } else {
        atomicText.textContent = "Atomic changeset: all four merge together, or none do. Waiting for 2 repos to finish gating.";
      }
    }

    // Merge button
    var btn = document.getElementById('fr-merge-btn');
    if (btn) {
      if (merged) {
        btn.textContent = "Fleet merged ✓";
        btn.style.background = GREEN;
        btn.style.cursor = "default";
        btn.classList.remove('fr-btn-disabled');
        btn.classList.add('fr-btn-merged');
      } else if (ready) {
        btn.textContent = "Approve & merge fleet";
        btn.style.background = "#16181d";
        btn.style.cursor = "pointer";
        btn.classList.remove('fr-btn-disabled');
      } else {
        btn.textContent = "Waiting on gates…";
        btn.style.background = "#9a9da8";
        btn.style.cursor = "default";
        btn.classList.add('fr-btn-disabled');
      }
    }
  }

  // Timer: advance step every 3.5s up to step 2
  var timer = setInterval(function() {
    if (step < 2) {
      step++;
      render();
    } else {
      clearInterval(timer);
    }
  }, 3500);

  // Merge button click
  document.addEventListener('DOMContentLoaded', function() {
    render();
    var btn = document.getElementById('fr-merge-btn');
    if (btn) {
      btn.addEventListener('click', function() {
        if (isAllReady(step) && !merged) {
          merged = true;
          render();
        }
      });
    }
  });

  // Run immediately if DOM already ready
  if (document.readyState !== 'loading') {
    render();
    var btn = document.getElementById('fr-merge-btn');
    if (btn) {
      btn.addEventListener('click', function() {
        if (isAllReady(step) && !merged) {
          merged = true;
          render();
        }
      });
    }
  }
})();
        `
      }} />
    </>
  );
};

export default FleetRefactor;

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; }
}

*, *::before, *::after {
  box-sizing: border-box;
}

.fr-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 */
.fr-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;
}

.fr-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;
}

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

.fr-header-sep {
  color: #c4c6cf;
}

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

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

.fr-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 */
.fr-main {
  flex: 1;
  max-width: 1180px;
  width: 100%;
  margin: 0 auto;
  padding: 44px 32px 80px;
}

/* Hero */
.fr-hero {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 36px;
}

.fr-hero-text {
  max-width: 640px;
}

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

.fr-title {
  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;
}

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

.fr-hero-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-shrink: 0;
}

.fr-btn-secondary {
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  border: 1px solid rgba(22,24,29,0.12);
  background: #ffffff;
  color: #16181d;
  text-decoration: none;
  display: inline-block;
  white-space: nowrap;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.15s;
}

.fr-btn-secondary:hover {
  border-color: rgba(22,24,29,0.24);
}

.fr-btn-primary {
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  border: 0;
  background: #16181d;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
  transition: background 0.2s, cursor 0.1s;
}

.fr-btn-disabled {
  background: #9a9da8 !important;
  cursor: default !important;
}

.fr-btn-merged {
  background: #1e7f5c !important;
  cursor: default !important;
}

/* Fleet board */
.fr-board {
  border: 1px solid rgba(22,24,29,0.07);
  border-radius: 14px;
  background: #ffffff;
  overflow: hidden;
  margin-bottom: 36px;
}

.fr-board-header {
  display: grid;
  grid-template-columns: minmax(150px,1.4fr) minmax(90px,0.9fr) minmax(120px,1.2fr) minmax(90px,0.9fr) minmax(120px,1fr);
  gap: 12px;
  padding: 10px 22px;
  border-bottom: 1px solid rgba(22,24,29,0.07);
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #8a8d99;
}

.fr-board-row {
  display: grid;
  grid-template-columns: minmax(150px,1.4fr) minmax(90px,0.9fr) minmax(120px,1.2fr) minmax(90px,0.9fr) minmax(120px,1fr);
  gap: 12px;
  padding: 15px 22px;
  border-bottom: 1px solid rgba(22,24,29,0.05);
  align-items: center;
}

.fr-board-row:last-of-type {
  border-bottom: 1px solid rgba(22,24,29,0.05);
}

.fr-repo-cell {
  min-width: 0;
}

.fr-repo-name {
  display: block;
  font-size: 13.5px;
  font-weight: 500;
  color: #16181d;
}

.fr-pr-label {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: #8a8d99;
  margin-top: 1px;
}

.fr-diff-cell {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.fr-diff-add {
  color: #1e7f5c;
}

.fr-diff-del {
  color: #b42318;
}

.fr-gate-cell {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
}

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

.fr-gate-text {
  color: #1e7f5c;
}

.fr-sandbox-link {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  color: #4353c9;
  text-decoration: none;
}

.fr-sandbox-link:hover {
  text-decoration: underline;
}

.fr-status-chip {
  font-size: 12.5px;
  font-weight: 500;
  color: #1e7f5c;
}

.fr-atomic-note {
  padding: 13px 22px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: #fcfcfd;
}

.fr-atomic-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #b45309;
  flex-shrink: 0;
  display: inline-block;
  transition: background 0.3s;
}

.fr-atomic-text {
  font-size: 12.5px;
  color: #6b7080;
}

/* Lower two-column */
.fr-lower {
  display: grid;
  grid-template-columns: minmax(0,1.5fr) minmax(300px,1fr);
  gap: 44px;
  align-items: start;
}

/* Diff section */
.fr-diff-section {
  /* left column */
}

.fr-section-heading {
  font-family: 'Inter Tight', sans-serif;
  font-size: 15px;
  font-weight: 600;
  margin: 0 0 16px;
  color: #16181d;
  letter-spacing: -0.015em;
}

.fr-diff-card {
  border: 1px solid rgba(22,24,29,0.07);
  border-radius: 12px;
  overflow: hidden;
  background: #ffffff;
}

.fr-diff-card-header {
  padding: 9px 18px;
  border-bottom: 1px solid rgba(22,24,29,0.07);
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  color: #6b7080;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.fr-diff-body {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  line-height: 1.75;
  padding: 8px 0;
}

.fr-diff-line {
  padding: 0 18px;
  white-space: pre;
}

.fr-diff-ctx {
  color: #8a8d99;
}

.fr-diff-rem {
  background: rgba(180,35,24,0.05);
  color: #b42318;
}

.fr-diff-ins {
  background: rgba(30,127,92,0.06);
  color: #1e7f5c;
}

.fr-diff-note {
  font-size: 12.5px;
  color: #8a8d99;
  margin: 12px 0 0;
  line-height: 1.6;
}

/* Aside */
.fr-aside {
  display: flex;
  flex-direction: column;
  gap: 32px;
  position: sticky;
  top: 92px;
}

.fr-aside-block {
  /* individual block */
}

.fr-aside-eyebrow {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #8a8d99;
  font-weight: 500;
  margin: 0 0 14px;
}

.fr-aside-card {
  border: 1px solid rgba(22,24,29,0.07);
  border-radius: 12px;
  background: #ffffff;
  padding: 20px;
}

.fr-aside-body {
  font-size: 13px;
  color: #6b7080;
  margin: 0;
  line-height: 1.65;
}

.fr-aside-strong {
  color: #16181d;
  font-weight: 500;
}

.fr-aside-footer {
  border-top: 1px solid rgba(22,24,29,0.07);
  padding-top: 20px;
}

.fr-aside-footer-text {
  font-size: 12.5px;
  color: #8a8d99;
  margin: 0;
  line-height: 1.6;
}

@media (max-width: 900px) {
  .fr-lower {
    grid-template-columns: 1fr;
  }
  .fr-aside {
    position: static;
  }
}

@media (max-width: 700px) {
  .fr-main {
    padding: 28px 16px 60px;
  }
  .fr-board-header,
  .fr-board-row {
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }
  .fr-board-header span:nth-child(n+3),
  .fr-board-row > *:nth-child(n+3) {
    display: none;
  }
  .fr-hero {
    flex-direction: column;
    align-items: flex-start;
  }
}
`;
