/**
 * ABGABE-STATUS: Reservierungs-/Abgabe-Status-Verwaltung.
 * Liste der (vor allem abzugebenden) Tiere mit Status verfügbar → reserviert → abgegeben,
 * inkl. Reservierung für einen Kontakt, Termin, Preis und Notiz. Tier- und Kontakt-Bezüge
 * sind als Links hinterlegt. Dieser Status ist die Vormerkung VOR dem rechtlichen Vertrag
 * (Verträge-Seite) — er ersetzt ihn nicht.
 */
import { useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import { de } from '../strings/de'
import { listGerbils } from '../api/gerbils'
import { listContactsPaged } from '../api/contacts'
import {
  createReservation,
  deleteReservation,
  listReservations,
  updateReservation,
  type ReservationStatus,
  type SaleReservation,
} from '../api/reservations'
import { useApi, useMutation } from '../hooks/useApi'
import type { Contact, Gerbil } from '../api/types'
import './reservierungen.css'

const STATUSES: ReservationStatus[] = ['verfuegbar', 'reserviert', 'abgegeben']
type FilterKey = 'all' | ReservationStatus

/** ISO-Datetime → "TT.MM.JJJJ"; leer/ungültig → Strich. */
function dateOnly(iso: string | null): string {
  if (!iso) return de.pages.reservierungen.fields.none
  const date = new Date(iso)
  if (Number.isNaN(date.getTime())) return iso
  return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })
}

/** ISO-Datetime → Wert für <input type="date"> ("YYYY-MM-DD"). */
function toDateInput(iso: string | null): string {
  if (!iso) return ''
  const date = new Date(iso)
  if (Number.isNaN(date.getTime())) return ''
  return date.toISOString().slice(0, 10)
}

/** <input type="date">-Wert ("YYYY-MM-DD") → ISO-Datetime oder null. */
function fromDateInput(value: string): string | null {
  if (!value) return null
  return new Date(`${value}T00:00:00Z`).toISOString()
}

interface FormState {
  id: string | null
  gerbilId: string
  status: ReservationStatus
  reservedForContactId: string
  appointmentDate: string
  price: string
  note: string
  handedOverDate: string
}

const emptyForm: FormState = {
  id: null,
  gerbilId: '',
  status: 'reserviert',
  reservedForContactId: '',
  appointmentDate: '',
  price: '',
  note: '',
  handedOverDate: '',
}

export default function ReservierungenPage() {
  const t = de.pages.reservierungen

  const reservations = useApi(() => listReservations(), [])
  const gerbils = useApi(
    () => listGerbils({ orderBy: 'name', page: 1, pageSize: 1000 }),
    [],
  )
  const contacts = useApi(
    () => listContactsPaged({ orderBy: 'name', page: 1, pageSize: 1000 }),
    [],
  )

  const createM = useMutation(createReservation)
  const updateM = useMutation(updateReservation)
  const deleteM = useMutation(deleteReservation)

  const [filter, setFilter] = useState<FilterKey>('all')
  const [form, setForm] = useState<FormState | null>(null)
  const [formError, setFormError] = useState<string | null>(null)

  const gerbilById = useMemo(
    () => new Map((gerbils.data?.items ?? []).map((g: Gerbil) => [g.id, g])),
    [gerbils.data],
  )
  const contactById = useMemo(
    () => new Map((contacts.data?.items ?? []).map((c: Contact) => [c.id, c])),
    [contacts.data],
  )

  const rows = useMemo(() => {
    const all = reservations.data ?? []
    return filter === 'all' ? all : all.filter((r) => r.status === filter)
  }, [reservations.data, filter])

  const counts = useMemo(() => {
    const all = reservations.data ?? []
    const c: Record<FilterKey, number> = { all: all.length, verfuegbar: 0, reserviert: 0, abgegeben: 0 }
    for (const r of all) c[r.status] += 1
    return c
  }, [reservations.data])

  function gerbilName(r: SaleReservation): string {
    return gerbilById.get(r.gerbilId)?.name ?? r.gerbilName ?? t.fields.none
  }
  function contactName(r: SaleReservation): string {
    if (!r.reservedForContactId) return t.fields.none
    return contactById.get(r.reservedForContactId)?.name ?? r.contactName ?? t.fields.none
  }

  function openCreate() {
    setFormError(null)
    setForm({ ...emptyForm })
  }
  function openEdit(r: SaleReservation) {
    setFormError(null)
    setForm({
      id: r.id,
      gerbilId: r.gerbilId,
      status: r.status,
      reservedForContactId: r.reservedForContactId ?? '',
      appointmentDate: toDateInput(r.appointmentDate),
      price: r.price != null ? String(r.price) : '',
      note: r.note ?? '',
      handedOverDate: toDateInput(r.handedOverDate),
    })
  }

  async function saveForm() {
    if (!form) return
    if (!form.gerbilId) {
      setFormError(t.form.chooseAnimal)
      return
    }
    const g = gerbilById.get(form.gerbilId)
    const c = form.reservedForContactId ? contactById.get(form.reservedForContactId) : undefined
    const priceNum = form.price.trim() === '' ? null : Number(form.price.replace(',', '.'))
    const payload = {
      status: form.status,
      reservedForContactId: form.reservedForContactId || null,
      contactName: c?.name ?? null,
      appointmentDate: fromDateInput(form.appointmentDate),
      price: priceNum != null && !Number.isNaN(priceNum) ? priceNum : null,
      note: form.note.trim() || null,
      handedOverDate: fromDateInput(form.handedOverDate),
    }
    const result = form.id
      ? await updateM.run(form.id, payload)
      : await createM.run({ gerbilId: form.gerbilId, gerbilName: g?.name ?? null, ...payload })
    if (result.ok) {
      setForm(null)
      reservations.reload()
    } else {
      setFormError(t.form.saveError)
    }
  }

  async function quickStatus(r: SaleReservation, status: ReservationStatus) {
    const patch: Parameters<typeof updateReservation>[1] = { status }
    if (status === 'abgegeben' && !r.handedOverDate) patch.handedOverDate = new Date().toISOString()
    const result = await updateM.run(r.id, patch)
    if (result.ok) reservations.reload()
  }

  async function remove(r: SaleReservation) {
    if (!window.confirm(t.actions.confirmDelete)) return
    const result = await deleteM.run(r.id)
    if (result.ok) reservations.reload()
  }

  if (reservations.loading) return <p className="muted">{de.common.loading}</p>
  if (reservations.error) return <p className="error">{t.loadError}</p>

  return (
    <section className="page reservierungen">
      <h2>{t.title}</h2>
      <p className="muted">{t.subtitle}</p>
      <p className="muted reservierungen__hint">{t.contractHint}</p>

      <div className="reservierungen__toolbar">
        <div className="reservierungen__filters" role="group" aria-label={t.fields.status}>
          {(['all', ...STATUSES] as FilterKey[]).map((key) => (
            <button
              key={key}
              type="button"
              className={
                filter === key
                  ? 'reservierungen-filter reservierungen-filter--active'
                  : 'reservierungen-filter'
              }
              onClick={() => setFilter(key)}
            >
              {t.filters[key]}
              <span className="reservierungen-filter__count">{counts[key]}</span>
            </button>
          ))}
        </div>
        <button type="button" className="btn btn--primary" onClick={openCreate}>
          {t.newButton}
        </button>
      </div>

      {form && (
        <ReservationForm
          t={t}
          form={form}
          setForm={setForm}
          gerbils={gerbils.data?.items ?? []}
          contacts={contacts.data?.items ?? []}
          error={formError}
          pending={createM.pending || updateM.pending}
          onSave={saveForm}
          onCancel={() => setForm(null)}
        />
      )}

      {rows.length === 0 ? (
        <p className="muted">{t.empty}</p>
      ) : (
        <ul className="reservierungen__list">
          {rows.map((r) => (
            <li key={r.id} className={`reservation-card reservation-card--${r.status}`}>
              <div className="reservation-card__head">
                <Link to={`/rennmaeuse/${r.gerbilId}`} className="reservation-card__animal">
                  {gerbilName(r)}
                </Link>
                <span className={`reservation-badge reservation-badge--${r.status}`}>
                  {t.status[r.status]}
                </span>
              </div>
              <dl className="reservation-card__meta">
                <div>
                  <dt>{t.fields.reservedFor}</dt>
                  <dd>
                    {r.reservedForContactId ? (
                      <Link to={`/kontakte/${r.reservedForContactId}`}>{contactName(r)}</Link>
                    ) : (
                      contactName(r)
                    )}
                  </dd>
                </div>
                <div>
                  <dt>{t.fields.appointment}</dt>
                  <dd>{dateOnly(r.appointmentDate)}</dd>
                </div>
                <div>
                  <dt>{t.fields.price}</dt>
                  <dd>{r.price != null ? `${r.price.toFixed(2)} €` : t.fields.none}</dd>
                </div>
                <div>
                  <dt>{t.fields.handedOver}</dt>
                  <dd>{dateOnly(r.handedOverDate)}</dd>
                </div>
              </dl>
              {r.note && <p className="reservation-card__note">{r.note}</p>}
              <div className="reservation-card__actions">
                {r.status !== 'reserviert' && (
                  <button type="button" className="btn" onClick={() => quickStatus(r, 'reserviert')}>
                    {t.actions.markReserved}
                  </button>
                )}
                {r.status !== 'abgegeben' && (
                  <button type="button" className="btn" onClick={() => quickStatus(r, 'abgegeben')}>
                    {t.actions.markHandedOver}
                  </button>
                )}
                {r.status !== 'verfuegbar' && (
                  <button type="button" className="btn" onClick={() => quickStatus(r, 'verfuegbar')}>
                    {t.actions.markAvailable}
                  </button>
                )}
                <button type="button" className="btn" onClick={() => openEdit(r)}>
                  {t.actions.edit}
                </button>
                <button type="button" className="btn btn--danger" onClick={() => remove(r)}>
                  {t.actions.delete}
                </button>
              </div>
            </li>
          ))}
        </ul>
      )}
    </section>
  )
}

interface FormProps {
  t: typeof de.pages.reservierungen
  form: FormState
  setForm: (f: FormState) => void
  gerbils: Gerbil[]
  contacts: Contact[]
  error: string | null
  pending: boolean
  onSave: () => void
  onCancel: () => void
}

function ReservationForm({ t, form, setForm, gerbils, contacts, error, pending, onSave, onCancel }: FormProps) {
  const isEdit = form.id != null
  return (
    <form
      className="reservation-form"
      onSubmit={(e) => {
        e.preventDefault()
        onSave()
      }}
    >
      <h3>{isEdit ? t.form.editTitle : t.form.addTitle}</h3>

      <label>
        {t.form.animal}
        <select
          value={form.gerbilId}
          disabled={isEdit}
          onChange={(e) => setForm({ ...form, gerbilId: e.target.value })}
        >
          <option value="">{t.form.animalPlaceholder}</option>
          {gerbils.map((g) => (
            <option key={g.id} value={g.id}>
              {g.name}
            </option>
          ))}
        </select>
      </label>

      <label>
        {t.form.status}
        <select
          value={form.status}
          onChange={(e) => setForm({ ...form, status: e.target.value as ReservationStatus })}
        >
          {STATUSES.map((s) => (
            <option key={s} value={s}>
              {t.status[s]}
            </option>
          ))}
        </select>
      </label>

      <label>
        {t.form.reservedFor}
        <select
          value={form.reservedForContactId}
          onChange={(e) => setForm({ ...form, reservedForContactId: e.target.value })}
        >
          <option value="">{t.form.contactNone}</option>
          {contacts.map((c) => (
            <option key={c.id} value={c.id}>
              {c.name}
            </option>
          ))}
        </select>
      </label>

      <label>
        {t.form.appointment}
        <input
          type="date"
          value={form.appointmentDate}
          onChange={(e) => setForm({ ...form, appointmentDate: e.target.value })}
        />
      </label>

      <label>
        {t.form.price}
        <input
          type="number"
          step="0.01"
          min="0"
          value={form.price}
          onChange={(e) => setForm({ ...form, price: e.target.value })}
        />
      </label>

      <label>
        {t.form.handedOver}
        <input
          type="date"
          value={form.handedOverDate}
          onChange={(e) => setForm({ ...form, handedOverDate: e.target.value })}
        />
      </label>

      <label className="reservation-form__note">
        {t.form.note}
        <textarea
          value={form.note}
          rows={2}
          onChange={(e) => setForm({ ...form, note: e.target.value })}
        />
      </label>

      {error && <p className="error">{error}</p>}

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