/* Shared UI primitives + hooks */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------- Icons (inline SVGs) ---------- */
const Icon = {
  Search: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <circle cx="11" cy="11" r="7" />
      <line x1="21" y1="21" x2="16.65" y2="16.65" />
    </svg>
  ),
  ChevronLeft: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polyline points="15 18 9 12 15 6" />
    </svg>
  ),
  ChevronRight: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polyline points="9 18 15 12 9 6" />
    </svg>
  ),
  ArrowRight: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <line x1="5" y1="12" x2="19" y2="12" />
      <polyline points="12 5 19 12 12 19" />
    </svg>
  ),
  Upload: (p) => (
    <svg viewBox="0 0 24 24" width="32" height="32" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
      <polyline points="17 8 12 3 7 8" />
      <line x1="12" y1="3" x2="12" y2="15" />
    </svg>
  ),
  File: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
      <polyline points="14 2 14 8 20 8" />
    </svg>
  ),
  Logout: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
      <polyline points="16 17 21 12 16 7" />
      <line x1="21" y1="12" x2="9" y2="12" />
    </svg>
  ),
  Check: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polyline points="20 6 9 17 4 12" />
    </svg>
  ),
  X: (p) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <line x1="18" y1="6" x2="6" y2="18" />
      <line x1="6" y1="18" x2="18" y2="6" />
    </svg>
  ),
};

/* ---------- Page-load delay (every nav) ----------
 * Fires real chained httpbin.org/delay requests on every navigation so
 * the page-load duration is visible in the Network tab. httpbin caps
 * each /delay/N at 10 seconds, so longer loads are broken into chunks.
 * The final chunk is tagged `event=page-ready` — candidates can wait
 * for that specific request to know the page has finished loading.
 * A 5-second failsafe ensures we never stay stuck if the network is
 * blocked.
 */
function useArtificialDelay(key, ms = 700) {
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    setLoading(true);
    if (ms <= 0) { setLoading(false); return; }

    const controller = new AbortController();
    let cancelled = false;

    const failsafe = setTimeout(() => {
      if (!cancelled) setLoading(false);
    }, ms + 5000);

    (async () => {
      const totalChunks = Math.max(1, Math.ceil(ms / 10000));
      let remaining = ms;
      for (let i = 1; i <= totalChunks; i++) {
        if (cancelled) return;
        const chunkMs = Math.min(remaining, 10000);
        const chunkSec = Math.max(1, Math.round(chunkMs / 1000));
        const isLast = i === totalChunks;
        const event = isLast ? "page-ready" : "page-loading";
        const url =
          `https://httpbin.org/delay/${chunkSec}` +
          `?event=${event}&chunk=${i}-of-${totalChunks}` +
          `&page=${encodeURIComponent(key)}`;
        try {
          await fetch(url, { signal: controller.signal, cache: "no-store" });
        } catch (_) {
          // Aborted (navigated away) or offline — bail out; failsafe
          // timer above will release the loading state.
          return;
        }
        remaining -= chunkMs;
      }
      if (!cancelled) setLoading(false);
    })();

    return () => {
      cancelled = true;
      controller.abort();
      clearTimeout(failsafe);
    };
  }, [key, ms]);
  return loading;
}

function PageLoader() {
  return (
    <div className="page-loader" data-testid="page-loader" role="progressbar" aria-busy="true">
      <div className="page-loader-bar" />
    </div>
  );
}

function PageSkeleton({ kind = "topic" }) {
  if (kind === "home") {
    return (
      <div className="page-skeleton" data-testid="page-skeleton">
        <div className="skeleton" style={{ height: 36, width: 240, marginBottom: 12 }} />
        <div className="skeleton" style={{ height: 16, width: 360, marginBottom: 32 }} />
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))", gap: 16 }}>
          {Array.from({ length: 9 }).map((_, i) => (
            <div key={i} className="skeleton" style={{ height: 144 }} />
          ))}
        </div>
      </div>
    );
  }
  return (
    <div className="page-skeleton" data-testid="page-skeleton">
      <div className="skeleton" style={{ height: 14, width: 120, marginBottom: 12 }} />
      <div className="skeleton" style={{ height: 36, width: 340, marginBottom: 12 }} />
      <div className="skeleton" style={{ height: 16, width: "60%", marginBottom: 32 }} />
      <div className="skeleton" style={{ height: 120, marginBottom: 24 }} />
      <div className="skeleton" style={{ height: 220 }} />
    </div>
  );
}

/* ---------- Test surface wrapper ---------- */
function TestSurface({ title = "Test surface", onReset, children }) {
  return (
    <div className="test-surface" data-testid="test-surface">
      <div className="test-surface-head">
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span className="dot" />
          <span>{title}</span>
        </div>
        {onReset && (
          <button className="test-reset" data-testid="test-reset" onClick={onReset}>
            Reset
          </button>
        )}
      </div>
      <div className="test-surface-body">{children}</div>
    </div>
  );
}

/* ---------- Top bar ---------- */
function TopBar({ crumbs = [], user = "Candidate", onLogout, onNavHome }) {
  return (
    <header className="topbar" data-testid="topbar">
      <a className="topbar-brand" onClick={onNavHome} style={{ cursor: "pointer" }} data-testid="brand-link">
        <span className="brand-mark">Q</span>
        <span>QA Candidate Testing</span>
      </a>
      {crumbs.length > 0 && (
        <nav className="topbar-crumbs" data-testid="breadcrumbs">
          <span className="sep">/</span>
          {crumbs.map((c, i) => (
            <React.Fragment key={i}>
              {c.href ? (
                <a onClick={c.onClick} style={{ cursor: "pointer" }}>{c.label}</a>
              ) : (
                <span style={{ color: "var(--fg)" }}>{c.label}</span>
              )}
              {i < crumbs.length - 1 && <span className="sep">/</span>}
            </React.Fragment>
          ))}
        </nav>
      )}
      <div className="topbar-spacer" />
      <div className="topbar-user">
        <span>Signed in as <strong style={{ color: "var(--fg)" }}>{user}</strong></span>
        <button className="btn btn-ghost btn-sm" data-testid="logout" onClick={onLogout}>
          <Icon.Logout /> Sign out
        </button>
        <div className="avatar" aria-hidden="true">{user.slice(0,2).toUpperCase()}</div>
      </div>
    </header>
  );
}

Object.assign(window, { Icon, useArtificialDelay, PageLoader, PageSkeleton, TestSurface, TopBar });
