import { useCallback, useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { de } from '../strings/de'
import { getLitter } from '../api/litters'
import { getGerbil, listGerbils } from '../api/gerbils'
import { listColorVarieties, listContacts } from '../api/lookups'
import { API_BASE_URL } from '../api/client'
import { condition } from '../api/gridify'
import { type Gerbil } from '../api/types'
import { useApi } from '../hooks/useApi'
import { formatDate, genderLabel } from '../format/labels'
import { isValidGenotype } from '../format/genotypeText'
import { breed, fromDisplayString, genotypeToFarbschlag, formatVarietyName, UNKNOWN_FARBSCHLAG, type BreedingResult } from '../genetics'
import BreedingResultView from '../components/BreedingResultView'
import GerbilIcon from '../components/GerbilIcon'
import ProvenanceDialog from '../components/ProvenanceDialog'
import ReportErrorDialog from '../components/ReportErrorDialog'
import { useGerbilName } from '../components/breederSuffix'
import './wuerfe.css'

/** Addiert Tage zu einem ISO-Datum (YYYY-MM-DD) und gibt ISO zurück. */
function addDaysIso(iso: string, days: number): string {
  const d = new Date(iso + 'T00:00:00')
  d.setDate(d.getDate() + days)
  return d.toISOString().slice(0, 10)
}

type JuvenileFields = (typeof de.pages.litters.detail.juvenileFields)

function JuvenileCard({ g, farbe, receiver, tJf }: {
  g: Gerbil
  farbe: string | null
  receiver: string | null
  tJf: JuvenileFields
}) {
  const gerbilName = useGerbilName()
  const [failedUrl, setFailedUrl] = useState<string | null>(null)
  const rawUrl = g.profilePhotoUrl
    ? /^(https?:|data:|\/\/)/.test(g.profilePhotoUrl)
      ? g.profilePhotoUrl
      : `${API_BASE_URL}${g.profilePhotoUrl}`
    : null
  const photoUrl = rawUrl !== failedUrl ? rawUrl : null

  return (
    <Link to={`/rennmaeuse/${g.id}`} className="gerbil-card gerbil-card--with-photo">
      <div className="juvenile-photo">
        {photoUrl ? (
          <img
            src={photoUrl}
            alt={g.name || ''}
            className="juvenile-photo__avatar"
            onError={() => setFailedUrl(rawUrl)}
          />
        ) : (
          <GerbilIcon size="1.4rem" aria-hidden="true" />
        )}
      </div>
      <div className="juvenile-body">
        <span className="gerbil-card__name">{gerbilName(g)}</span>
        <span className="gerbil-card__meta">{genderLabel(g.gender)}</span>
        {farbe && <span className="gerbil-card__meta">{tJf.colorVariety}: {farbe}</span>}
        {g.goHomeDate && <span className="gerbil-card__meta">{tJf.goHomeDate}: {formatDate(g.goHomeDate)}</span>}
        {receiver && <span className="gerbil-card__meta">{tJf.receiver}: {receiver}</span>}
        {g.dateOfDeath && <span className="gerbil-card__meta">{tJf.dateOfDeath}: {formatDate(g.dateOfDeath)}</span>}
        {g.causeOfDeath && <span className="gerbil-card__meta">{tJf.causeOfDeath}: {g.causeOfDeath}</span>}
      </div>
    </Link>
  )
}

export default function WurfDetailPage() {
  const t = de.pages.litters
  const gerbilName = useGerbilName()
  const { id = '' } = useParams()
  const [reportOpen, setReportOpen] = useState(false)
  const [provenanceOpen, setProvenanceOpen] = useState(false)

  const litter = useApi(() => getLitter(id), [id])
  const fatherId = litter.data?.fatherId ?? null
  const motherId = litter.data?.motherId ?? null

  const father = useApi(() => (fatherId ? getGerbil(fatherId) : Promise.resolve(null)), [fatherId])
  const mother = useApi(() => (motherId ? getGerbil(motherId) : Promise.resolve(null)), [motherId])

  // Juveniles = gerbils whose litterId is this litter.
  const juveniles = useApi(
    () =>
      id
        ? listGerbils({
            filter: condition({ field: 'litterId', op: '==', value: id }),
            orderBy: 'name',
            page: 1,
            pageSize: 1000,
          })
        : Promise.resolve(null),
    [id],
  )

  // Expected Farbschlag distribution for this pairing (client-side GEN-1).
  const expected: BreedingResult | null = useMemo(() => {
    const fg = father.data?.genotype
    const mg = mother.data?.genotype
    if (!fg || !mg || !isValidGenotype(fg) || !isValidGenotype(mg)) return null
    return breed(fromDisplayString(fg), fromDisplayString(mg))
  }, [father.data, mother.data])

  // Farbschlag + Abnehmer lookups for the juvenile list.
  const colorVarieties = useApi(() => listColorVarieties(), [])
  const contacts = useApi(() => listContacts(), [])

  const colorNameById = useMemo(
    () => new Map((colorVarieties.data ?? []).map((c) => [c.id, c.name])),
    [colorVarieties.data],
  )
  const contactNameById = useMemo(
    () => new Map((contacts.data ?? []).map((c) => [c.id, c.name])),
    [contacts.data],
  )

  const farbschlagOf = useCallback(
    (g: { colorVarietyId: string | null; genotype: string | null }): string | null => {
      if (g.colorVarietyId) {
        const name = colorNameById.get(g.colorVarietyId)
        if (name) return formatVarietyName(name, g.genotype)
      }
      if (g.genotype?.trim()) {
        try {
          const name = genotypeToFarbschlag(fromDisplayString(g.genotype))
          return name === UNKNOWN_FARBSCHLAG ? null : name
        } catch {
          return null
        }
      }
      return null
    },
    [colorNameById],
  )

  if (litter.loading) return <p className="muted">{de.common.loading}</p>
  if (litter.error || !litter.data) {
    return (
      <section className="page">
        <p className="muted">{litter.error ?? t.detail.notFound}</p>
        <Link to="/wuerfe" className="btn">
          {t.detail.back}
        </Link>
      </section>
    )
  }

  const l = litter.data
  const registered = juveniles.data?.totalCount ?? 0
  const parentLink = (id: string | null, g: Gerbil | null) =>
    id && g ? <Link to={`/rennmaeuse/${id}`}>{gerbilName(g) || de.pages.gerbils.nameless}</Link> : t.detail.unknownParent

  return (
    <section className="page">
      <header className="page-head">
        <h2>{l.name}</h2>
        <div className="head-actions">
          <Link to={`/wuerfe/${l.id}/bearbeiten`} className="btn btn--primary">
            {t.detail.edit}
          </Link>
          <button type="button" className="btn" onClick={() => setProvenanceOpen(true)}>
            {de.provenance.button}
          </button>
          <button type="button" className="btn" onClick={() => setReportOpen(true)}>
            {de.feedback.button}
          </button>
          <Link to="/wuerfe" className="btn">
            {t.detail.back}
          </Link>
        </div>
      </header>

      <dl className="def-list">
        <div className="def-row">
          <dt>{t.fields.date}</dt>
          <dd>{formatDate(l.date)}</dd>
        </div>
        <div className="def-row">
          <dt>{t.detail.parents}</dt>
          <dd>
            {parentLink(fatherId, father.data)} × {parentLink(motherId, mother.data)}
          </dd>
        </div>
        <div className="def-row">
          <dt>{t.detail.registered}</dt>
          <dd>
            {registered}
            {l.totalBorn != null ? ` / ${l.totalBorn}` : ''}
          </dd>
        </div>
        {l.deathsWithin8Weeks != null && (
          <div className="def-row">
            <dt>{t.fields.deathsWithin8Weeks}</dt>
            <dd>{l.deathsWithin8Weeks}</dd>
          </div>
        )}
        {l.stillborn != null && (
          <div className="def-row">
            <dt>{t.fields.stillborn}</dt>
            <dd>{l.stillborn}</dd>
          </div>
        )}
        {l.date && (
          <>
            <div className="def-row">
              <dt>{t.fields.socializeDate}</dt>
              <dd>{formatDate(addDaysIso(l.date, 56))}</dd>
            </div>
            <div className="def-row">
              <dt>{t.fields.groupGoHomeDate}</dt>
              <dd>{formatDate(addDaysIso(l.date, 70))}</dd>
            </div>
          </>
        )}
        <div className="def-row">
          <dt>{t.fields.expectedGoHomeDate}</dt>
          <dd>{formatDate(l.expectedGoHomeDate)}</dd>
        </div>
        {l.notes && (
          <div className="def-row">
            <dt>{t.fields.notes}</dt>
            <dd>{l.notes}</dd>
          </div>
        )}
      </dl>

      <div className="page-head">
        <h3>{t.detail.juveniles}</h3>
        <Link
          to={`/rennmaeuse/neu?litterId=${l.id}${l.date ? `&dob=${l.date}` : ''}`}
          className="btn btn--primary"
        >
          + {t.detail.registerJuvenile}
        </Link>
      </div>
      {juveniles.loading && <p className="muted">{de.common.loading}</p>}
      {!juveniles.loading && registered === 0 && <p className="muted">{t.detail.noJuveniles}</p>}
      {registered > 0 && (
        <ul className="card-list">
          {[...(juveniles.data?.items ?? [])]
            .sort((a, b) => {
              // Wurfchronik-Reihenfolge (birthOrder) zuerst; ohne Angabe alphabetisch.
              const ao = a.birthOrder ?? Number.POSITIVE_INFINITY
              const bo = b.birthOrder ?? Number.POSITIVE_INFINITY
              if (ao !== bo) return ao - bo
              return (a.name || '').localeCompare(b.name || '', 'de')
            })
            .map((g) => {
            const farbe = farbschlagOf(g)
            const receiver = g.receiverContactId ? contactNameById.get(g.receiverContactId) ?? null : null
            const tJf = t.detail.juvenileFields
            return (
              <li key={g.id}>
                <JuvenileCard g={g} farbe={farbe} receiver={receiver} tJf={tJf} />
              </li>
            )
          })}
        </ul>
      )}

      {expected ? (
        <BreedingResultView result={expected} title={t.detail.expectedColors} />
      ) : (
        <p className="muted">{t.detail.needParentsGenotype}</p>
      )}

      <ReportErrorDialog
        open={reportOpen}
        onClose={() => setReportOpen(false)}
        context={{ context: 'litter-detail', litterId: l.id, entityName: l.name }}
      />

      <ProvenanceDialog
        open={provenanceOpen}
        onClose={() => setProvenanceOpen(false)}
        provenance={l.provenance}
        entityLabel={de.provenance.entityLabels.litter}
      />
    </section>
  )
}
