import React, { useCallback, useEffect, useState } from 'react';
import { Plus, Trash2, Edit2, RefreshCcw, ArrowDownToLine, ArrowUpFromLine } from 'lucide-react';
import {
  ListUDPIntegrations, SaveUDPIntegration, DeleteUDPIntegration, ReloadUDPIntegrations,
  GetWsjtHighlight, SetWsjtHighlight, GetWsjtHighlightWorked, SetWsjtHighlightWorked, GetWsjtFollowMode, SetWsjtFollowMode,
  GetWsjtHighlightColours, SetWsjtHighlightColours,
} from '../../wailsjs/go/main/App';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox';
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription,
} from '@/components/ui/dialog';
import {
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import { cn } from '@/lib/utils';
import { useI18n } from '@/lib/i18n';

// Local mirror of the Go struct — we duplicate the type rather than depend
// on the generated Wails model because the inline `as any` casts are
// noisier than just owning the shape here.
type UDPConfig = {
  id: number;
  direction: 'inbound' | 'outbound';
  name: string;
  port: number;
  service_type: 'wsjt' | 'adif' | 'n1mm' | 'remote_call' | 'db_updated' | 'pstrotator_freq' | 'n1mm_radioinfo' | 'wsjt_log' | 'wsjt_relay' | 'custom';
  // Custom rows only.
  trigger?: string;
  template?: string;
  transport?: string;
  url?: string;
  line_end?: string;
  multicast: boolean;
  multicast_group: string;
  destination_ip: string;
  enabled: boolean;
  sort_order: number;
};

// Service-type catalog used by the dropdowns; each entry is restricted to
// inbound or outbound and carries a hint suggesting reasonable defaults
// for the "preset" button.
const SERVICE_TYPES: Array<{
  id: UDPConfig['service_type'];
  direction: UDPConfig['direction'];
  label: string;
  hint: string;
  defaults: Partial<UDPConfig>;
}> = [
  {
    id: 'wsjt',
    direction: 'inbound',
    label: 'udpp.svcWsjtLabel',
    hint: 'udpp.svcWsjtHint',
    defaults: { port: 2237, multicast: true, multicast_group: '224.0.0.1' },
  },
  {
    id: 'adif',
    direction: 'inbound',
    label: 'udpp.svcAdifLabel',
    hint: 'udpp.svcAdifHint',
    defaults: { port: 2333, multicast: false },
  },
  {
    id: 'n1mm',
    direction: 'inbound',
    label: 'udpp.svcN1mmLabel',
    hint: 'udpp.svcN1mmHint',
    defaults: { port: 12060, multicast: false },
  },
  {
    id: 'remote_call',
    direction: 'inbound',
    label: 'udpp.svcRemoteLabel',
    hint: 'udpp.svcRemoteHint',
    defaults: { port: 12090, multicast: false },
  },
  {
    id: 'db_updated',
    direction: 'outbound',
    label: 'udpp.svcDbLabel',
    hint: 'udpp.svcDbHint',
    defaults: { port: 2333, destination_ip: '127.0.0.1' },
  },
  {
    // Announces the QSO on the WSJT-X UDP interface instead of as plain text.
    // Named for the protocol, not for one program: Logger32 is what it was
    // built against, but anything listening on that interface takes it, and a
    // label saying "Logger32" would have every other operator scroll past.
    // 2250 is Logger32's first additional socket — a starting point, not a rule.
    id: 'wsjt_log',
    direction: 'outbound',
    label: 'udpp.svcWsjtLogLabel',
    hint: 'udpp.svcWsjtLogHint',
    defaults: { port: 2250, destination_ip: '127.0.0.1' },
  },
  {
    // Feeds a SECOND application the stream this OpsLog receives. WSJT-X, JTDX
    // and MSHV each send to ONE address, so without a relay the choice is
    // between OpsLog and JTAlert/GridTracker rather than both.
    //
    // 2238 by default: beside the 2237 the sender uses, and free. Pointing it AT
    // 2237 would name an OpsLog listener, which the relay refuses.
    id: 'wsjt_relay',
    direction: 'outbound',
    label: 'udpp.svcWsjtRelayLabel',
    hint: 'udpp.svcWsjtRelayHint',
    defaults: { port: 2238, destination_ip: '127.0.0.1' },
  },
  {
    // The general case: the operator picks the moment and writes the message.
    // Mainly for antenna switches, which are driven by a URL and want the band
    // change — but nothing about it is specific to them.
    id: 'custom',
    direction: 'outbound',
    label: 'udpp.svcCustomLabel',
    hint: 'udpp.svcCustomHint',
    defaults: { port: 12000, destination_ip: '127.0.0.1' },
  },
  {
    id: 'pstrotator_freq',
    direction: 'outbound',
    label: 'udpp.svcPstLabel',
    hint: 'udpp.svcPstHint',
    defaults: { port: 12040, destination_ip: '127.0.0.1' },
  },
  {
    id: 'n1mm_radioinfo',
    direction: 'outbound',
    label: 'udpp.svcN1mmRadioLabel',
    hint: 'udpp.svcN1mmRadioHint',
    defaults: { port: 12060, destination_ip: '127.0.0.1' },
  },
];

// The fields each trigger carries, and NOTHING else.
//
// This list is the point of the whole feature. A rotation has no frequency, a
// lookup has no report — and a placeholder the trigger cannot fill renders as
// nothing at all. Without seeing what is available, an operator writes {freq}
// on a band change, gets an empty string, and has no way to learn why. So the
// panel prints them under the box, for the trigger actually selected.
const TRIGGER_FIELDS: Record<string, string[]> = {
  qso_logged: ['call', 'band', 'band_m', 'mode', 'freq_hz', 'freq_mhz', 'grid', 'name', 'country', 'dxcc', 'rst_s', 'rst_r', 'comment', 'date', 'time'],
  rotator_goto: ['az', 'el', 'path'],
  lookup_done: ['call', 'name', 'grid', 'country', 'qth', 'state', 'dxcc'],
  band_change: ['band', 'band_m', 'freq_hz', 'freq_mhz', 'mode'],
};

const TRIGGERS = [
  { id: 'band_change', label: 'udpp.trgBand' },
  { id: 'qso_logged', label: 'udpp.trgQso' },
  { id: 'rotator_goto', label: 'udpp.trgRotator' },
  { id: 'lookup_done', label: 'udpp.trgLookup' },
];

type Props = { onError: (msg: string) => void };

export function UDPIntegrationsPanel({ onError }: Props) {
  const [highlightOn, setHighlightOn] = useState(false);
  const [hlWorked, setHlWorked] = useState(false);
  // The palette, as chosen. Background per verdict; the text colour is the
  // backend’s business (see colourFor).
  const [colours, setColours] = useState({ watchlist: '#F472B6', new_dxcc: '#16823C', new_band: '#E27A18', worked: '#4B5563' });
  const [followMode, setFollowMode] = useState(true);
  useEffect(() => {
    GetWsjtHighlight().then((v) => setHighlightOn(!!v)).catch(() => {});
    GetWsjtHighlightColours().then((c: any) => { if (c) setColours(c); }).catch(() => {});
    GetWsjtHighlightWorked().then((v) => setHlWorked(!!v)).catch(() => {});
    GetWsjtHighlightWorked().then((v) => setHlWorked(!!v)).catch(() => {});
    GetWsjtFollowMode().then((v) => setFollowMode(!!v)).catch(() => {});
  }, []);
  const { t } = useI18n();
  const [items, setItems] = useState<UDPConfig[]>([]);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState<UDPConfig | null>(null);

  const reload = useCallback(async () => {
    try {
      const list = await ListUDPIntegrations();
      setItems(((list ?? []) as any[]) as UDPConfig[]);
    } catch (e: any) { onError(String(e?.message ?? e)); }
    finally { setLoading(false); }
  }, [onError]);

  useEffect(() => { void reload(); }, [reload]);

  function addNew(direction: UDPConfig['direction']) {
    const preset = SERVICE_TYPES.find((s) => s.direction === direction)!;
    setEditing({
      id: 0,
      direction,
      name: '',
      port: preset.defaults.port ?? 2237,
      service_type: preset.id,
      multicast: !!preset.defaults.multicast,
      multicast_group: preset.defaults.multicast_group ?? '',
      destination_ip: preset.defaults.destination_ip ?? '',
      enabled: true,
      sort_order: items.filter((i) => i.direction === direction).length,
      trigger: '', template: '', transport: 'udp', url: '', line_end: '',
    });
  }

  async function save(cfg: UDPConfig) {
    try {
      const saved = await SaveUDPIntegration(cfg as any) as UDPConfig;
      setItems((prev) => {
        if (cfg.id === 0) return [...prev, saved];
        return prev.map((x) => x.id === saved.id ? saved : x);
      });
      setEditing(null);
    } catch (e: any) { onError(String(e?.message ?? e)); }
  }

  async function remove(id: number) {
    if (!confirm(t('udpp.deleteConfirm'))) return;
    try {
      await DeleteUDPIntegration(id);
      setItems((prev) => prev.filter((x) => x.id !== id));
    } catch (e: any) { onError(String(e?.message ?? e)); }
  }

  async function toggleEnabled(cfg: UDPConfig) {
    await save({ ...cfg, enabled: !cfg.enabled });
  }

  async function reloadServers() {
    try {
      const errs = await ReloadUDPIntegrations();
      if (errs && (errs as string[]).length > 0) {
        onError((errs as string[]).join(' • '));
      }
    } catch (e: any) { onError(String(e?.message ?? e)); }
  }

  if (loading) return <div className="text-xs text-muted-foreground italic">{t('udpp.loading')}</div>;

  const inbound = items.filter((i) => i.direction === 'inbound');
  const outbound = items.filter((i) => i.direction === 'outbound');

  return (
    <div className="space-y-4">
      {/* Log-aware colours in WSJT-X / JTDX's own window — lives HERE because
          this panel is where the WSJT-X link is configured. */}
      <label className="flex items-start gap-2 text-sm cursor-pointer max-w-2xl">
        <Checkbox checked={highlightOn}
          onCheckedChange={(c) => { setHighlightOn(!!c); void SetWsjtHighlight(!!c); }} />
        <span>
          {t('udpp.highlight')}
          <span className="block text-[11px] text-muted-foreground">{t('udpp.highlightHint')}</span>
        </span>
      </label>
      {/* The palette, nested under the switch for the same reason as the box
          below it. One colour per verdict, and the background only: the text
          colour is worked out from it, so a chosen colour cannot come back
          unreadable in the decoder's window. */}
      {highlightOn && (
        <div className="pl-6 max-w-2xl space-y-1.5">
          <div className="text-[11px] text-muted-foreground">{t('udpp.hlColours')}</div>
          <div className="flex flex-wrap gap-3">
            {([
              ['watchlist', t('udpp.hlWatchlist')],
              ['new_dxcc', t('udpp.hlNewDxcc')],
              ['new_band', t('udpp.hlNewBand')],
              ['worked', t('udpp.hlWorkedC')],
            ] as const).map(([k, label]) => (
              <label key={k} className="inline-flex items-center gap-1.5 text-xs">
                <input
                  type="color"
                  value={(colours as any)[k] || '#000000'}
                  onChange={(e) => {
                    const next = { ...colours, [k]: e.target.value.toUpperCase() };
                    setColours(next);
                    void SetWsjtHighlightColours(next as any);
                  }}
                  className="h-6 w-8 rounded border border-border bg-background p-0.5 cursor-pointer"
                />
                {label}
              </label>
            ))}
            <button type="button" className="text-xs text-muted-foreground underline hover:text-foreground"
              onClick={() => {
                const def = { watchlist: '#F472B6', new_dxcc: '#16823C', new_band: '#E27A18', worked: '#4B5563' };
                setColours(def as any);
                void SetWsjtHighlightColours(def as any);
              }}>
              {t('udpp.hlReset')}
            </button>
          </div>
        </div>
      )}
      {/* Nested under the switch above: the same feature, and meaningless
          while that one is off. */}
      {highlightOn && (
        <label className="flex items-start gap-2 text-sm cursor-pointer max-w-2xl pl-6">
          <Checkbox checked={hlWorked}
            onCheckedChange={(c) => { setHlWorked(!!c); void SetWsjtHighlightWorked(!!c); }} />
          <span>{t('udpp.hlWorked')}</span>
        </label>
      )}
      <label className="flex items-start gap-2 text-sm cursor-pointer max-w-2xl">
        <Checkbox checked={followMode}
          onCheckedChange={(c) => { setFollowMode(!!c); void SetWsjtFollowMode(!!c); }} />
        <span>
          {t('udpp.followMode')}
          <span className="block text-[11px] text-muted-foreground">{t('udpp.followModeHint')}</span>
        </span>
      </label>
      <Section
        title={t('udpp.inboundTitle')}
        icon={<ArrowDownToLine className="size-4" />}
        items={inbound}
        onAdd={() => addNew('inbound')}
        onEdit={(c) => setEditing(c)}
        onDelete={remove}
        onToggle={toggleEnabled}
      />
      <Section
        title={t('udpp.outboundTitle')}
        icon={<ArrowUpFromLine className="size-4" />}
        items={outbound}
        onAdd={() => addNew('outbound')}
        onEdit={(c) => setEditing(c)}
        onDelete={remove}
        onToggle={toggleEnabled}
      />

      <div className="border-t border-border/60 pt-3 flex items-center gap-3">
        <Button size="sm" variant="outline" onClick={reloadServers}>
          <RefreshCcw className="size-3.5" /> {t('udpp.reloadAll')}
        </Button>
        <span className="text-[11px] text-muted-foreground">
          {t('udpp.reloadHint')}
        </span>
      </div>

      {editing && (
        <EditDialog
          cfg={editing}
          onCancel={() => setEditing(null)}
          onSave={save}
        />
      )}
    </div>
  );
}

// ── Section listing ────────────────────────────────────────────────────

function Section({
  title, icon, items, onAdd, onEdit, onDelete, onToggle,
}: {
  title: string;
  icon: React.ReactNode;
  items: UDPConfig[];
  onAdd: () => void;
  onEdit: (c: UDPConfig) => void;
  onDelete: (id: number) => void;
  onToggle: (c: UDPConfig) => void;
}) {
  const { t } = useI18n();
  return (
    <div className="rounded-md border border-border bg-card">
      <div className="flex items-center gap-2 px-3 py-2 border-b border-border/60 bg-muted/30">
        {icon}
        <span className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">{title}</span>
        <div className="flex-1" />
        <Button size="sm" variant="outline" className="h-7 text-xs" onClick={onAdd}>
          <Plus className="size-3" /> {t('udpp.add')}
        </Button>
      </div>
      {items.length === 0 ? (
        <div className="px-3 py-3 text-xs text-muted-foreground italic">{t('udpp.noConnection')}</div>
      ) : (
        <div className="divide-y divide-border/60">
          {items.map((c) => {
            const svc = SERVICE_TYPES.find((s) => s.id === c.service_type);
            return (
              <div key={c.id} className="flex items-center gap-2 px-3 py-2">
                <Checkbox checked={c.enabled} onCheckedChange={() => onToggle(c)} />
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    <span className="font-semibold text-sm truncate">{c.name || t('udpp.unnamed')}</span>
                    <span className="text-[10px] uppercase tracking-wider text-muted-foreground bg-muted px-1.5 py-0.5 rounded">
                      {svc ? t(svc.label) : c.service_type}
                    </span>
                  </div>
                  <div className="text-[11px] text-muted-foreground font-mono">
                    {c.multicast
                      ? <>multicast <strong>{c.multicast_group || '?'}</strong>:{c.port}</>
                      : c.direction === 'outbound'
                        ? <>→ {c.destination_ip || '?'}:{c.port}</>
                        : <>:{c.port}</>
                    }
                  </div>
                </div>
                <Button size="icon" variant="ghost" className="size-7" onClick={() => onEdit(c)}>
                  <Edit2 className="size-3.5" />
                </Button>
                <Button size="icon" variant="ghost" className="size-7 text-destructive hover:bg-destructive/10" onClick={() => onDelete(c.id)}>
                  <Trash2 className="size-3.5" />
                </Button>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ── Edit dialog ────────────────────────────────────────────────────────

function EditDialog({
  cfg, onCancel, onSave,
}: {
  cfg: UDPConfig;
  onCancel: () => void;
  onSave: (c: UDPConfig) => void;
}) {
  const { t } = useI18n();
  const [draft, setDraft] = useState<UDPConfig>(cfg);
  // Service-type list filtered to this connection's direction.
  const services = SERVICE_TYPES.filter((s) => s.direction === draft.direction);
  const currentService = services.find((s) => s.id === draft.service_type);

  function applyPreset(id: UDPConfig['service_type']) {
    const preset = SERVICE_TYPES.find((s) => s.id === id);
    if (!preset) return;
    setDraft((d) => ({
      ...d,
      service_type: id,
      port: preset.defaults.port ?? d.port,
      multicast: preset.defaults.multicast ?? d.multicast,
      multicast_group: preset.defaults.multicast_group ?? d.multicast_group,
      destination_ip: preset.defaults.destination_ip ?? d.destination_ip,
    }));
  }

  return (
    <Dialog open onOpenChange={(o) => { if (!o) onCancel(); }}>
      <DialogContent className="max-w-xl">
        <DialogHeader>
          <DialogTitle>
            {t('udpp.dialogTitle', {
              action: cfg.id === 0 ? t('udpp.new') : t('udpp.edit'),
              direction: draft.direction === 'inbound' ? t('udpp.directionInbound') : t('udpp.directionOutbound'),
            })}
          </DialogTitle>
          <DialogDescription>
            {currentService ? t(currentService.hint) : ''}
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4 px-5 py-4">
          <div className="space-y-1">
            <Label>{t('udpp.name')}</Label>
            <Input
              autoFocus
              value={draft.name}
              onChange={(e) => setDraft((d) => ({ ...d, name: e.target.value }))}
            />
          </div>

          <div className="space-y-1">
            <Label>{t('udpp.serviceType')}</Label>
            <Select value={draft.service_type} onValueChange={(v) => applyPreset(v as UDPConfig['service_type'])}>
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                {services.map((s) => (
                  <SelectItem key={s.id} value={s.id}>{t(s.label)}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="grid grid-cols-[1fr_auto] gap-2 items-end">
            <div className="space-y-1">
              <Label>{t('udpp.port')}</Label>
              <Input
                type="number"
                min={1} max={65535}
                className="font-mono"
                value={draft.port}
                onChange={(e) => {
                  const n = Number(e.target.value);
                  if (Number.isFinite(n)) setDraft((d) => ({ ...d, port: Math.floor(n) }));
                }}
              />
            </div>
            <label className="flex items-center gap-2 text-sm cursor-pointer pb-2">
              <Checkbox
                checked={draft.multicast}
                onCheckedChange={(c) => setDraft((d) => ({ ...d, multicast: !!c }))}
              />
              <span>{t('udpp.multicast')}</span>
            </label>
          </div>

          {draft.multicast && (
            <div className="space-y-1">
              <Label>{t('udpp.multicastGroup')}</Label>
              <Input
                className="font-mono"
                placeholder="224.0.0.1"
                value={draft.multicast_group}
                onChange={(e) => setDraft((d) => ({ ...d, multicast_group: e.target.value }))}
              />
              <div className="text-[10px] text-muted-foreground">
                {t('udpp.multicastHint')}
              </div>
            </div>
          )}

          {draft.direction === 'outbound' && draft.service_type !== 'custom' && (
            <div className="space-y-1">
              <Label>{t('udpp.destinationIp')}</Label>
              <Input
                className="font-mono"
                placeholder="127.0.0.1"
                value={draft.destination_ip}
                onChange={(e) => setDraft((d) => ({ ...d, destination_ip: e.target.value }))}
              />
            </div>
          )}

          {draft.service_type === 'custom' && (
            <CustomFields draft={draft} setDraft={setDraft} />
          )}

          <label className="flex items-center gap-2 text-sm cursor-pointer">
            <Checkbox
              checked={draft.enabled}
              onCheckedChange={(c) => setDraft((d) => ({ ...d, enabled: !!c }))}
            />
            <span>{t('udpp.enabled')}</span>
          </label>
        </div>

        <DialogFooter>
          <Button variant="ghost" onClick={onCancel}>{t('udpp.cancel')}</Button>
          <Button
            onClick={() => onSave(draft)}
            disabled={!draft.name.trim() || !draft.port}
          >
            {t('udpp.save')}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// silence unused-import for cn — kept for future styling tweaks
void cn;

// CustomFields is the editor for a custom outbound row: what fires it, how it
// leaves, and what it says.
function CustomFields({ draft, setDraft }: {
  draft: UDPConfig;
  setDraft: React.Dispatch<React.SetStateAction<UDPConfig>>;
}) {
  const { t } = useI18n();
  const fields = TRIGGER_FIELDS[draft.trigger ?? ''] ?? [];
  const isURL = draft.transport === 'url';
  return (
    <div className="space-y-4 rounded-md border border-border/60 p-3">
      <div className="grid grid-cols-2 gap-3">
        <div className="space-y-1">
          <Label>{t('udpp.trigger')}</Label>
          <Select value={draft.trigger || 'band_change'} onValueChange={(v) => setDraft((d) => ({ ...d, trigger: v }))}>
            <SelectTrigger><SelectValue /></SelectTrigger>
            <SelectContent>
              {TRIGGERS.map((x) => <SelectItem key={x.id} value={x.id}>{t(x.label)}</SelectItem>)}
            </SelectContent>
          </Select>
        </div>
        <div className="space-y-1">
          <Label>{t('udpp.transport')}</Label>
          <Select value={draft.transport || 'udp'} onValueChange={(v) => setDraft((d) => ({ ...d, transport: v }))}>
            <SelectTrigger><SelectValue /></SelectTrigger>
            <SelectContent>
              <SelectItem value="udp">{t('udpp.transportUdp')}</SelectItem>
              <SelectItem value="url">{t('udpp.transportUrl')}</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </div>

      {/* The one place these two features overlap. A relay board is a STATE per
          band, not an event: Station Control tracks it, reads the boards at
          startup and does not re-switch while the VFO moves inside a band. A
          URL fired on a band change has none of that, and building the mapping
          by hand here is work that is already done there. */}
      {draft.trigger === 'band_change' && isURL && (
        <div className="rounded border border-warning-border bg-warning-muted px-2 py-1.5 text-[11px] text-warning-muted-foreground leading-relaxed">
          {t('udpp.relayInstead')}
        </div>
      )}

      {isURL ? (
        <div className="space-y-1">
          <Label>{t('udpp.url')}</Label>
          <Input
            className="font-mono text-xs"
            placeholder="http://192.168.1.50/antenna?band={band}"
            value={draft.url ?? ''}
            onChange={(e) => setDraft((d) => ({ ...d, url: e.target.value }))}
          />
          <div className="text-[10px] text-muted-foreground">{t('udpp.urlHint')}</div>
        </div>
      ) : (
        <>
          <div className="grid grid-cols-[1fr_auto] gap-2">
            <div className="space-y-1">
              <Label>{t('udpp.destinationIp')}</Label>
              <Input
                className="font-mono"
                placeholder="127.0.0.1"
                value={draft.destination_ip}
                onChange={(e) => setDraft((d) => ({ ...d, destination_ip: e.target.value }))}
              />
            </div>
            <div className="space-y-1">
              <Label>{t('udpp.lineEnd')}</Label>
              <Select value={draft.line_end || 'none'} onValueChange={(v) => setDraft((d) => ({ ...d, line_end: v === 'none' ? '' : v }))}>
                <SelectTrigger className="w-28"><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">{t('udpp.lineEndNone')}</SelectItem>
                  <SelectItem value="lf">LF</SelectItem>
                  <SelectItem value="crlf">CRLF</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>
          <div className="space-y-1">
            <Label>{t('udpp.template')}</Label>
            <textarea
              className="w-full min-h-[64px] rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs"
              placeholder="<AZIMUT>{az}</AZIMUT>"
              value={draft.template ?? ''}
              onChange={(e) => setDraft((d) => ({ ...d, template: e.target.value }))}
            />
          </div>
        </>
      )}

      {/* What this trigger can actually fill in. */}
      <div className="space-y-1">
        <div className="text-[10px] uppercase tracking-wider text-muted-foreground">{t('udpp.fieldsAvailable')}</div>
        <div className="flex flex-wrap gap-1">
          {fields.map((f) => (
            <code key={f} className="rounded bg-muted px-1 py-px text-[10px] text-muted-foreground">{`{${f}}`}</code>
          ))}
        </div>
        <div className="text-[10px] text-muted-foreground">{t('udpp.fieldsHint')}</div>
      </div>
    </div>
  );
}
