import { useState, useEffect, useMemo, type KeyboardEvent } from 'react'
import { useTranslation } from 'react-i18next'
import { api, endpoints } from '../../api'
import type { DetectionClass, Aircraft, GpsProtocol } from '../../types'
import { useAiSettings } from './useAiSettings'
import { useGpsSettings } from './useGpsSettings'
import { Modal } from './Modal'
import { NumberStepper } from './NumberStepper'
import { ClassEditRow } from './ClassEditRow'

type EditForm = { name: string; shortName: string; color: string; maxSizeM: number }
type EditErrorKind = 'nameRequired' | 'updateFailed'
// editingId === ADDING_ID switches Save from PATCH to POST.
const ADDING_ID = -1
const NEW_CLASS_DEFAULTS: EditForm = { name: '', shortName: '', color: '#FF9D3D', maxSizeM: 7 }

type AircraftDraft = {
  model: string
  type: Aircraft['type']
  resolution: string
  maxMinutes: number
  isDefault: boolean
}
const NEW_AIRCRAFT_DEFAULTS: AircraftDraft = {
  model: '', type: 'Copter', resolution: '4K', maxMinutes: 30, isDefault: false,
}
const AIRCRAFT_TYPES = ['Plane', 'Copter', 'FixedWing'] as const

const PROTOCOLS: GpsProtocol[] = ['NMEA', 'UBX', 'MAVLINK']
const RESOLUTIONS = ['HD', '1080P', '4K', '6K'] as const
const FALLBACK = '—'

const TYPE_COLORS: Record<Aircraft['type'], string> = {
  Plane:     'var(--accent-blue)',
  Copter:    'var(--accent-green)',
  FixedWing: 'var(--accent-amber)',
}
const TYPE_LETTERS: Record<Aircraft['type'], 'P' | 'C' | 'F'> = {
  Plane: 'P', Copter: 'C', FixedWing: 'F',
}
const TYPE_LEGEND_KEY: Record<Aircraft['type'], 'legendPlane' | 'legendCopter' | 'legendFixedW'> = {
  Plane: 'legendPlane', Copter: 'legendCopter', FixedWing: 'legendFixedW',
}

function PencilIcon() {
  return (
    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
      <path d="M12 20h9" />
      <path d="M16.5 3.5a2.121 2.121 0 113 3L7 19l-4 1 1-4L16.5 3.5z" />
    </svg>
  )
}
function CloseIcon() {
  return (
    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
      <line x1="18" y1="6" x2="6" y2="18" />
      <line x1="6" y1="6" x2="18" y2="18" />
    </svg>
  )
}
function StarIcon({ filled }: { filled: boolean }) {
  return (
    <svg width="13" height="13" viewBox="0 0 24 24" fill={filled ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth={filled ? 1 : 1.4}>
      <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
    </svg>
  )
}

function formatRunTime(iso: string | null): string {
  if (!iso) return FALLBACK
  // HH:MM:SSZ rendering, mockup-style.
  const m = iso.match(/T(\d{2}:\d{2}:\d{2})/)
  return m ? `${m[1]}Z` : FALLBACK
}


export default function AdminPage() {
  const { t } = useTranslation()
  const [classes, setClasses] = useState<DetectionClass[]>([])
  const [aircrafts, setAircrafts] = useState<Aircraft[]>([])
  const [classFilter, setClassFilter] = useState('')
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editForm, setEditForm] = useState<EditForm>(NEW_CLASS_DEFAULTS)
  const [editError, setEditError] = useState<EditErrorKind | null>(null)
  const [editSaving, setEditSaving] = useState(false)

  const [aircraftModalOpen, setAircraftModalOpen] = useState(false)
  const [aircraftDraft, setAircraftDraft] = useState<AircraftDraft>(NEW_AIRCRAFT_DEFAULTS)
  const [aircraftSaving, setAircraftSaving] = useState(false)
  const [aircraftError, setAircraftError] = useState<string | null>(null)

  const openAircraftModal = () => {
    setAircraftDraft(NEW_AIRCRAFT_DEFAULTS)
    setAircraftError(null)
    setAircraftModalOpen(true)
  }
  const closeAircraftModal = () => {
    if (aircraftSaving) return
    setAircraftModalOpen(false)
  }
  const saveAircraft = async () => {
    if (!aircraftDraft.model.trim()) { setAircraftError('modelRequired'); return }
    setAircraftError(null)
    setAircraftSaving(true)
    try {
      const created = await api.post<Aircraft>(endpoints.flights.aircrafts(), aircraftDraft)
      setAircrafts(prev => [...prev, created])
      setAircraftModalOpen(false)
    } catch {
      setAircraftError('saveFailed')
    } finally {
      setAircraftSaving(false)
    }
  }

  const ai = useAiSettings()
  const gps = useGpsSettings()

  useEffect(() => {
    api.get<DetectionClass[]>(endpoints.annotations.classes()).then(setClasses).catch(() => {})
    api.get<Aircraft[]>(endpoints.flights.aircrafts()).then(setAircrafts).catch(() => {})
  }, [])

  const filteredClasses = useMemo(() => {
    const q = classFilter.trim().toLowerCase()
    if (!q) return classes
    return classes.filter(c => c.name.toLowerCase().includes(q))
  }, [classes, classFilter])

  const handleStartAdd = () => {
    setEditingId(ADDING_ID)
    setEditForm({ ...NEW_CLASS_DEFAULTS })
    setEditError(null)
    setEditSaving(false)
  }

  const handleDeleteClass = async (id: number) => {
    await api.delete(endpoints.admin.class(id))
    setClasses(prev => prev.filter(c => c.id !== id))
  }

  const handleStartEdit = (c: DetectionClass) => {
    setEditingId(c.id)
    setEditForm({ name: c.name, shortName: c.shortName, color: c.color, maxSizeM: c.maxSizeM })
    setEditError(null)
    setEditSaving(false)
  }

  const handleCancelEdit = () => {
    setEditingId(null)
    setEditError(null)
    setEditSaving(false)
  }

  const handleSaveClass = async () => {
    if (editingId === null || editSaving) return
    if (!editForm.name.trim()) { setEditError('nameRequired'); return }
    setEditError(null)
    setEditSaving(true)
    try {
      if (editingId === ADDING_ID) {
        const created = await api.post<DetectionClass>(endpoints.admin.classes(), editForm)
        setClasses(prev => [...prev, created])
      } else {
        const updated = await api.patch<DetectionClass>(endpoints.admin.class(editingId), editForm)
        setClasses(prev => prev.map(c => c.id === editingId ? updated : c))
      }
      setEditingId(null)
    } catch {
      setEditError('updateFailed')
    } finally {
      setEditSaving(false)
    }
  }

  const handleEditKeyDown = (e: KeyboardEvent<HTMLElement>) => {
    if (e.key === 'Enter') { e.preventDefault(); void handleSaveClass() }
    else if (e.key === 'Escape') { e.preventDefault(); handleCancelEdit() }
  }

  const handleToggleDefault = async (a: Aircraft) => {
    await api.patch(endpoints.flights.aircraft(a.id), { isDefault: !a.isDefault })
    setAircrafts(prev => prev.map(x => x.id === a.id ? { ...x, isDefault: !x.isDefault } : x))
  }

  return (
    <main className="flex h-full overflow-hidden" style={{ background: 'var(--surface-0)' }}>

      {/* ===== LEFT: DETECTION CLASSES (340px) ===== */}
      <aside
        className="shrink-0 flex flex-col"
        style={{ width: 340, background: 'var(--surface-1)', borderRight: '1px solid var(--border-hair)' }}
      >
        <div
          className="px-4 pt-4 pb-3 flex items-center justify-between"
          style={{ borderBottom: '1px solid var(--border-hair)' }}
        >
          <div className="flex items-center gap-2">
            <span className="sect-head">{t('admin.classes.title')}</span>
            <span className="mono tnum" style={{ fontSize: 10, color: 'var(--text-muted)' }}>
              [{String(classes.length).padStart(2, '0')}]
            </span>
          </div>
        </div>

        {/* Search + Add */}
        <div
          className="px-4 py-3 flex items-center gap-2"
          style={{ borderBottom: '1px solid var(--border-hair)' }}
        >
          <div className="relative flex-1">
            <svg className="absolute left-2 top-1/2 -translate-y-1/2" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ color: 'var(--text-muted)' }}>
              <circle cx="11" cy="11" r="7" />
              <line x1="21" y1="21" x2="16.65" y2="16.65" />
            </svg>
            <input
              type="text"
              placeholder={t('admin.classes.search')}
              className="inp"
              value={classFilter}
              onChange={e => setClassFilter(e.target.value)}
              style={{ paddingLeft: 26, height: 28, fontSize: 11 }}
            />
          </div>
          <button
            className="btn btn-primary"
            onClick={handleStartAdd}
            type="button"
            disabled={editingId === ADDING_ID}
          >
            <span>{t('admin.classes.add')}</span>
          </button>
        </div>

        {/* Table */}
        <div className="flex-1 overflow-y-auto">
          <table className="w-full tabular">
            <thead className="sticky top-0" style={{ background: 'var(--surface-1)' }}>
              <tr style={{ borderBottom: '1px solid var(--border-hair)' }}>
                <th className="text-left px-3 py-2 micro" style={{ width: 36 }}>#</th>
                <th className="text-left px-2 py-2 micro">{t('admin.classes.colName')}</th>
                <th className="text-center px-2 py-2 micro" style={{ width: 30 }}>{t('admin.classes.colHex')}</th>
                <th className="text-right px-3 py-2 micro" style={{ width: 60 }}>{t('admin.classes.colOps')}</th>
              </tr>
            </thead>
            <tbody>
              {editingId === ADDING_ID && (
                <ClassEditRow
                  idCell="+"
                  rowId="new"
                  form={editForm}
                  onChange={setEditForm}
                  onSave={() => void handleSaveClass()}
                  onCancel={handleCancelEdit}
                  onKeyDown={handleEditKeyDown}
                  saving={editSaving}
                  errorMessage={editError ? t(`admin.classes.${editError}`) : null}
                  placeholderName="Name"
                />
              )}
              {filteredClasses.map(c => c.id === editingId ? (
                <ClassEditRow
                  key={c.id}
                  idCell={c.id}
                  rowId={c.id}
                  form={editForm}
                  onChange={setEditForm}
                  onSave={() => void handleSaveClass()}
                  onCancel={handleCancelEdit}
                  onKeyDown={handleEditKeyDown}
                  saving={editSaving}
                  errorMessage={editError ? t(`admin.classes.${editError}`) : null}
                />
              ) : (
                <tr key={c.id} className="row-hover" style={{ borderBottom: '1px solid var(--border-hair)', height: 32 }}>
                  <td className="px-3 mono tnum" style={{ color: 'var(--text-muted)', fontSize: 12 }}>{c.id}</td>
                  <td className="px-2"><span style={{ fontSize: 12 }}>{c.name}</span></td>
                  <td className="px-2 text-center"><span className="swatch" style={{ background: c.color }} /></td>
                  <td className="px-3 text-right">
                    <span className="reveal inline-flex gap-1">
                      <button
                        type="button"
                        onClick={() => handleStartEdit(c)}
                        className="ibtn edit"
                        aria-label={t('admin.classes.edit')}
                        title={t('admin.classes.edit')}
                      >
                        <PencilIcon />
                      </button>
                      <button
                        type="button"
                        onClick={() => handleDeleteClass(c.id)}
                        className="ibtn danger"
                        aria-label="×"
                        title={t('admin.classes.delete')}
                      >
                        <CloseIcon />
                      </button>
                    </span>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </aside>

      {/* ===== CENTER ===== */}
      <section className="flex-1 overflow-y-auto grid-bg">
        <div className="max-w-[920px] mx-auto p-6 space-y-6">

          {/* AI RECOGNITION ENGINE */}
          <div>
            <div className="flex items-end justify-between mb-3">
              <div>
                <div className="sect-head">{t('admin.aiEngine.title')}</div>
                <div className="hint mt-1">{t('admin.aiEngine.subtitle')}</div>
              </div>
              <div className="flex items-center gap-2 micro">
                <span style={{ color: 'var(--text-muted)' }}>{t('admin.aiEngine.model')}</span>
                <span className="mono tnum" style={{ color: 'var(--text-primary)' }}>
                  {ai.telemetry ? `${ai.telemetry.model} · ${ai.telemetry.checkpoint}` : FALLBACK}
                </span>
                <span className="pill pill-cyan"><span className="dot live" />{t('admin.aiEngine.loaded')}</span>
              </div>
            </div>

            <div className="bracket panel p-5">
              <span className="br" />

              <div className="grid grid-cols-3 gap-x-6 gap-y-4">
                <div>
                  <label className="micro block mb-1">{t('admin.aiEngine.framesToRecognize')}</label>
                  <div className="hint mb-2">{t('admin.aiEngine.framesHint')}</div>
                  <NumberStepper
                    value={ai.draft.framesToRecognize}
                    min={1}
                    step={1}
                    suffix={t('admin.aiEngine.unitFR')}
                    onChange={v => ai.setDraft({ ...ai.draft, framesToRecognize: v })}
                  />
                </div>

                <div>
                  <label className="micro block mb-1">{t('admin.aiEngine.minSeconds')}</label>
                  <div className="hint mb-2">{t('admin.aiEngine.minSecondsHint')}</div>
                  <NumberStepper
                    value={ai.draft.minSecondsBetween}
                    min={0}
                    step={1}
                    suffix={t('admin.aiEngine.unitSec')}
                    onChange={v => ai.setDraft({ ...ai.draft, minSecondsBetween: v })}
                  />
                </div>

                <div>
                  <label className="micro block mb-1">{t('admin.aiEngine.minConfidence')}</label>
                  <div className="hint mb-2">{t('admin.aiEngine.minConfidenceHint')}</div>
                  <NumberStepper
                    value={ai.draft.minConfidence}
                    min={0}
                    max={100}
                    step={5}
                    suffix="%"
                    onChange={v => ai.setDraft({ ...ai.draft, minConfidence: v })}
                  />
                </div>
              </div>

              <div
                className="mt-5 pt-4 flex items-center justify-between"
                style={{ borderTop: '1px dashed var(--border-hair)' }}
              >
                <div className="flex items-center gap-5 micro">
                  <span style={{ color: 'var(--text-muted)' }}>
                    {t('admin.aiEngine.lastRun')}{' '}
                    <span className="mono tnum" style={{ color: 'var(--text-secondary)' }}>
                      {formatRunTime(ai.telemetry?.lastRunAt ?? null)}
                    </span>
                  </span>
                  <span style={{ color: 'var(--text-muted)' }}>
                    {t('admin.aiEngine.frames')}{' '}
                    <span className="mono tnum" style={{ color: 'var(--text-secondary)' }}>
                      {ai.telemetry ? ai.telemetry.frames.toLocaleString() : FALLBACK}
                    </span>
                  </span>
                  <span style={{ color: 'var(--text-muted)' }}>
                    {t('admin.aiEngine.avgConf')}{' '}
                    <span className="mono tnum" style={{ color: 'var(--accent-green)' }}>
                      {ai.telemetry ? `${ai.telemetry.avgConfidence.toFixed(1)}%` : FALLBACK}
                    </span>
                  </span>
                </div>
                <div className="flex items-center gap-2">
                  <button type="button" className="btn btn-ghost" onClick={ai.reset}>
                    {t('admin.aiEngine.reset')}
                  </button>
                  <button
                    type="button"
                    className="btn btn-primary"
                    onClick={() => void ai.save()}
                    disabled={ai.status === 'saving'}
                  >
                    {t('admin.aiEngine.apply')}
                  </button>
                </div>
              </div>
              {ai.error && (
                <div role="alert" className="mt-2" style={{ color: 'var(--accent-red)', fontSize: 11 }}>
                  {ai.error}
                </div>
              )}
            </div>
          </div>

          {/* GPS DEVICE LINK */}
          <div>
            <div className="flex items-end justify-between mb-3">
              <div>
                <div className="sect-head">{t('admin.gpsDevice.title')}</div>
                <div className="hint mt-1">{t('admin.gpsDevice.subtitle')}</div>
              </div>
              <div className="flex items-center gap-2 micro">
                <span style={{ color: 'var(--text-muted)' }}>{t('admin.gpsDevice.socket')}</span>
                <span className="mono tnum" style={{ color: 'var(--text-primary)' }}>
                  {gps.telemetry?.socket ?? FALLBACK}
                </span>
                <span className={`pill ${gps.telemetry?.connected ? 'pill-green' : 'pill-red'}`}>
                  <span className="dot" />
                  {t('admin.gpsDevice.connected')}
                </span>
              </div>
            </div>

            <div className="bracket panel p-5">
              <span className="br" />

              <div className="grid grid-cols-2 gap-x-6 gap-y-4">
                <div>
                  <label className="micro block mb-1">{t('admin.gpsDevice.address')}</label>
                  <div className="hint mb-2">{t('admin.gpsDevice.addressHint')}</div>
                  <input
                    className="inp inp-mono"
                    value={gps.draft.address}
                    placeholder="0.0.0.0"
                    onChange={e => gps.setDraft({ ...gps.draft, address: e.target.value })}
                    aria-label={t('admin.gpsDevice.address')}
                  />
                </div>

                <div>
                  <label className="micro block mb-1">{t('admin.gpsDevice.port')}</label>
                  <div className="hint mb-2">{t('admin.gpsDevice.portHint')}</div>
                  <input
                    className="inp inp-mono"
                    type="number"
                    value={gps.draft.port}
                    onChange={e => gps.setDraft({ ...gps.draft, port: Number(e.target.value) })}
                    style={{ textAlign: 'right' }}
                    aria-label={t('admin.gpsDevice.port')}
                  />
                </div>
              </div>

              <div className="mt-5">
                <label className="micro block mb-1">{t('admin.gpsDevice.protocol')}</label>
                <div className="hint mb-2">{t('admin.gpsDevice.protocolHint')}</div>
                <div className="seg" role="group" aria-label={t('admin.gpsDevice.protocol')}>
                  {PROTOCOLS.map(p => (
                    <button
                      key={p}
                      type="button"
                      onClick={() => gps.setDraft({ ...gps.draft, protocol: p })}
                      className={`seg-btn${gps.draft.protocol === p ? ' active' : ''}`}
                      aria-pressed={gps.draft.protocol === p}
                    >
                      {p}
                    </button>
                  ))}
                </div>
              </div>

              <div
                className="mt-5 pt-4 flex items-center justify-between"
                style={{ borderTop: '1px dashed var(--border-hair)' }}
              >
                <div className="flex items-center gap-5 micro">
                  <span style={{ color: 'var(--text-muted)' }}>
                    {t('admin.gpsDevice.fix')}{' '}
                    <span className="mono tnum" style={{ color: 'var(--accent-green)' }}>
                      {gps.telemetry ? `${gps.telemetry.fix} · ${gps.telemetry.satellites} SAT` : FALLBACK}
                    </span>
                  </span>
                  <span style={{ color: 'var(--text-muted)' }}>
                    {t('admin.gpsDevice.hdop')}{' '}
                    <span className="mono tnum" style={{ color: 'var(--text-secondary)' }}>
                      {gps.telemetry ? gps.telemetry.hdop.toFixed(2) : FALLBACK}
                    </span>
                  </span>
                  <span style={{ color: 'var(--text-muted)' }}>
                    {t('admin.gpsDevice.lastPkt')}{' '}
                    <span className="mono tnum" style={{ color: 'var(--text-secondary)' }}>
                      {gps.telemetry ? `+${gps.telemetry.lastPacketMs}ms` : FALLBACK}
                    </span>
                  </span>
                </div>
                <div className="flex items-center gap-2">
                  <button type="button" className="btn btn-ghost" onClick={() => void gps.ping()} disabled={gps.status === 'pinging'}>
                    {t('admin.gpsDevice.ping')}
                  </button>
                  <button type="button" className="btn btn-secondary" onClick={() => void gps.reconnect()} disabled={gps.status === 'reconnecting'}>
                    {t('admin.gpsDevice.reconnect')}
                  </button>
                  <button
                    type="button"
                    className="btn btn-primary"
                    onClick={() => void gps.save()}
                    disabled={gps.status === 'saving'}
                  >
                    {t('admin.gpsDevice.apply')}
                  </button>
                </div>
              </div>
              {gps.error && (
                <div role="alert" className="mt-2" style={{ color: 'var(--accent-red)', fontSize: 11 }}>
                  {gps.error}
                </div>
              )}
            </div>
          </div>
        </div>
      </section>

      {/* ===== RIGHT: DEFAULT AIRCRAFTS (280px) ===== */}
      <aside
        className="shrink-0 flex flex-col"
        style={{ width: 280, background: 'var(--surface-1)', borderLeft: '1px solid var(--border-hair)' }}
      >
        <div
          className="px-4 pt-4 pb-3 flex items-center justify-between"
          style={{ borderBottom: '1px solid var(--border-hair)' }}
        >
          <span className="sect-head">{t('admin.aircrafts.title')}</span>
          <span className="mono tnum" style={{ fontSize: 10, color: 'var(--text-muted)' }}>
            [{String(aircrafts.length).padStart(2, '0')}]
          </span>
        </div>

        <div
          className="px-4 py-2.5 flex items-center gap-3 micro"
          style={{ borderBottom: '1px solid var(--border-hair)', background: 'var(--surface-0)' }}
        >
          <div className="flex items-center gap-1.5">
            <span className="type-sq" style={{ background: TYPE_COLORS.Plane }}>P</span>
            <span style={{ color: 'var(--text-muted)' }}>{t('admin.aircrafts.legendPlane')}</span>
          </div>
          <div className="flex items-center gap-1.5">
            <span className="type-sq" style={{ background: TYPE_COLORS.Copter }}>C</span>
            <span style={{ color: 'var(--text-muted)' }}>{t('admin.aircrafts.legendCopter')}</span>
          </div>
          <div className="flex items-center gap-1.5">
            <span className="type-sq" style={{ background: TYPE_COLORS.FixedWing }}>F</span>
            <span style={{ color: 'var(--text-muted)' }}>{t('admin.aircrafts.legendFixedW')}</span>
          </div>
        </div>

        <div className="flex-1 overflow-y-auto">
          {aircrafts.map(a => (
            <div
              key={a.id}
              data-aircraft-id={a.id}
              className="row-hover flex items-center gap-3 px-4 py-2.5"
              style={{
                borderBottom: '1px solid var(--border-hair)',
                background: a.isDefault ? 'var(--surface-2)' : 'transparent',
                borderLeft: a.isDefault ? '2px solid var(--accent-amber)' : '2px solid transparent',
              }}
            >
              <span className="type-sq" style={{ background: TYPE_COLORS[a.type] }}>{TYPE_LETTERS[a.type]}</span>
              <div className="flex-1 min-w-0">
                <div style={{ fontSize: 12.5 }}>{a.model}</div>
                <div className="mono tnum" style={{ fontSize: 10.5, color: 'var(--text-muted)' }}>
                  {a.id} · {a.resolution ?? FALLBACK} · {a.maxMinutes ?? FALLBACK}MIN
                </div>
              </div>
              <button
                type="button"
                onClick={() => void handleToggleDefault(a)}
                className={a.isDefault ? 'star' : 'star-off ibtn'}
                aria-label={a.isDefault ? t('admin.aircrafts.default') : t('admin.aircrafts.setDefault')}
                aria-pressed={a.isDefault}
                title={a.isDefault ? t('admin.aircrafts.default') : t('admin.aircrafts.setDefault')}
                style={a.isDefault ? { background: 'transparent', border: 0, cursor: 'pointer' } : undefined}
              >
                <StarIcon filled={a.isDefault} />
              </button>
            </div>
          ))}
        </div>

        <div
          className="px-4 py-3"
          style={{ borderTop: '1px solid var(--border-hair)', background: 'var(--surface-0)' }}
        >
          <button
            type="button"
            className="btn btn-secondary w-full justify-center"
            onClick={openAircraftModal}
          >
            {t('admin.aircrafts.add')}
          </button>
        </div>
      </aside>

      <Modal
        open={aircraftModalOpen}
        title={t('admin.aircrafts.addTitle')}
        onClose={closeAircraftModal}
        closeLabel={t('admin.classes.cancel')}
        footer={
          <>
            <button
              type="button"
              className="btn btn-ghost"
              onClick={closeAircraftModal}
              disabled={aircraftSaving}
            >
              {t('admin.classes.cancel')}
            </button>
            <button
              type="button"
              className="btn btn-primary"
              onClick={() => void saveAircraft()}
              disabled={aircraftSaving}
            >
              {t('admin.aircrafts.addTitle')}
            </button>
          </>
        }
      >
        <div>
          <label className="micro block mb-1">{t('admin.aircrafts.fieldModel')}</label>
          <input
            autoFocus
            className="inp inp-mono"
            value={aircraftDraft.model}
            onChange={e => setAircraftDraft(p => ({ ...p, model: e.target.value }))}
            placeholder="DJI Mavic 3"
            aria-label={t('admin.aircrafts.fieldModel')}
          />
        </div>

        <div>
          <label className="micro block mb-1">{t('admin.aircrafts.fieldType')}</label>
          <div className="seg" role="group" aria-label={t('admin.aircrafts.fieldType')}>
            {AIRCRAFT_TYPES.map(typ => (
              <button
                key={typ}
                type="button"
                onClick={() => setAircraftDraft(p => ({ ...p, type: typ }))}
                className={`seg-btn${aircraftDraft.type === typ ? ' active' : ''}`}
                aria-pressed={aircraftDraft.type === typ}
              >
                {t(`admin.aircrafts.${TYPE_LEGEND_KEY[typ]}`)}
              </button>
            ))}
          </div>
        </div>

        <div className="grid grid-cols-2 gap-3">
          <div>
            <label className="micro block mb-1">{t('admin.aircrafts.fieldResolution')}</label>
            <select
              className="inp inp-mono"
              value={aircraftDraft.resolution}
              onChange={e => setAircraftDraft(p => ({ ...p, resolution: e.target.value }))}
              aria-label={t('admin.aircrafts.fieldResolution')}
            >
              {RESOLUTIONS.map(r => (
                <option key={r} value={r}>{r}</option>
              ))}
            </select>
          </div>
          <div>
            <label className="micro block mb-1">{t('admin.aircrafts.fieldMaxMinutes')}</label>
            <input
              type="number"
              className="inp inp-mono"
              value={aircraftDraft.maxMinutes}
              onChange={e => setAircraftDraft(p => ({ ...p, maxMinutes: Number(e.target.value) }))}
              style={{ textAlign: 'right' }}
              aria-label={t('admin.aircrafts.fieldMaxMinutes')}
            />
          </div>
        </div>

        <label className="checkbox-row">
          <input
            type="checkbox"
            className="checkbox"
            checked={aircraftDraft.isDefault}
            onChange={e => setAircraftDraft(p => ({ ...p, isDefault: e.target.checked }))}
          />
          <span>{t('admin.aircrafts.fieldDefault')}</span>
        </label>

        {aircraftError && (
          <div role="alert" style={{ color: 'var(--accent-red)', fontSize: 11 }}>
            {t(`admin.aircrafts.${aircraftError}`)}
          </div>
        )}
      </Modal>
    </main>
  )
}
