// API keys — URL `/api-keys`. Drives the framework's BUILT-IN key management
// surface (`GET/POST /v1/api-keys*`), which the api exposes when it sets
// `apiKeys: true`. Keys are hash-stored; the raw token is shown exactly ONCE at
// mint time and is unrecoverable after.
//
// This surface is admin-scoped and off by default, so the page DEGRADES: a 404
// means the api hasn't enabled `apiKeys`, a 401/403 means the signed-in user
// lacks the scope. It tells the operator exactly what to turn on rather than
// showing a broken table. (api-saas-starter does not enable it out of the box —
// see the README.)
import type { ReactNode } from 'react'
import { useEffect, useState, type FormEvent } from 'react'
import type { PageMeta } from '@voltro/web'
import { T, useT } from '@voltro/i18n'
import { getCatalog } from '../../../locales/index'
import type { ApiKey } from '../../../lib/api'

export const renderMode = 'ssr' as const

export const meta = ({ locale }: { readonly locale: string }): PageMeta => ({
  title: getCatalog(locale)['meta.apiKeys.title'],
})

type State = 'loading' | 'ready' | 'notEnabled' | 'noAccess' | 'error'

const BASE = '/v1/api-keys'

export default function ApiKeys(): ReactNode {
  const [state, setState] = useState<State>('loading')
  const [keys, setKeys] = useState<ReadonlyArray<ApiKey>>([])
  const [name, setName] = useState('')
  const [minted, setMinted] = useState<string | null>(null)
  const [pending, setPending] = useState(false)
  const nameLabel = useT('apiKeys.name.placeholder')

  const load = (): void => {
    void fetch(BASE, { headers: { accept: 'application/json' } })
      .then(async (res) => {
        if (res.ok) {
          const body = (await res.json()) as { keys: ReadonlyArray<ApiKey> }
          setKeys(body.keys ?? [])
          setState('ready')
        } else if (res.status === 404) setState('notEnabled')
        else if (res.status === 401 || res.status === 403) setState('noAccess')
        else setState('error')
      })
      .catch(() => setState('error'))
  }

  useEffect(load, [])

  const onIssue = (e: FormEvent): void => {
    e.preventDefault()
    const trimmed = name.trim()
    if (trimmed === '') return
    setPending(true)
    setMinted(null)
    void fetch(`${BASE}/issue`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ name: trimmed }),
    })
      .then(async (res) => {
        if (res.ok) {
          const body = (await res.json()) as { token: string }
          setMinted(body.token)
          setName('')
          load()
        }
      })
      .finally(() => setPending(false))
  }

  const onRevoke = (id: string): void => {
    void fetch(`${BASE}/revoke`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ id }),
    }).then(() => load())
  }

  return (
    <section>
      <h1><T id="apiKeys.heading" /></h1>

      {state === 'loading' ? <p className="empty"><T id="apiKeys.loading" /></p> : null}
      {state === 'notEnabled' ? <p className="notice" role="status"><T id="apiKeys.notEnabled" /></p> : null}
      {state === 'noAccess' ? <p className="notice" role="status"><T id="apiKeys.noAccess" /></p> : null}
      {state === 'error' ? <p className="error-text" role="alert"><T id="apiKeys.error" /></p> : null}

      {state === 'ready' ? (
        <>
          <form className="row" onSubmit={onIssue} style={{ marginTop: '0.5rem' }}>
            <input aria-label={nameLabel} placeholder={nameLabel} value={name} onChange={(e) => setName(e.target.value)} />
            <button type="submit" className="btn" disabled={pending}><T id="apiKeys.issue" /></button>
          </form>

          {minted ? (
            <div className="paywall" role="alert" style={{ marginTop: '1rem' }}>
              <strong><T id="apiKeys.minted.title" /></strong>
              <p className="muted"><T id="apiKeys.minted.body" /></p>
              <code className="token">{minted}</code>
            </div>
          ) : null}

          {keys.length === 0 ? (
            <p className="empty"><T id="apiKeys.empty" /></p>
          ) : (
            <ul className="rows" style={{ marginTop: '1.25rem' }}>
              {keys.map((k) => (
                <li key={k.id}>
                  <span className="grow">{k.name} <code>{k.keyPrefix}…</code></span>
                  {k.revokedAt
                    ? <span className="tag"><T id="apiKeys.revoked" /></span>
                    : <button type="button" className="link" onClick={() => onRevoke(k.id)}><T id="apiKeys.revoke" /></button>}
                </li>
              ))}
            </ul>
          )}
        </>
      ) : null}
    </section>
  )
}
