import { useMemo, useState, type FormEvent } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { de } from '../strings/de'
import { errorCode } from '../api/client'
import { createLitter, getLitter, updateLitter } from '../api/litters'
import { listGerbils } from '../api/gerbils'
import type { CreateLitter } from '../api/types'
import { useApi, useMutation } from '../hooks/useApi'
import AnimalPicker from '../components/AnimalPicker'

interface FormState {
  name: string
  date: string
  fatherId: string
  fatherName: string
  motherId: string
  motherName: string
  totalBorn: string
  expectedGoHomeDate: string
  notes: string
}

const EMPTY: FormState = {
  name: '',
  date: '',
  fatherId: '',
  fatherName: '',
  motherId: '',
  motherName: '',
  totalBorn: '',
  expectedGoHomeDate: '',
  notes: '',
}

/** Add n days to an ISO date ("YYYY-MM-DD"), in UTC to avoid TZ drift. */
function addDays(iso: string, n: number): string {
  const [y, m, d] = iso.split('-').map(Number)
  if (!y || !m || !d) return ''
  const ms = Date.UTC(y, m - 1, d) + n * 86_400_000
  return new Date(ms).toISOString().slice(0, 10)
}

const nn = (s: string): string | null => (s.trim() === '' ? null : s)

export default function WurfFormPage() {
  const t = de.pages.litters
  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 [submitError, setSubmitError] = useState<string | null>(null)
  const [goHomeTouched, setGoHomeTouched] = useState(false)
  const [initializedFor, setInitializedFor] = useState<string | null>(null)

  const existing = useApi(() => (id ? getLitter(id) : Promise.resolve(null)), [id])
  // Resolve parent names when editing (litter stores only ids).
  const gerbils = useApi(() => listGerbils({ page: 1, pageSize: 1000, orderBy: 'name' }), [])
  const nameById = useMemo(() => {
    const map = new Map<string, string>()
    for (const g of gerbils.data?.items ?? []) map.set(g.id, g.name)
    return map
  }, [gerbils.data])

  // Prefill in edit mode (adjust state during render, guarded).
  if (existing.data && initializedFor !== existing.data.id) {
    setInitializedFor(existing.data.id)
    const l = existing.data
    setForm({
      name: l.name,
      date: l.date ?? '',
      fatherId: l.fatherId ?? '',
      fatherName: l.fatherId ? (nameById.get(l.fatherId) || de.pages.gerbils.nameless) : '',
      motherId: l.motherId ?? '',
      motherName: l.motherId ? (nameById.get(l.motherId) || de.pages.gerbils.nameless) : '',
      totalBorn: l.totalBorn != null ? String(l.totalBorn) : '',
      expectedGoHomeDate: l.expectedGoHomeDate ?? '',
      notes: l.notes ?? '',
    })
    setGoHomeTouched(true)
  }

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

  // Wurfdatum change: auto-suggest go-home +35 days unless the user edited it.
  const onDateChange = (date: string) => {
    setForm((f) => ({
      ...f,
      date,
      expectedGoHomeDate: goHomeTouched ? f.expectedGoHomeDate : date ? addDays(date, 35) : '',
    }))
  }

  const mutation = useMutation((body: CreateLitter) =>
    isEdit && id ? updateLitter(id, body) : createLitter(body),
  )

  function validate(): boolean {
    const next: Partial<Record<keyof FormState, string>> = {}
    if (form.name.trim() === '') next.name = t.validation.nameRequired
    if (form.date.trim() === '') next.date = t.validation.dateRequired
    setErrors(next)
    return Object.keys(next).length === 0
  }

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    if (!validate()) return
    const totalBornNum = form.totalBorn.trim() === '' ? null : Number(form.totalBorn)
    const body: CreateLitter = {
      name: form.name.trim(),
      date: form.date,
      fatherId: nn(form.fatherId),
      motherId: nn(form.motherId),
      totalBorn: totalBornNum != null && Number.isFinite(totalBornNum) ? totalBornNum : null,
      expectedGoHomeDate: nn(form.expectedGoHomeDate),
      notes: nn(form.notes),
    }
    setSubmitError(null)
    const result = await mutation.run(body)
    if (result.ok) {
      navigate(`/wuerfe/${result.value.id}`)
      return
    }
    // Localize the backend's parent-gender 400 by its code; else generic message.
    setSubmitError(
      errorCode(result.cause) === 'InvalidParentGender'
        ? t.validation.invalidParentGender
        : result.error,
    )
  }

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

  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.date} *</span>
          <input
            type="date"
            className="input"
            value={form.date}
            onChange={(e) => onDateChange(e.target.value)}
            aria-invalid={Boolean(errors.date)}
          />
          {errors.date && <small className="error-text">{errors.date}</small>}
        </label>

        <fieldset className="parent-selector">
          <legend>{t.fields.father}</legend>
          {form.fatherName ? (
            <p className="muted parent-selector__animal">
              {form.fatherName}
              <button
                type="button"
                className="link-btn"
                onClick={() => setForm((f) => ({ ...f, fatherId: '', fatherName: '' }))}
              >
                {de.pages.genetik.clearAnimal}
              </button>
            </p>
          ) : (
            <AnimalPicker
              gender="male"
              onPick={(g) => setForm((f) => ({ ...f, fatherId: g.id, fatherName: g.name || de.pages.gerbils.nameless }))}
            />
          )}
        </fieldset>

        <fieldset className="parent-selector">
          <legend>{t.fields.mother}</legend>
          {form.motherName ? (
            <p className="muted parent-selector__animal">
              {form.motherName}
              <button
                type="button"
                className="link-btn"
                onClick={() => setForm((f) => ({ ...f, motherId: '', motherName: '' }))}
              >
                {de.pages.genetik.clearAnimal}
              </button>
            </p>
          ) : (
            <AnimalPicker
              gender="female"
              onPick={(g) => setForm((f) => ({ ...f, motherId: g.id, motherName: g.name || de.pages.gerbils.nameless }))}
            />
          )}
        </fieldset>

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

        <label className="field">
          <span>{t.fields.expectedGoHomeDate}</span>
          <input
            type="date"
            className="input"
            value={form.expectedGoHomeDate}
            onChange={(e) => {
              setGoHomeTouched(true)
              set('expectedGoHomeDate', e.target.value)
            }}
          />
          <small className="muted">{t.form.goHomeHint}</small>
        </label>

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

        {submitError && <div className="alert alert--error">{submitError}</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 ? `/wuerfe/${id}` : '/wuerfe'} className="btn">
            {t.form.cancel}
          </Link>
        </div>
      </form>
    </section>
  )
}
