/* global React, ReactDOM */
const { useState, useEffect, useRef } = React;

const THEME = {
  bg: "#f4f1ea",
  ink: "#0a0a0a",
  dim: "#7a7569",
  line: "#d8d2c4",
  accent: "#0a0a0a",
};

const HEADLINE = "catching the next wave";
const SUB = "We're offline while we ship some upgrades. Back online shortly.";
const INTENSITY = 1;

// Layered sine waves drawn on a canvas, behind everything.
function WaveField({ intensity }) {
  const canvasRef = useRef(null);
  const rafRef = useRef(0);

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    let w = 0, h = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      w = canvas.clientWidth;
      h = canvas.clientHeight;
      canvas.width = w * dpr;
      canvas.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    const layers = Array.from({ length: 9 }).map((_, i) => ({
      yFrac: 0.18 + i * 0.085,
      amp: (10 + i * 3) * intensity,
      freq: 0.0035 + i * 0.0006,
      speed: 0.00018 + i * 0.00009,
      phase: i * 1.7,
      width: i < 2 ? 1.4 : 0.7,
      alphaMul: i < 2 ? 1 : 0.5 + (1 - i / 9) * 0.5,
    }));

    const draw = (t) => {
      ctx.clearRect(0, 0, w, h);
      for (const L of layers) {
        const y0 = h * L.yFrac;
        ctx.beginPath();
        const step = 4;
        for (let x = 0; x <= w; x += step) {
          const y =
            y0 +
            Math.sin(x * L.freq + t * L.speed + L.phase) * L.amp +
            Math.sin(x * L.freq * 0.4 + t * L.speed * 1.6 + L.phase * 0.7) *
              (L.amp * 0.3);
          if (x === 0) ctx.moveTo(x, y);
          else ctx.lineTo(x, y);
        }
        ctx.lineWidth = L.width;
        ctx.strokeStyle = THEME.ink;
        ctx.globalAlpha = 0.10 * L.alphaMul;
        ctx.stroke();
      }
      ctx.globalAlpha = 1;
      rafRef.current = requestAnimationFrame(draw);
    };
    rafRef.current = requestAnimationFrame(draw);

    return () => {
      cancelAnimationFrame(rafRef.current);
      ro.disconnect();
    };
  }, [intensity]);

  return <canvas ref={canvasRef} className="wave-canvas" />;
}

// The three triangular wave-motifs from the WAVERUNNER mark, animated.
function HeroMark() {
  return (
    <svg
      className="hero-mark"
      viewBox="0 0 90 78"
      preserveAspectRatio="xMidYMid meet"
      aria-hidden="true"
    >
      <g className="cres cres-3">
        <path
          d="M21.33 20.86 L12.88 1.76 C11.83 -0.61 8.46 -0.59 7.44 1.81 L0 19.34 L8.45 38.43 C9.50 40.80 12.87 40.78 13.89 38.38 L21.34 20.86 Z"
          fill={THEME.ink}
        />
      </g>
      <g className="cres cres-2">
        <path
          d="M55.20 21.02 L46.75 1.93 C45.70 -0.44 42.33 -0.42 41.31 1.97 L17.88 57.15 L26.33 76.24 C27.38 78.62 30.75 78.59 31.77 76.20 L55.20 21.02 Z"
          fill={THEME.ink}
        />
      </g>
      <g className="cres cres-1">
        <path
          d="M75.83 1.92 L52.37 57.14 L60.82 76.24 C61.87 78.61 65.24 78.59 66.26 76.19 L89.72 20.97 L81.27 1.88 C80.22 -0.50 76.84 -0.47 75.83 1.92 Z"
          fill={THEME.ink}
        />
      </g>
    </svg>
  );
}

// Full WAVERUNNER wordmark for the top-left.
function Wordmark() {
  return (
    <svg
      className="wordmark"
      viewBox="0 0 684 78"
      preserveAspectRatio="xMinYMid meet"
      aria-label="WAVERUNNER"
    >
      <g fill={THEME.ink}>
        <path d="M75.83 1.92 L52.37 57.14 L60.82 76.24 C61.87 78.61 65.24 78.59 66.26 76.19 L89.72 20.97 L81.27 1.88 C80.22 -0.50 76.84 -0.47 75.83 1.92Z" />
        <path d="M55.20 21.02 L46.75 1.93 C45.70 -0.44 42.33 -0.42 41.31 1.97 L17.88 57.15 L26.33 76.24 C27.38 78.62 30.75 78.59 31.77 76.20 L55.20 21.02Z" />
        <path d="M21.33 20.86 L12.88 1.76 C11.83 -0.61 8.46 -0.59 7.44 1.81 L0 19.34 L8.45 38.43 C9.50 40.80 12.87 40.78 13.89 38.38 L21.34 20.86Z" />
        <path d="M179.25 37.82L181.93 45.01H182.25L184.94 37.82L198.99 3.60H218.94L187.08 75.58H177.21L145.36 3.60H165.41L179.25 37.82Z" />
        <path d="M272.15 3.39V17.97H242.75V30.95H270.75V45.54H242.33V60.98H272.47V75.57H225.49V3.39H272.16Z" />
        <path d="M300.36 55.20V75.47H283.09V3.50L312.37 3.39C321.02 3.39 327.64 5.42 332.22 9.46C336.79 13.50 339.08 20.09 339.08 29.25C339.08 35.32 337.45 40.19 334.20 43.83C330.94 47.48 326.60 49.81 321.17 50.81L341.44 75.58L320.74 75.48L305.29 55.21H300.36ZM321.92 29.02C321.92 27.02 321.65 25.33 321.11 23.93C320.58 22.54 319.82 21.41 318.86 20.55C317.89 19.69 316.78 19.07 315.53 18.68C314.28 18.28 313.01 18.08 311.72 18.08H300.56V40.18H310.64C313.58 40.18 315.80 39.61 317.29 38.46C318.80 37.32 319.90 36.03 320.62 34.60C321.41 32.95 321.84 31.09 321.91 29.02Z" />
        <path d="M391.53 2.42H408.70L408.80 47.58C408.80 51.66 408.03 55.42 406.50 58.85C404.96 62.28 402.85 65.23 400.17 67.70C397.49 70.17 394.34 72.09 390.73 73.49C387.12 74.89 383.27 75.58 379.19 75.58C375.12 75.58 371.27 74.90 367.66 73.55C364.05 72.19 360.90 70.29 358.22 67.86C355.54 65.43 353.41 62.52 351.84 59.12C350.27 55.72 349.48 51.99 349.48 47.91V2.74H366.86L366.33 48.12C366.33 49.84 366.65 51.44 367.29 52.94C367.94 54.44 368.83 55.77 369.97 56.91C371.12 58.05 372.42 58.94 373.89 59.59C375.36 60.23 376.94 60.55 378.66 60.55C380.38 60.55 381.99 60.23 383.49 59.59C384.99 58.94 386.31 58.06 387.46 56.91C388.60 55.77 389.50 54.44 390.14 52.94C390.79 51.44 391.10 49.83 391.10 48.12L391.53 2.42Z" />
        <path d="M613.80 3.39V17.97H584.41V30.95H612.41V45.54H583.99V60.98H614.13V75.57H567.15V3.39H613.81Z" />
        <path d="M642.01 55.20V75.47H624.74V3.50L654.02 3.39C662.67 3.39 669.29 5.42 673.87 9.46C678.45 13.50 680.74 20.09 680.74 29.25C680.74 35.32 679.11 40.19 675.85 43.83C672.60 47.48 668.26 49.81 662.82 50.81L683.09 75.58L662.39 75.48L646.95 55.21H642.01ZM663.57 29.02C663.57 27.02 663.30 25.33 662.76 23.93C662.23 22.54 661.47 21.41 660.51 20.55C659.55 19.69 658.43 19.07 657.18 18.68C655.93 18.28 654.66 18.08 653.37 18.08H642.22V40.18H652.30C655.23 40.18 657.45 39.61 658.95 38.46C660.45 37.32 661.56 36.03 662.27 34.60C663.06 32.95 663.49 31.09 663.56 29.02Z" />
        <path d="M420.71 75.58V3.50H430.37L454.40 30.74L462.55 40.40H462.87V3.50H480.14V75.58H471.88L447.86 47.91L438.31 36.54H437.99V75.58H420.72Z" />
        <path d="M511.03 75.47L493.76 75.58V3.50H511.06L528.43 30.74L535.59 40.40H535.91V3.50H553.18V75.58H544.87L511.43 34.69H511.05L511.02 75.47Z" />
        <path d="M152.40 63.21L126.26 3.28H115.53L89.43 63.12L84.00 75.58H101.70C103.94 71.58 107.73 68.66 112.19 67.59C114.97 66.93 117.88 66.57 120.86 66.57C123.85 66.57 126.85 66.93 129.67 67.63C134.10 68.71 137.87 71.60 140.10 75.58H145.10H157.81L152.41 63.21ZM120.85 52.36C117.53 52.36 114.29 52.67 111.15 53.28L120.89 31.17L130.65 53.30C127.47 52.68 124.20 52.36 120.85 52.36Z" />
      </g>
    </svg>
  );
}

const LOG_LINES = [
  "warming inference cores",
  "rotating model weights",
  "rebalancing routing tables",
  "patching ingestion pipeline",
  "vacuuming database indices",
  "rolling forward to v2.6.4",
  "warming feature store cache",
  "verifying signal integrity",
  "draining stale connections",
  "regenerating embeddings",
  "tightening rate limiters",
  "redeploying edge workers",
  "reseeding prediction queue",
  "calibrating confidence bands",
  "syncing replicas → us-west-2",
  "purging stale auth tokens",
];

function timestamp(offsetMin) {
  const d = new Date(Date.now() + offsetMin * 60000);
  return d.toUTCString().slice(17, 25);
}

function SystemLog() {
  const [lines, setLines] = useState(() => [
    { id: 0, t: timestamp(-12), msg: "maintenance window opened", state: "ok" },
    { id: 1, t: timestamp(-9), msg: "draining live traffic", state: "ok" },
    { id: 2, t: timestamp(-5), msg: "warming inference cores", state: "run" },
  ]);
  const idRef = useRef(3);

  useEffect(() => {
    const tick = () => {
      setLines((prev) => {
        const updated = prev.map((l) => (l.state === "run" ? { ...l, state: "ok" } : l));
        const next = {
          id: idRef.current++,
          t: timestamp(0),
          msg: LOG_LINES[Math.floor(Math.random() * LOG_LINES.length)],
          state: "run",
        };
        return [...updated, next].slice(-7);
      });
    };
    const id = setInterval(tick, 2400);
    return () => clearInterval(id);
  }, []);

  return (
    <div className="log" style={{ borderColor: THEME.line, color: THEME.dim }}>
      <div className="log-head">
        <span className="dot" style={{ background: THEME.accent }}></span>
        <span style={{ color: THEME.ink }}>system log</span>
        <span className="log-meta">live · /maintenance</span>
      </div>
      <div className="log-body">
        {lines.map((l) => (
          <div key={l.id} className={`log-line state-${l.state}`}>
            <span className="log-t">{l.t}</span>
            <span className="log-arrow">›</span>
            <span
              className="log-msg"
              style={{ color: l.state === "run" ? THEME.ink : THEME.dim }}
            >
              {l.msg}
            </span>
            <span className="log-state">
              {l.state === "run" ? <em className="blink">…</em> : "ok"}
            </span>
          </div>
        ))}
      </div>
    </div>
  );
}

// Initial return date is ~15 days out. If that lapses, auto-extend by 7 days at a time.
// Persisted to localStorage so a single visitor sees a stable target across reloads.
const INITIAL_TARGET = new Date("2026-05-23T17:00:00Z").getTime();
const EXTENSION_MS = 7 * 24 * 60 * 60 * 1000;
const STORAGE_KEY = "wr_maintenance_target";

function getCurrentTarget() {
  let target = INITIAL_TARGET;
  try {
    const stored = parseInt(localStorage.getItem(STORAGE_KEY) || "", 10);
    if (!isNaN(stored) && stored > 0) target = stored;
  } catch (_) {}
  const now = Date.now();
  while (target <= now) target += EXTENSION_MS;
  try {
    localStorage.setItem(STORAGE_KEY, String(target));
  } catch (_) {}
  return target;
}

function Countdown() {
  const [target, setTarget] = useState(() => getCurrentTarget());
  const [now, setNow] = useState(Date.now());
  useEffect(() => {
    const id = setInterval(() => {
      const t = Date.now();
      setNow(t);
      if (t >= target) setTarget(getCurrentTarget());
    }, 1000);
    return () => clearInterval(id);
  }, [target]);

  const TARGET_DATE = new Date(target);
  const diff = Math.max(0, target - now);
  const days = Math.floor(diff / 86400000);
  const hours = Math.floor((diff % 86400000) / 3600000);
  const mins = Math.floor((diff % 3600000) / 60000);
  const returnDate = TARGET_DATE.toLocaleDateString(undefined, {
    month: "short",
    day: "numeric",
  }).toLowerCase();

  return (
    <div className="eta">
      <div className="eta-label" style={{ color: THEME.dim }}>estimated return</div>
      <div className="eta-clock" style={{ color: THEME.ink }}>
        <span className="unit">
          <span className="num">{String(days).padStart(2, "0")}</span>
          <span className="u" style={{ color: THEME.dim }}>d</span>
        </span>
        <span className="colon">:</span>
        <span className="unit">
          <span className="num">{String(hours).padStart(2, "0")}</span>
          <span className="u" style={{ color: THEME.dim }}>h</span>
        </span>
        <span className="colon">:</span>
        <span className="unit">
          <span className="num">{String(mins).padStart(2, "0")}</span>
          <span className="u" style={{ color: THEME.dim }}>m</span>
        </span>
      </div>
      <div className="eta-sub" style={{ color: THEME.dim }}>back on&nbsp;·&nbsp;{returnDate}</div>
    </div>
  );
}

function StatusPill() {
  return (
    <div className="status" style={{ borderColor: THEME.line, color: THEME.dim }}>
      <span className="pulse" style={{ background: THEME.accent }}>
        <span className="pulse-ring" style={{ background: THEME.accent }}></span>
      </span>
      <span>scheduled maintenance · in progress</span>
    </div>
  );
}

function Ticker() {
  const items = [
    "● scheduled maintenance",
    "v2.6.4 rolling out",
    "no data loss",
    "back shortly",
    "status.waverunner.ai",
    "● scheduled maintenance",
    "v2.6.4 rolling out",
    "no data loss",
    "back shortly",
    "status.waverunner.ai",
  ];
  return (
    <div className="ticker" style={{ borderColor: THEME.line }}>
      <div className="ticker-track" style={{ color: THEME.dim }}>
        {[...items, ...items].map((t, i) => (
          <span key={i} className="ticker-item">{t}</span>
        ))}
      </div>
    </div>
  );
}

function App() {
  return (
    <div className="page">
      <WaveField intensity={INTENSITY} />
      <div className="grain"></div>

      <header className="top">
        <div className="top-left">
          <Wordmark />
        </div>
        <div className="top-right">
          <StatusPill />
        </div>
      </header>

      <main className="hero">
        <div className="hero-inner">
          <HeroMark />
          <h1 className="headline" style={{ color: THEME.ink }}>
            <span className="headline-line">
              {HEADLINE.split(" ").map((w, i, arr) => (
                <span
                  className="word"
                  key={i}
                  style={{ animationDelay: `${0.15 * i}s` }}
                >
                  {w}
                  {i < arr.length - 1 ? " " : ""}
                </span>
              ))}
            </span>
          </h1>
          <p className="sub" style={{ color: THEME.dim }}>{SUB}</p>

          <div className="meta-row">
            <Countdown />
            <div className="meta-divider" style={{ background: THEME.line }}></div>
            <div className="meta-block">
              <div className="meta-label" style={{ color: THEME.dim }}>follow along</div>
              <a className="meta-link" style={{ color: THEME.ink }} href="https://x.com/waverunnerai" target="_blank" rel="noreferrer">@waverunnerai ↗</a>
              <a className="meta-link" style={{ color: THEME.ink }} href="mailto:hello@waverunner.ai">hello@waverunner.ai ↗</a>
            </div>
          </div>
        </div>

        <SystemLog />
      </main>

      <Ticker />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
