import { useCallback, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import { de } from '../strings/de'
import { listLitters } from '../api/litters'
import { listGerbils } from '../api/gerbils'
import { andFilter, condition, escapeGridifyValue } from '../api/gridify'
import type { Gerbil, Litter } from '../api/types'
import { useApi } from '../hooks/useApi'
import { useInfiniteList, useInfiniteSentinel } from '../hooks/useInfiniteList'
import { formatDate } from '../format/labels'
import { FilterPanel } from '../components/FilterPanel'
import { useGerbilName } from '../components/breederSuffix'

const PAGE_SIZE = 20

type Tab = 'litters' | 'pairs'
type SortKey = 'dateDesc' | 'dateAsc'
// Trailing `id` → total order, so OFFSET pagination is stable for infinite scroll.
const SORT_ORDER_BY: Record<SortKey, string> = { dateDesc: 'date desc,id', dateAsc: 'date,id' }

function yearOptions(): number[] {
  const current = new Date().getFullYear()
  return Array.from({ length: 30 }, (_, i) => current - i)
}

interface Pair {
  fatherId: string
  motherId: string
  count: number
  lastDate: string
}

/** Group litters (with both parents known) by (father, mother). */
function derivePairs(litters: Litter[]): Pair[] {
  const map = new Map<string, Pair>()
  for (const l of litters) {
    if (!l.fatherId || !l.motherId) continue
    const key = `${l.fatherId}|${l.motherId}`
    const existing = map.get(key)
    if (existing) {
      existing.count += 1
      if (l.date > existing.lastDate) existing.lastDate = l.date
    } else {
      map.set(key, { fatherId: l.fatherId, motherId: l.motherId, count: 1, lastDate: l.date })
    }
  }
  return Array.from(map.values()).sort((a, b) => b.lastDate.localeCompare(a.lastDate))
}

export default function WuerfeListPage() {
  const t = de.pages.litters
  const [tab, setTab] = useState<Tab>('litters')
  const [search, setSearch] = useState('')
  const [year, setYear] = useState('')
  const [sort, setSort] = useState<SortKey>('dateDesc')

  // Parent names (shared by both tabs) — keep the full gerbil so the Zucht suffix applies.
  const gerbilName = useGerbilName()
  const gerbils = useApi(() => listGerbils({ page: 1, pageSize: 1000, orderBy: 'name' }), [])
  const gerbilById = useMemo(() => {
    const map = new Map<string, Gerbil>()
    for (const g of gerbils.data?.items ?? []) map.set(g.id, g)
    return map
  }, [gerbils.data])
  const parentName = useCallback((id: string | null): string => {
    if (!id) return '—'
    const gp = gerbilById.get(id)
    return gp ? gerbilName(gp) || de.pages.gerbils.nameless : t.detail.unknownParent
  }, [gerbilById, gerbilName, t.detail.unknownParent])

  // Litters tab (paged, filtered).
  const filter = andFilter(
    search.trim() && `(name=*${escapeGridifyValue(search)}/i|notes=*${escapeGridifyValue(search)}/i|litterLetter=*${escapeGridifyValue(search)}/i)`,
    year && condition({ field: 'date', op: '>=', value: `${year}-01-01` }),
    year && condition({ field: 'date', op: '<=', value: `${year}-12-31` }),
  )
  const orderBy = SORT_ORDER_BY[sort]
  const litters = useInfiniteList(
    (page) => listLitters({ filter: filter || undefined, orderBy, page, pageSize: PAGE_SIZE }),
    `${filter}|${orderBy}`,
    'wuerfe',
  )
  const littersSentinelRef = useInfiniteSentinel(litters)

  // Pairs tab: all litters, grouped client-side.
  const allLitters = useApi(
    () => (tab === 'pairs' ? listLitters({ page: 1, pageSize: 1000, orderBy: 'date desc' }) : Promise.resolve(null)),
    [tab],
  )
  const pairs = useMemo(() => derivePairs(allLitters.data?.items ?? []), [allLitters.data])

  // Search-enabled pairs list (client-side search by parent name)
  const filteredPairs = useMemo(() => {
    if (!search.trim()) return pairs
    const term = search.toLowerCase()
    return pairs.filter((p) =>
      parentName(p.fatherId).toLowerCase().includes(term) ||
      parentName(p.motherId).toLowerCase().includes(term)
    )
  }, [pairs, search, parentName])

  const items = litters.items

  return (
    <section className="page">
      <header className="page-head">
        <h2>{t.title}</h2>
        <Link to="/wuerfe/neu" className="btn btn--primary">
          + {t.newButton}
        </Link>
      </header>

      <div className="tabs" role="tablist">
        <button
          type="button"
          role="tab"
          aria-selected={tab === 'litters'}
          className={tab === 'litters' ? 'tab tab--active' : 'tab'}
          onClick={() => setTab('litters')}
        >
          {t.tabs.litters}
        </button>
        <button
          type="button"
          role="tab"
          aria-selected={tab === 'pairs'}
          className={tab === 'pairs' ? 'tab tab--active' : 'tab'}
          onClick={() => setTab('pairs')}
        >
          {t.tabs.pairs}
        </button>
      </div>

      {tab === 'litters' && (
        <>
          <FilterPanel
            searchField={
              <input
                type="search"
                className="input"
                placeholder={t.searchPlaceholder}
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                aria-label="Wurf suchen"
              />
            }
            activeCount={(year !== '' ? 1 : 0) + (search.trim() !== '' ? 1 : 0)}
            onReset={() => {
              setSearch('')
              setYear('')
              setSort('dateDesc')
            }}
          >
            <label className="field">
              <span>{t.filterYear}</span>
              <select
                value={year}
                onChange={(e) => setYear(e.target.value)}
              >
                <option value="">{t.allYears}</option>
                {yearOptions().map((y) => (
                  <option key={y} value={y}>
                    {y}
                  </option>
                ))}
              </select>
            </label>
            <label className="field">
              <span>{de.pages.gerbils.filters.sortBy}</span>
              <select value={sort} onChange={(e) => setSort(e.target.value as SortKey)}>
                <option value="dateDesc">{t.sort.dateDesc}</option>
                <option value="dateAsc">{t.sort.dateAsc}</option>
              </select>
            </label>
          </FilterPanel>

          {litters.loading && <p className="muted">{de.common.loading}</p>}
          {litters.error && (
            <div className="alert alert--error">
              <span>{litters.error}</span>
              <button type="button" className="btn" onClick={litters.reload}>
                {de.common.retry}
              </button>
            </div>
          )}
          {!litters.loading && !litters.error && items.length === 0 && (
            <p className="muted">{t.empty}</p>
          )}

          {items.length > 0 && (
            <ul className="card-list">
              {items.map((l) => (
                <li key={l.id}>
                  <Link to={`/wuerfe/${l.id}`} className="gerbil-card">
                    <span className="gerbil-card__name">{l.name}</span>
                    <span className="gerbil-card__meta">{formatDate(l.date)}</span>
                    <span className="gerbil-card__meta">
                      {parentName(l.fatherId)} × {parentName(l.motherId)}
                    </span>
                    <span className="gerbil-card__meta">
                      {l.totalBorn != null ? `${l.totalBorn} ${t.fields.totalBorn}` : '—'}
                    </span>
                  </Link>
                </li>
              ))}
            </ul>
          )}

          {/* Infinite-scroll sentinel + "loading more" indicator. */}
          {litters.hasMore && (
            <div ref={littersSentinelRef} aria-hidden="true" style={{ height: 1 }} />
          )}
          {litters.loadingMore && (
            <p className="muted" style={{ textAlign: 'center', padding: '0.75rem 0' }}>
              {de.common.loading}
            </p>
          )}
        </>
      )}

      {tab === 'pairs' && (
        <>
          <div style={{ marginBottom: '1.5rem', display: 'flex', gap: '1rem', alignItems: 'center' }}>
            <input
              type="search"
              className="input"
              style={{ maxWidth: '320px' }}
              placeholder="Elternteil suchen …"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              aria-label="Elternteil suchen"
            />
            {search && (
              <button
                type="button"
                className="btn btn--secondary btn--sm"
                onClick={() => setSearch('')}
              >
                {de.pages.gerbils.filters.reset}
              </button>
            )}
          </div>
          {allLitters.loading && <p className="muted">{de.common.loading}</p>}
          {!allLitters.loading && filteredPairs.length === 0 && <p className="muted">{t.pairs.empty}</p>}
          {filteredPairs.length > 0 && (
            <ul className="card-list">
              {filteredPairs.map((p) => (
                <li key={`${p.fatherId}|${p.motherId}`} className="gerbil-card">
                  <span className="gerbil-card__name">
                    {parentName(p.fatherId)} × {parentName(p.motherId)}
                  </span>
                  <span className="gerbil-card__meta">
                    {p.count} {t.pairs.litterCount}
                  </span>
                  <span className="gerbil-card__meta">
                    {t.pairs.lastLitter}: {formatDate(p.lastDate)}
                  </span>
                  <Link to={`/genetik?vater=${p.fatherId}&mutter=${p.motherId}`} className="link-btn">
                    {t.pairs.testMating}
                  </Link>
                </li>
              ))}
            </ul>
          )}
        </>
      )}
    </section>
  )
}
