import { useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import PublicLayout from '../../components/PublicLayout.jsx'
import PageHeader from '../../components/PageHeader.jsx'
import { Loading, ErrorState, EmptyState } from '../../components/PageState.jsx'
import { useAsync } from '../../lib/useAsync.js'
import { api } from '../../api/client.js'

// One creature: where it spawns, and what spawns alongside it.
//
// `places` is the point of the page — the aggregate that turns 62 raw
// coordinates into "Shrines, Isamu-Jima, Yew". The individual spawners are
// available underneath for the reader who actually wants a coordinate, but they
// are secondary and collapsed by default.

const num = (v) => (Number.isFinite(v) ? v.toLocaleString() : '—')

// Spawn delays are stored in seconds. A raw "1200" tells the reader nothing.
function delay(min, max) {
  const fmt = (s) => (s >= 60 ? `${Math.round(s / 60)}m` : `${s}s`)
  if (!Number.isFinite(min) || !Number.isFinite(max)) return null
  if (min === max) return fmt(min)
  return `${fmt(min)}–${fmt(max)}`
}

function Panel({ title, right, children }) {
  return (
    <section className="panel" style={{ padding: 18 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12 }}>
        <h2 className="display" style={{ margin: '0 0 12px', fontSize: '1.02rem', color: 'var(--head)' }}>
          {title}
        </h2>
        {right}
      </div>
      {children}
    </section>
  )
}

function Places({ places }) {
  if (places.length === 0) {
    return <p className="sans dim" style={{ margin: 0 }}>No placed spawners.</p>
  }
  return (
    <div>
      {places.map((place) => (
        <div
          key={`${place.facet}:${place.label}`}
          className="sans"
          style={{
            display: 'flex',
            alignItems: 'baseline',
            justifyContent: 'space-between',
            gap: 12,
            padding: '6px 0',
            borderBottom: '1px solid var(--line)',
            fontSize: '0.86rem',
          }}
        >
          <span style={{ minWidth: 0, color: 'var(--head)' }}>{place.label}</span>
          <span className="dim" style={{ flex: 'none' }}>
            {place.facet} · {num(place.spawners)} spawner{place.spawners === 1 ? '' : 's'} · up to{' '}
            {num(place.maxAlive)} at once
          </span>
        </div>
      ))}
    </div>
  )
}

function Spawners({ spawners, truncated }) {
  const [open, setOpen] = useState(false)
  if (spawners.length === 0) return null
  return (
    <Panel
      title="Individual spawners"
      right={
        <button
          type="button"
          className="sans"
          onClick={() => setOpen((v) => !v)}
          style={{ background: 'none', border: 'none', color: 'var(--accent)', cursor: 'pointer', fontSize: '0.78rem' }}
        >
          {open ? 'Hide' : `Show ${num(spawners.length)}`}
        </button>
      }
    >
      {open && (
        <div style={{ overflowX: 'auto' }}>
          <table className="sans" style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.8rem' }}>
            <thead>
              <tr style={{ textAlign: 'left', color: 'var(--muted)' }}>
                <th style={{ padding: '4px 8px 8px 0' }}>Place</th>
                <th style={{ padding: '4px 8px 8px 0' }}>Facet</th>
                <th style={{ padding: '4px 8px 8px 0' }}>Coords</th>
                <th style={{ padding: '4px 8px 8px 0' }}>Max</th>
                <th style={{ padding: '4px 0 8px 0' }}>Respawn</th>
              </tr>
            </thead>
            <tbody>
              {spawners.map((s) => (
                <tr key={s.id} style={{ borderTop: '1px solid var(--line)' }}>
                  <td style={{ padding: '6px 8px 6px 0', color: 'var(--head)' }}>{s.label}</td>
                  <td style={{ padding: '6px 8px 6px 0' }} className="dim">{s.facet}</td>
                  <td style={{ padding: '6px 8px 6px 0' }} className="dim">{s.x}, {s.y}</td>
                  <td style={{ padding: '6px 8px 6px 0' }} className="dim">{num(s.maxCount)}</td>
                  <td style={{ padding: '6px 0' }} className="dim">{delay(s.minDelay, s.maxDelay) || '—'}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {truncated && (
            <p className="sans dim" style={{ fontSize: '0.74rem', margin: '10px 0 0' }}>
              Only the largest spawners are listed.
            </p>
          )}
        </div>
      )}
    </Panel>
  )
}

export default function AtlasCreature() {
  const { slug } = useParams()
  const { loading, error, data } = useAsync(() => api.atlas.creature(slug), [slug])

  // A 404 here means "no such creature in this atlas", which is a real answer
  // and not a failure — a visitor following a stale link deserves to be told
  // that plainly rather than shown a generic error box.
  const missing = error?.status === 404 || error?.message === 'Not Found'

  const facets = useMemo(
    () => Object.entries(data?.facets || {}).sort((a, b) => b[1] - a[1]),
    [data],
  )

  return (
    <PublicLayout section="website">
      <div className="shell-narrow page-body">
        <p className="sans" style={{ marginBottom: 8 }}>
          <Link to="/site/atlas" style={{ color: 'var(--accent)', fontSize: '0.78rem' }}>
            ← Spawn atlas
          </Link>
        </p>

        {loading && <Loading />}
        {error && !missing && <ErrorState message="Could not load that creature right now." />}
        {missing && <EmptyState>Nothing by that name spawns on this shard.</EmptyState>}

        {!loading && !error && data && (
          <>
            <PageHeader
              eyebrow="Bestiary"
              title={data.name}
              lead={`Up to ${num(data.total)} alive at once across ${num(data.points)} spawner${data.points === 1 ? '' : 's'}.`}
            />

            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              <Panel
                title="Where it spawns"
                right={
                  <span className="sans dim" style={{ fontSize: '0.74rem' }}>
                    {facets.map(([facet, n]) => `${facet} (${n})`).join(' · ')}
                  </span>
                }
              >
                <Places places={data.places || []} />
              </Panel>

              <Spawners spawners={data.spawners || []} truncated={!!data.spawnersTruncated} />

              {data.alsoHere?.length > 0 && (
                <Panel title="Shares a spawner with">
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                    {data.alsoHere.map((other) => (
                      <Link
                        key={other.slug}
                        to={`/site/atlas/${encodeURIComponent(other.slug)}`}
                        className="sans"
                        style={{
                          fontSize: '0.78rem',
                          padding: '4px 11px',
                          borderRadius: 999,
                          border: '1px solid var(--line)',
                          color: 'var(--muted)',
                          textDecoration: 'none',
                        }}
                      >
                        {other.name} <span className="dim">×{num(other.shared)}</span>
                      </Link>
                    ))}
                  </div>
                </Panel>
              )}
            </div>
          </>
        )}
      </div>
    </PublicLayout>
  )
}
