import { useState, type FormEvent } from 'react'
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import { de } from '../strings/de'
import { createGerbil, getGerbil, updateGerbil } from '../api/gerbils'
import { listColorVarieties, listContacts, listEnclosures, listLitters } from '../api/lookups'
import { GENDERS, GERBIL_STATUSES, type CreateGerbil, type Gender, type GerbilStatus } from '../api/types'
import { useApi, useMutation } from '../hooks/useApi'
import { genderLabel, statusLabel } from '../format/labels'
import { fromDisplayString } from '../genetics'
import FarbschlagImage from '../components/FarbschlagImage'

interface FormState {
  name: string
  gender: Gender | ''
  status: GerbilStatus
  dateOfBirth: string
  dateOfDeath: string
  causeOfDeath: string
  goHomeDate: string
  colorVarietyId: string
  enclosureId: string
  litterId: string
  originContactId: string
  originBreeder: string
  receiverContactId: string
  genotype: string
  notes: string
  isResident: boolean
  isDeaf: boolean | null
}

const EMPTY: FormState = {
  name: '',
  gender: '',
  status: 'Active',
  dateOfBirth: '',
  dateOfDeath: '',
  causeOfDeath: '',
  goHomeDate: '',
  colorVarietyId: '',
  enclosureId: '',
  litterId: '',
  originContactId: '',
  originBreeder: '',
  receiverContactId: '',
  genotype: '',
  notes: '',
  isResident: true,
  isDeaf: null,
}

function formFromGerbil(g: {
  name: string
  gender: Gender
  status: GerbilStatus
  dateOfBirth: string | null
  dateOfDeath: string | null
  causeOfDeath: string | null
  goHomeDate: string | null
  colorVarietyId: string | null
  enclosureId: string | null
  litterId: string | null
  originContactId: string | null
  originBreeder?: string | null
  receiverContactId: string | null
  genotype: string | null
  notes: string | null
  isResident?: boolean | null
  isDeaf?: boolean | null
}): FormState {
  return {
    name: g.name,
    gender: g.gender,
    status: g.status,
    dateOfBirth: g.dateOfBirth ?? '',
    dateOfDeath: g.dateOfDeath ?? '',
    causeOfDeath: g.causeOfDeath ?? '',
    goHomeDate: g.goHomeDate ?? '',
    colorVarietyId: g.colorVarietyId ?? '',
    enclosureId: g.enclosureId ?? '',
    litterId: g.litterId ?? '',
    originContactId: g.originContactId ?? '',
    originBreeder: g.originBreeder ?? '',
    receiverContactId: g.receiverContactId ?? '',
    genotype: g.genotype ?? '',
    notes: g.notes ?? '',
    isResident: g.isResident ?? true,
    isDeaf: g.isDeaf ?? null,
  }
}

/** "" -> null, else the value. */
const nn = (s: string): string | null => (s.trim() === '' ? null : s)

function isGenotypeValid(genotype: string): boolean {
  if (genotype.trim() === '') return true
  try {
    fromDisplayString(genotype)
    return true
  } catch {
    return false
  }
}

export default function GerbilFormPage() {
  const t = de.pages.gerbils
  const navigate = useNavigate()
  const { id } = useParams()
  const isEdit = Boolean(id)

  const [form, setForm] = useState<FormState>(EMPTY)
  const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({})
  const [initializedFor, setInitializedFor] = useState<string | null>(null)

  const existing = useApi(() => (id ? getGerbil(id) : Promise.resolve(null)), [id])
  const colorVarieties = useApi(() => listColorVarieties(), [])
  const enclosures = useApi(() => listEnclosures(), [])
  const contacts = useApi(() => listContacts(), [])
  const litters = useApi(() => listLitters(), [])

  // Prefill from the loaded gerbil once (edit mode). React's "adjust state
  // during render" pattern — runs without an effect and re-renders immediately.
  if (existing.data && initializedFor !== existing.data.id) {
    setInitializedFor(existing.data.id)
    setForm(formFromGerbil(existing.data))
  }

  // Create-mode prefill from query params (?litterId, ?dob) — used by the Wurf
  // workspace's "Jungtier erfassen" action to register a pup in one tap.
  const [searchParams] = useSearchParams()
  if (!isEdit && initializedFor === null) {
    const litterId = searchParams.get('litterId')
    const dob = searchParams.get('dob')
    if (litterId || dob) {
      setInitializedFor('new')
      setForm((f) => ({
        ...f,
        litterId: litterId ?? f.litterId,
        dateOfBirth: dob ?? f.dateOfBirth,
      }))
    }
  }

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

  const mutation = useMutation((body: CreateGerbil) =>
    isEdit && id ? updateGerbil(id, body) : createGerbil(body),
  )

  function validate(): boolean {
    const next: Partial<Record<keyof FormState, string>> = {}
    if (form.name.trim() === '') next.name = t.validation.nameRequired
    if (form.gender === '') next.gender = t.validation.genderRequired
    if (!isGenotypeValid(form.genotype)) next.genotype = t.validation.genotypeInvalid
    if (form.dateOfBirth && form.dateOfDeath && form.dateOfDeath < form.dateOfBirth) {
      next.dateOfDeath = t.validation.dateOfDeathBeforeBirth
    }
    setErrors(next)
    return Object.keys(next).length === 0
  }

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    if (!validate()) return
    const body: CreateGerbil = {
      name: form.name.trim(),
      gender: form.gender as Gender,
      status: form.status,
      dateOfBirth: nn(form.dateOfBirth),
      dateOfDeath: nn(form.dateOfDeath),
      causeOfDeath: nn(form.causeOfDeath),
      goHomeDate: nn(form.goHomeDate),
      colorVarietyId: nn(form.colorVarietyId),
      enclosureId: nn(form.enclosureId),
      litterId: nn(form.litterId),
      originContactId: nn(form.originContactId),
      originBreeder: nn(form.originBreeder),
      receiverContactId: nn(form.receiverContactId),
      genotype: nn(form.genotype),
      notes: nn(form.notes),
      isResident: form.isResident,
      isDeaf: form.isDeaf,
    }
    const result = await mutation.run(body)
    if (result.ok) navigate(`/rennmaeuse/${result.value.id}`)
    // On failure mutation.error drives the inline alert; run() never throws.
  }

  if (isEdit && existing.loading) return <p className="muted">{de.common.loading}</p>

  const selectedColorName =
    (colorVarieties.data ?? []).find((cv) => cv.id === form.colorVarietyId)?.name ?? null

  return (
    <section className="page">
      <h2>{isEdit ? t.form.editTitle : t.form.createTitle}</h2>

      <form className="form" onSubmit={onSubmit} noValidate>
        <label className="field">
          <span>{t.fields.name} *</span>
          <input
            className="input"
            value={form.name}
            onChange={(e) => set('name', e.target.value)}
            aria-invalid={Boolean(errors.name)}
          />
          {errors.name && <small className="error-text">{errors.name}</small>}
        </label>

        <label className="field">
          <span>{t.fields.gender} *</span>
          <select
            value={form.gender}
            onChange={(e) => set('gender', e.target.value as Gender | '')}
            aria-invalid={Boolean(errors.gender)}
          >
            <option value="">{t.form.none}</option>
            {GENDERS.map((g) => (
              <option key={g} value={g}>
                {genderLabel(g)}
              </option>
            ))}
          </select>
          {errors.gender && <small className="error-text">{errors.gender}</small>}
        </label>

        <label className="field">
          <span>{t.fields.status}</span>
          <select value={form.status} onChange={(e) => set('status', e.target.value as GerbilStatus)}>
            {GERBIL_STATUSES.map((s) => (
              <option key={s} value={s}>
                {statusLabel(s)}
              </option>
            ))}
          </select>
        </label>

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

        {form.status === 'Deceased' && (
          <>
            <label className="field">
              <span>{t.fields.dateOfDeath}</span>
              <input
                type="date"
                className="input"
                value={form.dateOfDeath}
                onChange={(e) => set('dateOfDeath', e.target.value)}
                aria-invalid={Boolean(errors.dateOfDeath)}
              />
              {errors.dateOfDeath && <small className="error-text">{errors.dateOfDeath}</small>}
            </label>
            <label className="field">
              <span>{t.fields.causeOfDeath}</span>
              <input
                className="input"
                value={form.causeOfDeath}
                onChange={(e) => set('causeOfDeath', e.target.value)}
              />
            </label>
          </>
        )}

        {form.status === 'GivenAway' && (
          <label className="field">
            <span>{t.fields.goHomeDate}</span>
            <input
              type="date"
              className="input"
              value={form.goHomeDate}
              onChange={(e) => set('goHomeDate', e.target.value)}
            />
          </label>
        )}

        <label className="field">
          <span>{t.fields.colorVariety}</span>
          <span className="farbschlag-value">
            <select
              value={form.colorVarietyId}
              onChange={(e) => set('colorVarietyId', e.target.value)}
            >
              <option value="">{t.form.none}</option>
              {(colorVarieties.data ?? []).map((cv) => (
                <option key={cv.id} value={cv.id}>
                  {cv.name}
                </option>
              ))}
            </select>
            {selectedColorName && <FarbschlagImage name={selectedColorName} size={36} />}
          </span>
        </label>

        <label className="field">
          <span>{t.fields.enclosure}</span>
          <select value={form.enclosureId} onChange={(e) => set('enclosureId', e.target.value)}>
            <option value="">{t.form.none}</option>
            {(enclosures.data ?? []).map((en) => (
              <option key={en.id} value={en.id}>
                {en.name}
              </option>
            ))}
          </select>
        </label>

        <label className="field">
          <span>{t.fields.litter}</span>
          <select value={form.litterId} onChange={(e) => set('litterId', e.target.value)}>
            <option value="">{t.form.none}</option>
            {(litters.data ?? []).map((l) => (
              <option key={l.id} value={l.id}>
                {l.name}
              </option>
            ))}
          </select>
        </label>

        <label className="field">
          <span>{t.fields.origin}</span>
          <select value={form.originContactId} onChange={(e) => set('originContactId', e.target.value)}>
            <option value="">{t.form.none}</option>
            {(contacts.data ?? []).map((c) => (
              <option key={c.id} value={c.id}>
                {c.name}
              </option>
            ))}
          </select>
        </label>

        <label className="field">
          <span>{t.fields.originBreeder}</span>
          <input
            className="input"
            value={form.originBreeder}
            placeholder="z. B. Zucht der Kleinen Chaoten"
            onChange={(e) => set('originBreeder', e.target.value)}
          />
        </label>

        <label className="field">
          <span>{t.fields.receiver}</span>
          <select
            value={form.receiverContactId}
            onChange={(e) => set('receiverContactId', e.target.value)}
          >
            <option value="">{t.form.none}</option>
            {(contacts.data ?? []).map((c) => (
              <option key={c.id} value={c.id}>
                {c.name}
              </option>
            ))}
          </select>
        </label>

        <label className="field">
          <span>{t.fields.genotype}</span>
          <input
            className="input"
            value={form.genotype}
            placeholder="Aa CC Dd EE GG Pp Spsp rere"
            onChange={(e) => set('genotype', e.target.value)}
            aria-invalid={Boolean(errors.genotype)}
          />
          <small className={errors.genotype ? 'error-text' : 'muted'}>
            {errors.genotype ?? t.form.genotypeHint}
          </small>
        </label>

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

        <label className="field">
          <span>{t.fields.isDeaf}</span>
          <select
            value={form.isDeaf === null ? '' : String(form.isDeaf)}
            onChange={(e) => {
              const v = e.target.value
              set('isDeaf', v === '' ? null : v === 'true')
            }}
          >
            <option value="">{t.form.isDeafUnknown}</option>
            <option value="true">{t.form.isDeafYes}</option>
            <option value="false">{t.form.isDeafNo}</option>
          </select>
        </label>

        <label className="field field--check" title={t.form.isResidentHint}>
          <span>{t.form.isResidentLabel}</span>
          <input
            type="checkbox"
            checked={form.isResident}
            onChange={(e) => set('isResident', e.target.checked)}
          />
        </label>

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

        <div className="form-actions">
          <button type="submit" className="btn btn--primary" disabled={mutation.pending}>
            {mutation.pending ? t.form.saving : t.form.save}
          </button>
          <Link to={isEdit && id ? `/rennmaeuse/${id}` : '/rennmaeuse'} className="btn">
            {t.form.cancel}
          </Link>
        </div>
      </form>
    </section>
  )
}
