/**
 * WAITLIST (RennmausPro nachfrage_tb): Warteliste/Nachfrage.
 *
 * Interessenten mit Wunschkriterien (Farbschlag, Geschlecht), Anfragedatum,
 * Status (offen | erfuellt | storniert) und Notiz. Anlegen/Bearbeiten über ein
 * Inline-Formular; Status direkt je Eintrag umstellbar; Filter „nur offene".
 * Wunsch-Farbschlag aus dem bestehenden Farbkatalog wählbar; Kontakt-Bezug als Link.
 *
 * Entkoppelt vom Kontakt (lose contactId ohne FK) → überlebt den Import-Re-Ingest.
 */
import { useMemo, useState, type FormEvent } from 'react'
import { Link } from 'react-router-dom'
import { de } from '../strings/de'
import { useApi, useMutation } from '../hooks/useApi'
import { useToast } from '../components/toast'
import { listContacts, listColorVarieties } from '../api/lookups'
import {
  listWaitingList,
  createWaitingListEntry,
  updateWaitingListEntry,
  deleteWaitingListEntry,
  WAITING_LIST_STATUSES,
  type WaitingListEntry,
  type WaitingListInput,
  type WaitingListStatus,
} from '../api/waitingList'

interface FormState {
  contactId: string
  contactName: string
  wishColor: string
  wishGender: '' | 'male' | 'female'
  requestedAt: string
  status: WaitingListStatus
  note: string
}

const EMPTY: FormState = {
  contactId: '',
  contactName: '',
  wishColor: '',
  wishGender: '',
  requestedAt: '',
  status: 'offen',
  note: '',
}

/** "" -> null, sonst der Wert. */
const nn = (s: string): string | null => (s.trim() === '' ? null : s)

function isStatus(value: string): value is WaitingListStatus {
  return (WAITING_LIST_STATUSES as string[]).includes(value)
}

export default function WartelistePage() {
  const t = de.pages.warteliste
  const toast = useToast()

  const entries = useApi(() => listWaitingList(), [])
  const contacts = useApi(() => listContacts(), [])
  const colors = useApi(() => listColorVarieties(), [])

  const [onlyOpen, setOnlyOpen] = useState(false)
  const [editingId, setEditingId] = useState<string | null>(null) // null = nicht im Formular, '' = neu
  const [form, setForm] = useState<FormState>(EMPTY)

  const set = <K extends keyof FormState>(key: K, value: FormState[K]) =>
    setForm((f) => ({ ...f, [key]: value }))

  const saveMutation = useMutation((args: { id: string | null; body: WaitingListInput }) =>
    args.id ? updateWaitingListEntry(args.id, args.body) : createWaitingListEntry(args.body),
  )
  const deleteMutation = useMutation((id: string) => deleteWaitingListEntry(id))

  const contactNameById = useMemo(() => {
    const map = new Map<string, string>()
    for (const c of contacts.data ?? []) map.set(c.id, c.name)
    return map
  }, [contacts.data])

  const visible = useMemo(() => {
    const rows = entries.data ?? []
    return onlyOpen ? rows.filter((e) => e.status === 'offen') : rows
  }, [entries.data, onlyOpen])

  function openNew() {
    setForm(EMPTY)
    setEditingId('')
  }

  function openEdit(e: WaitingListEntry) {
    setForm({
      contactId: e.contactId ?? '',
      contactName: e.contactName ?? '',
      wishColor: e.wishColor ?? '',
      wishGender: e.wishGender === 'male' || e.wishGender === 'female' ? e.wishGender : '',
      requestedAt: e.requestedAt ? e.requestedAt.slice(0, 10) : '',
      status: isStatus(e.status) ? e.status : 'offen',
      note: e.note ?? '',
    })
    setEditingId(e.id)
  }

  function closeForm() {
    setEditingId(null)
  }

  function buildBody(): WaitingListInput {
    return {
      contactId: nn(form.contactId),
      contactName: nn(form.contactName),
      wishColor: nn(form.wishColor),
      wishGender: form.wishGender === '' ? null : form.wishGender,
      requestedAt: form.requestedAt ? new Date(`${form.requestedAt}T00:00:00Z`).toISOString() : null,
      status: form.status,
      note: nn(form.note),
    }
  }

  async function onSubmit(ev: FormEvent) {
    ev.preventDefault()
    if (!form.contactId && form.contactName.trim() === '') {
      toast.error(t.validationName)
      return
    }
    const result = await saveMutation.run({ id: editingId || null, body: buildBody() })
    if (result.ok) {
      toast.success(de.common.saved)
      closeForm()
      entries.reload()
    } else {
      toast.error(result.error)
    }
  }

  /** Schnell-Statuswechsel direkt in der Liste (sendet den vollständigen Eintrag mit). */
  async function changeStatus(entry: WaitingListEntry, status: WaitingListStatus) {
    const body: WaitingListInput = {
      contactId: entry.contactId,
      contactName: entry.contactName,
      wishColor: entry.wishColor,
      wishGender: entry.wishGender,
      requestedAt: entry.requestedAt,
      status,
      note: entry.note,
    }
    const result = await saveMutation.run({ id: entry.id, body })
    if (result.ok) {
      toast.success(de.common.saved)
      entries.reload()
    } else {
      toast.error(result.error)
    }
  }

  async function onDelete(entry: WaitingListEntry) {
    if (!window.confirm(t.deleteConfirm)) return
    const result = await deleteMutation.run(entry.id)
    if (result.ok) {
      toast.success(de.common.deleted)
      entries.reload()
    } else {
      toast.error(result.error)
    }
  }

  const statusLabel = (status: string): string =>
    isStatus(status) ? t.status[status] : status

  const genderLabel = (g: string | null): string =>
    g === 'male' ? t.wishGender.male : g === 'female' ? t.wishGender.female : t.wishGender.any

  return (
    <section className="page">
      <header className="page-head">
        <div>
          <h2>{t.title}</h2>
          <p className="muted">{t.subtitle}</p>
          {!entries.loading && !entries.error && (
            <p className="muted">
              {visible.length} {t.countLabel}
            </p>
          )}
        </div>
        <button type="button" className="btn btn--primary" onClick={openNew}>
          + {t.newButton}
        </button>
      </header>

      <div className="filters">
        <label className="field field--check">
          <span>{t.onlyOpen}</span>
          <input
            type="checkbox"
            checked={onlyOpen}
            onChange={(ev) => setOnlyOpen(ev.target.checked)}
            aria-label={t.onlyOpen}
          />
        </label>
      </div>

      {editingId !== null && (
        <form className="form" onSubmit={onSubmit} noValidate aria-label={editingId ? t.formTitleEdit : t.formTitleNew}>
          <h3>{editingId ? t.formTitleEdit : t.formTitleNew}</h3>

          <label className="field">
            <span>{t.fields.contact}</span>
            <select
              className="input"
              value={form.contactId}
              onChange={(ev) => set('contactId', ev.target.value)}
            >
              <option value="">{t.fields.contactNone}</option>
              {(contacts.data ?? []).map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </select>
          </label>

          <label className="field">
            <span>{t.fields.contactName}</span>
            <input
              className="input"
              value={form.contactName}
              onChange={(ev) => set('contactName', ev.target.value)}
            />
          </label>

          <label className="field">
            <span>{t.fields.wishColor}</span>
            <select
              className="input"
              value={form.wishColor}
              onChange={(ev) => set('wishColor', ev.target.value)}
            >
              <option value="">{t.fields.wishColorAny}</option>
              {(colors.data ?? []).map((c) => (
                <option key={c.id} value={c.name}>
                  {c.name}
                </option>
              ))}
            </select>
          </label>

          <label className="field">
            <span>{t.fields.wishGender}</span>
            <select
              className="input"
              value={form.wishGender}
              onChange={(ev) => set('wishGender', ev.target.value as FormState['wishGender'])}
            >
              <option value="">{t.wishGender.any}</option>
              <option value="female">{t.wishGender.female}</option>
              <option value="male">{t.wishGender.male}</option>
            </select>
          </label>

          <label className="field">
            <span>{t.fields.requestedAt}</span>
            <input
              className="input"
              type="date"
              value={form.requestedAt}
              onChange={(ev) => set('requestedAt', ev.target.value)}
            />
          </label>

          <label className="field">
            <span>{t.fields.status}</span>
            <select
              className="input"
              value={form.status}
              onChange={(ev) => set('status', ev.target.value as WaitingListStatus)}
            >
              {WAITING_LIST_STATUSES.map((s) => (
                <option key={s} value={s}>
                  {t.status[s]}
                </option>
              ))}
            </select>
          </label>

          <label className="field">
            <span>{t.fields.note}</span>
            <textarea value={form.note} onChange={(ev) => set('note', ev.target.value)} />
          </label>

          {saveMutation.error && <div className="alert alert--error">{saveMutation.error}</div>}

          <div className="form-actions">
            <button type="submit" className="btn btn--primary" disabled={saveMutation.pending}>
              {t.save}
            </button>
            <button type="button" className="btn" onClick={closeForm}>
              {t.cancel}
            </button>
          </div>
        </form>
      )}

      {entries.loading && <p className="muted">{de.common.loading}</p>}
      {entries.error && (
        <div className="alert alert--error">
          <span>{t.loadError}</span>
          <button type="button" className="btn" onClick={entries.reload}>
            {de.common.retry}
          </button>
        </div>
      )}

      {!entries.loading && !entries.error && visible.length === 0 && (
        <p className="muted">{onlyOpen ? t.emptyOpen : t.empty}</p>
      )}

      {visible.length > 0 && (
        <ul className="card-list">
          {visible.map((e) => {
            const contactName = e.contactId ? contactNameById.get(e.contactId) : null
            return (
              <li key={e.id}>
                <div className="gerbil-card" style={{ display: 'block' }}>
                  <div className="gerbil-card__name">
                    {e.contactId && contactName ? (
                      <Link to={`/kontakte/${e.contactId}`}>{contactName}</Link>
                    ) : (
                      (e.contactName ?? t.noContactLink)
                    )}
                    {' — '}
                    <span className={`badge badge--${e.status}`}>{statusLabel(e.status)}</span>
                  </div>
                  <div className="gerbil-card__meta">
                    {(e.wishColor ?? t.fields.wishColorAny)} · {genderLabel(e.wishGender)}
                    {e.requestedAt ? ` · ${e.requestedAt.slice(0, 10)}` : ''}
                  </div>
                  {e.note && <p className="muted">{e.note}</p>}
                  <div className="form-actions">
                    <label className="field">
                      <span>{t.fields.status}</span>
                      <select
                        className="input"
                        value={isStatus(e.status) ? e.status : 'offen'}
                        onChange={(ev) => changeStatus(e, ev.target.value as WaitingListStatus)}
                        aria-label={`${t.fields.status} ${e.contactName ?? contactName ?? ''}`.trim()}
                        disabled={saveMutation.pending}
                      >
                        {WAITING_LIST_STATUSES.map((s) => (
                          <option key={s} value={s}>
                            {t.status[s]}
                          </option>
                        ))}
                      </select>
                    </label>
                    <button type="button" className="btn" onClick={() => openEdit(e)}>
                      {t.edit}
                    </button>
                    <button
                      type="button"
                      className="btn"
                      onClick={() => onDelete(e)}
                      disabled={deleteMutation.pending}
                    >
                      {t.delete}
                    </button>
                  </div>
                </div>
              </li>
            )
          })}
        </ul>
      )}
    </section>
  )
}
