import { useEffect, useMemo, useState } from 'react'
import { createFileRoute, Link } from '@tanstack/react-router'
import { ApiReferenceReact } from '@scalar/api-reference-react'
// @scalar/api-reference-react@0.9.47's entry does NOT import its own stylesheet
// (and doesn't inject it at runtime), so we must ship it ourselves or the
// reference renders unstyled. Load it as a route-scoped <link> (same pattern as
// the root app.css), so it's present for SSR + the client-side Vue mount.
import scalarCss from '@scalar/api-reference-react/style.css?url'
import BrandMark from '@/components/BrandMark'
import Wordmark from '@/components/Wordmark'

export const Route = createFileRoute('/api/')({
  component: ApiReference,
  head: () => ({
    meta: [
      { title: 'punktfunk — Management API reference' },
      {
        name: 'description',
        content:
          'Interactive reference for the punktfunk host management REST API (OpenAPI).',
      },
    ],
    links: [{ rel: 'stylesheet', href: scalarCss }],
  }),
})

// The full punktfunk theme rolled out onto Scalar — the same dark-violet (and
// light-lavender) product chrome as the docs/management console.
//
// IMPORTANT: Scalar toggles `.light-mode` / `.dark-mode` on `document.body`,
// and it renders our `customCss` *before* its own built-in theme preset in the
// SAME <style> tag. A bare `.dark-mode { … }` therefore has equal specificity
// to the preset that comes after it and LOSES (you get Scalar's stock #0f0f0f
// gray). Scoping to `body.dark-mode` / `body.light-mode` (specificity 0,1,1)
// beats both the linked base sheet and the in-component preset, so our palette
// wins regardless of source order. Scalar ignores unknown custom-property
// names, so this stays forward-safe.
const SCALAR_CSS = `
body.light-mode,
body.dark-mode {
  --scalar-font: 'Geist Variable', ui-sans-serif, system-ui, sans-serif;
  --scalar-font-code: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  --scalar-radius: 0.5rem;
  --scalar-radius-lg: 0.75rem;
  --scalar-radius-xl: 0.875rem;
}

/* ── Dark — the violet-tinted app-icon chrome (bg #141019 / cards #1c1530). ── */
body.dark-mode {
  --scalar-background-1: #141019;
  --scalar-background-2: #1c1530;
  --scalar-background-3: #221a36;
  --scalar-background-accent: #6c5bf32e;
  --scalar-border-color: #2a2148;

  --scalar-color-1: #f4f2fb;
  --scalar-color-2: #b7b1c9;
  --scalar-color-3: #8a85a0;
  --scalar-color-accent: #a79ff8;

  --scalar-link-color: #a79ff8;
  --scalar-link-color-hover: #c8c0fb;

  --scalar-button-1: #6c5bf3;
  --scalar-button-1-color: #ffffff;
  --scalar-button-1-hover: #5d4ee0;

  --scalar-sidebar-background-1: #17121f;
  --scalar-sidebar-color-1: #e9e6f4;
  --scalar-sidebar-color-2: #9a94ad;
  --scalar-sidebar-color-active: #c8c0fb;
  --scalar-sidebar-item-hover-background: #6c5bf31f;
  --scalar-sidebar-item-hover-color: #f4f2fb;
  --scalar-sidebar-item-active-background: #6c5bf333;
  --scalar-sidebar-border-color: #241c3d;
  --scalar-sidebar-search-background: #1c1530;
  --scalar-sidebar-search-border-color: #2a2148;
  --scalar-sidebar-search-color: #9a94ad;
  --scalar-sidebar-indent-border: #2a2148;
  --scalar-sidebar-indent-border-active: #6c5bf3;
  --scalar-sidebar-indent-border-hover: #463a78;

  --scalar-header-background-1: #141019;
  --scalar-header-color-1: #f4f2fb;
  --scalar-header-border-color: #2a2148;

  --scalar-scrollbar-color: #2a2148;
  --scalar-scrollbar-color-active: #463a78;

  --scalar-color-green: #4ade80;
  --scalar-color-red: #f87171;
  --scalar-color-yellow: #fbbf24;
  --scalar-color-blue: #60a5fa;
  --scalar-color-orange: #fb923c;
  --scalar-color-purple: #a79ff8;
}

/* ── Light — the lavender docs surface (bg #f0ebff / white content). ── */
body.light-mode {
  --scalar-background-1: #ffffff;
  --scalar-background-2: #f6f2ff;
  --scalar-background-3: #ece6fb;
  --scalar-background-accent: #6c5bf31a;
  --scalar-border-color: #e4dcf7;

  --scalar-color-1: #1b1430;
  --scalar-color-2: #4a4368;
  --scalar-color-3: #6f6a86;
  --scalar-color-accent: #6c5bf3;

  --scalar-link-color: #6c5bf3;
  --scalar-link-color-hover: #5d4ee0;

  --scalar-button-1: #6c5bf3;
  --scalar-button-1-color: #ffffff;
  --scalar-button-1-hover: #5d4ee0;

  --scalar-sidebar-background-1: #f6f2ff;
  --scalar-sidebar-color-1: #1b1430;
  --scalar-sidebar-color-2: #6f6a86;
  --scalar-sidebar-color-active: #5d4ee0;
  --scalar-sidebar-item-hover-background: #6c5bf314;
  --scalar-sidebar-item-hover-color: #1b1430;
  --scalar-sidebar-item-active-background: #6c5bf322;
  --scalar-sidebar-border-color: #e4dcf7;
  --scalar-sidebar-search-background: #ffffff;
  --scalar-sidebar-search-border-color: #e4dcf7;
  --scalar-sidebar-search-color: #6f6a86;
  --scalar-sidebar-indent-border: #e4dcf7;
  --scalar-sidebar-indent-border-active: #6c5bf3;
  --scalar-sidebar-indent-border-hover: #c9bdf0;

  --scalar-header-background-1: #ffffff;
  --scalar-header-color-1: #1b1430;
  --scalar-header-border-color: #e4dcf7;

  --scalar-scrollbar-color: #d9d0f2;
  --scalar-scrollbar-color-active: #bcb0ec;

  --scalar-color-green: #16a34a;
  --scalar-color-red: #dc2626;
  --scalar-color-yellow: #d97706;
  --scalar-color-blue: #2563eb;
  --scalar-color-orange: #ea580c;
  --scalar-color-purple: #6c5bf3;
}
`

function ApiReference() {
  // Follow the docs' own light/dark switch and hide Scalar's own toggle, so the
  // Fumadocs toggle stays the single source of truth. Fumadocs drives next-themes
  // with `attribute: "class"`, which writes the resolved theme as a class on
  // <html> — we read THAT class directly rather than next-themes' useTheme().
  // The class is the authoritative, already-resolved signal (system → light/dark
  // included) and, unlike the React context, can't be desynced when bridging into
  // Scalar's separate Vue app. Default to dark (the docs default) so SSR and the
  // first client render agree — no hydration flash; the observer then syncs to the
  // live class, tracking the docs toggle AND OS changes while in system mode.
  const [isDark, setIsDark] = useState(true)
  useEffect(() => {
    const root = document.documentElement
    const sync = () => setIsDark(root.classList.contains('dark'))
    sync()
    const observer = new MutationObserver(sync)
    observer.observe(root, { attributes: true, attributeFilter: ['class'] })
    return () => observer.disconnect()
  }, [])

  // Scalar pollutes global scope and never cleans up: it appends a persistent
  // <style id="scalar-style"> to <head> that includes a *global*
  // `body { background-color: var(--scalar-background-1) }`, adds its #scalar-refs
  // teleport target, and toggles .dark-mode/.light-mode on <body>. After a
  // client-side route change (no reload) that residue bleeds into the next page —
  // the docs body kept painting Scalar's bg instead of --color-fd-background, so
  // the docs looked gray until a hard reload. Strip it when /api unmounts so
  // leaving the page restores the same DOM a fresh load has; Scalar re-injects a
  // fresh instance on re-entry.
  useEffect(
    () => () => {
      document.getElementById('scalar-style')?.remove()
      document.getElementById('scalar-refs')?.remove()
      document.body.classList.remove('dark-mode', 'light-mode')
    },
    [],
  )

  // A fresh object on each theme flip so the React wrapper's
  // `updateConfiguration` effect fires and Scalar swaps the body mode class.
  const configuration = useMemo(
    () => ({
      url: '/openapi.json',
      darkMode: isDark,
      hideDarkModeToggle: true,
      metaData: { title: 'punktfunk Management API' },
      hideDownloadButton: false,
      customCss: SCALAR_CSS,
    }),
    [isDark],
  )

  return (
    <div className="flex min-h-screen flex-col">
      {/* Slim branded bar so the reference stays inside the punktfunk identity
          and links back into the docs. */}
      <header className="flex h-14 shrink-0 items-center justify-between border-b border-fd-border px-4 md:px-6">
        <Link
          to="/docs/$"
          params={{ _splat: '' }}
          aria-label="punktfunk documentation"
          className="flex items-center gap-2 no-underline"
        >
          <BrandMark className="size-6" />
          <Wordmark className="h-4" />
          <span className="ml-2 hidden text-sm text-fd-muted-foreground sm:inline">
            Management API
          </span>
        </Link>
        <nav className="flex items-center gap-4 text-sm">
          <Link
            to="/docs/$"
            params={{ _splat: '' }}
            className="text-fd-muted-foreground transition-colors hover:text-fd-foreground"
          >
            ← Docs
          </Link>
          <a
            href="/openapi.json"
            className="text-fd-muted-foreground transition-colors hover:text-fd-foreground"
          >
            openapi.json
          </a>
        </nav>
      </header>

      {/* Scalar mounts a Vue app client-side in a useEffect (SSR-safe: the
          server renders an empty container, the browser hydrates the reference). */}
      <div className="min-h-0 flex-1">
        <ApiReferenceReact configuration={configuration} />
      </div>
    </div>
  )
}
