'use client'

import { useCallback, useEffect, useState } from 'react'
import { Panel } from '@/components/cluster/Panel'
import { DEFAULT_KINDS, WAVES, apps, appsInWave, resourceKinds, type App } from '@/lib/clusterMock'

const TOTAL_RESOURCES = apps.reduce((n, a) => n + a.resources, 0)

/** Resource count as discrete cells, capped so a 68-resource app stays readable. */
function CountBar({ n }: { n: number }) {
  const cells = Math.min(n, 24)
  return (
    <div className="mt-2 flex flex-wrap gap-[2px]" aria-label={`${n} resources`}>
      {Array.from({ length: cells }, (_, i) => (
        <span key={i} className="h-1.5 w-1.5 rounded-[1px] bg-wire-lit" />
      ))}
      {n > 24 && <span className="ml-1 font-data text-[9px] leading-none text-dim">+{n - 24}</span>}
    </div>
  )
}

function AppCard({
  app,
  state,
  active,
  onSelect,
}: {
  app: App
  state: 'idle' | 'syncing' | 'done'
  active: boolean
  onSelect: () => void
}) {
  const degraded = app.health === 'degraded'
  const drifted = app.sync === 'outofsync'

  const border = active
    ? 'border-lamp'
    : state === 'syncing'
      ? 'border-lamp/70'
      : degraded
        ? 'border-rose/50'
        : drifted
          ? 'border-lamp/40'
          : 'border-wire'

  return (
    <button
      onClick={onSelect}
      aria-pressed={active}
      className={[
        'w-full border bg-deck p-2.5 text-left transition-all duration-300',
        'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lamp',
        border,
        state === 'syncing' ? 'bg-riser' : '',
        active ? 'bg-riser' : 'hover:border-wire-lit',
      ].join(' ')}
    >
      <div className="flex items-start justify-between gap-2">
        <span className="font-data text-[11px] leading-tight text-chalk">{app.name}</span>
        <span
          className={[
            'mt-1 h-1.5 w-1.5 shrink-0 rounded-full transition-colors',
            state === 'syncing' ? 'bg-lamp' : degraded ? 'bg-rose' : drifted ? 'bg-lamp' : 'bg-flux',
          ].join(' ')}
        />
      </div>
      <CountBar n={app.resources} />
      {(degraded || drifted) && (
        <p className={`mt-2 font-data text-[9px] uppercase tracking-[0.14em] ${degraded ? 'text-rose' : 'text-lamp'}`}>
          {degraded ? 'degraded' : 'out of sync'}
        </p>
      )}
    </button>
  )
}

export default function DeliveryPage() {
  const [selected, setSelected] = useState<string | null>('prometheus')
  const [front, setFront] = useState<number | null>(null)

  const replay = useCallback(() => setFront(0), [])

  useEffect(() => {
    if (front === null) return
    if (front > 8) {
      const done = setTimeout(() => setFront(null), 700)
      return () => clearTimeout(done)
    }
    const next = setTimeout(() => setFront((w) => (w === null ? null : w + 1)), 520)
    return () => clearTimeout(next)
  }, [front])

  const selectedApp = apps.find((a) => a.name === selected) ?? null
  const kinds = selectedApp ? (resourceKinds[selectedApp.name] ?? DEFAULT_KINDS) : []

  return (
    <div className="space-y-6">
      <header className="border border-wire bg-deck p-6 md:p-8">
        <p className="font-data text-[10px] uppercase tracking-[0.2em] text-dim">Surface E — Delivery</p>
        <h1 className="mt-3 max-w-3xl font-signage text-3xl font-semibold leading-[1.1] tracking-signage md:text-5xl">
          Nothing starts until the thing it needs is already running.
        </h1>
        <p className="mt-5 max-w-2xl font-plex text-sm leading-relaxed text-dim">
          {apps.length} applications, {TOTAL_RESOURCES} resources, applied in nine ordered waves. Certificates
          before issuers, issuers before ingress, storage before the databases that sit on it. The order is the
          design.
        </p>
        <button
          onClick={replay}
          disabled={front !== null}
          className="mt-6 border border-lamp px-4 py-2 font-data text-[11px] uppercase tracking-[0.16em] text-lamp transition-colors hover:bg-lamp hover:text-void focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lamp disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-lamp"
        >
          {front !== null ? `syncing wave ${Math.min(front, 8)}` : 'Replay sync'}
        </button>
      </header>

      <div className="grid gap-6 xl:grid-cols-[1fr_340px]">
        <Panel label="Sync waves" hint="0 → 8, left to right" className="min-w-0">
          <div className="-mx-4 overflow-x-auto px-4 pb-2">
            <div className="flex min-w-max gap-3">
              {WAVES.map((wave) => {
                const inWave = appsInWave(wave)
                const state = front === null ? 'idle' : front === wave ? 'syncing' : front > wave ? 'done' : 'idle'

                return (
                  <div key={wave} className="w-[168px] shrink-0">
                    <div
                      className={[
                        'mb-3 flex items-baseline justify-between border-b pb-1.5 transition-colors',
                        state === 'syncing' ? 'border-lamp' : 'border-wire',
                      ].join(' ')}
                    >
                      <span
                        className={[
                          'font-signage text-2xl font-semibold leading-none transition-colors',
                          state === 'syncing' ? 'text-lamp' : inWave.length ? 'text-chalk' : 'text-wire-lit',
                        ].join(' ')}
                      >
                        {wave}
                      </span>
                      <span className="font-data text-[9px] uppercase tracking-[0.14em] text-dim">
                        {inWave.length || '—'}
                      </span>
                    </div>

                    {inWave.length === 0 ? (
                      <p className="border border-dashed border-wire p-2.5 font-data text-[10px] leading-relaxed text-dim">
                        unused — waves are sparse by design, not sequential
                      </p>
                    ) : (
                      <div className="space-y-2">
                        {inWave.map((app) => (
                          <AppCard
                            key={app.name}
                            app={app}
                            state={state}
                            active={selected === app.name}
                            onSelect={() => setSelected(app.name)}
                          />
                        ))}
                      </div>
                    )}
                  </div>
                )
              })}
            </div>
          </div>
        </Panel>

        <Panel
          label={selectedApp ? selectedApp.name : 'No selection'}
          hint={selectedApp ? `wave ${selectedApp.wave ?? '—'} · ${selectedApp.resources} resources` : 'pick an app'}
        >
          {selectedApp ? (
            <div className="space-y-4">
              <dl className="grid grid-cols-2 gap-3 font-data text-[11px]">
                <div>
                  <dt className="text-dim">sync</dt>
                  <dd className={selectedApp.sync === 'synced' ? 'text-flux' : 'text-lamp'}>{selectedApp.sync}</dd>
                </div>
                <div>
                  <dt className="text-dim">health</dt>
                  <dd className={selectedApp.health === 'healthy' ? 'text-flux' : 'text-rose'}>
                    {selectedApp.health}
                  </dd>
                </div>
              </dl>

              <div>
                <p className="mb-2 font-data text-[10px] uppercase tracking-[0.16em] text-dim">Resources by kind</p>
                <ul className="space-y-1.5">
                  {kinds.map((k) => (
                    <li key={k.kind} className="flex items-center gap-3 font-data text-[11px]">
                      <span className={k.named ? 'text-chalk' : 'text-dim'}>{k.kind}</span>
                      <span className="h-px flex-1 bg-wire" />
                      <span className="tabular-nums text-dim">{k.count}</span>
                      {!k.named && (
                        <span className="border border-wire-lit px-1 text-[9px] uppercase tracking-[0.1em] text-dim">
                          count only
                        </span>
                      )}
                    </li>
                  ))}
                </ul>
              </div>

              <p className="border-t border-wire pt-3 font-plex text-[11px] leading-relaxed text-dim">
                Secrets appear as counts. Names, source repositories, and condition messages are never sent to the
                browser.
              </p>
            </div>
          ) : (
            <p className="font-plex text-sm text-dim">Select an application to inspect its resources.</p>
          )}
        </Panel>
      </div>
    </div>
  )
}
