/**
 * QA-1: Seed-Daten für den Mock-Modus — geformt exakt nach dem DATA-2-Vertrag
 * (camelCase-DTOs, Gridify-paged Listen). Datensatz angelehnt an Kellys
 * FEAT-4-Verifikationsdaten (mehrgenerationiger Stammbaum inkl. gemeinsamem
 * Vorfahren Anton), erweitert um Becken/Kontakte/Gesundheit/Gewicht für die
 * FEAT-2/FEAT-6-Flüsse.
 */
import type { Contact, Enclosure, Gerbil, Litter } from '../src/api/types'
import type { InboxRequest } from '../src/api/requests'

export interface HealthRecordRow {
  id: string
  gerbilId: string
  date: string
  type: string
  description: string
  veterinarian: string | null
  createdAt: string
}

export interface WeightRecordRow {
  id: string
  gerbilId: string
  date: string
  weightGrams: number
  notes: string | null
}

/** WEB-0b: CMS-Block (data ist das typ-spezifische JSON-Objekt). */
export interface MockBlock {
  id: string
  order: number
  type: string
  data: Record<string, unknown>
}

/** WEB-0b: CMS-Seite der öffentlichen Webseite. */
export interface MockPage {
  id: string
  slug: string
  title: string
  seoDescription: string | null
  status: 'Draft' | 'Published'
  blocks: MockBlock[]
}

/** ABGABE: Abgabevertrag (mirrors SaleContract in src/api/contracts.ts). */
export interface MockContract {
  id: string
  contactId: string
  price: number
  handoverDate: string
  contractDate: string
  fileName: string
  createdAt: string
  gerbilIds: string[]
  url: string
  /** Ob die Word-Datei vorliegt. Importierte Verträge: false (kein Word-Button). */
  hasFile: boolean
}

export interface MockDb {
  gerbils: Gerbil[]
  litters: Litter[]
  enclosures: Enclosure[]
  contacts: Contact[]
  colorVarieties: { id: string; name: string; canonicalGenotype: string | null; sortOrder: number }[]
  healthRecords: HealthRecordRow[]
  weightRecords: WeightRecordRow[]
  pages: MockPage[]
  // INBOX-1: Anfragen-Posteingang. Die Flags steuern die Fehlerpfade des Mocks
  // (Specs können sie pro Test umlegen): KI-Entwurf 503 / Sync+Send Mail-Fehler.
  requests: InboxRequest[]
  aiConfigured: boolean
  mailConfigured: boolean
  // ABGABE: Verträge + KI-Inserat-Flag
  contracts: MockContract[]
  saleAdConfigured: boolean
  // FEAT-NAMEGEN: Namensvorschläge — false = 503 NamesKeyMissing simulieren
  namesConfigured: boolean
  // FEEDBACK: "Fehler melden" — gesammelte Berichte (POST /feedback)
  feedback: Record<string, unknown>[]
  // GEPRÜFTE TIERE: „vollständig korrekt"-Markierungen / Schutz (/verified-gerbils)
  verified: Record<string, unknown>[]
  // RPRO3: RennmausPro-III-Import — feste Auswertung + Import-Ergebnis für die UI-Specs.
  rpro3: {
    analyze: Record<string, unknown>
    execute: Record<string, unknown>
  }
  // ERWERB: Erwerb/Kauf je Tier (Kaufdatum, Preis, Notiz) — /acquisitions
  acquisitions: Record<string, unknown>[]
  // ABGABE-STATUS: Reservierungs-/Abgabe-Status (POST/PUT/DELETE /reservations)
  reservations: Record<string, unknown>[]
  // WAITLIST: Warteliste/Nachfrage (RennmausPro nachfrage_tb)
  waitingList: Record<string, unknown>[]
  // RÜCKNAHMEN: zurückgenommene Tiere (CRUD /returns)
  returns: Record<string, unknown>[]
  // EXHIBITION: Ausstellungs-/Show-Ergebnisse je Tier (POST /exhibitions)
  exhibitions: Record<string, unknown>[]
}

function gerbil(
  id: string,
  name: string,
  gender: 'male' | 'female',
  dateOfBirth: string,
  litterId: string | null,
  colorVarietyId: string | null,
  genotype: string | null = null,
): Gerbil {
  return {
    id,
    name,
    gender,
    status: 'Breeding',
    dateOfBirth,
    dateOfDeath: null,
    causeOfDeath: null,
    goHomeDate: null,
    litterId,
    enclosureId: null,
    colorVarietyId,
    originContactId: null,
    receiverContactId: null,
    originBreeder: null,
    // SEARCH-2b: backend stores a normalized name (lowercase, [\s._-] stripped).
    nameSearch: name.toLowerCase().replace(/[\s._-]/g, ''),
    genotype,
    notes: null,
    // BESTAND-FILTER: default = eigener Bestand; einzelne externe Ahnen unten gesetzt.
    isResident: true,
    profilePhotoUrl: null,
  }
}

/** Frischer, unabhängiger Datenbestand pro Test. */
export function seedDb(): MockDb {
  const gerbils: Gerbil[] = [
    {
      ...gerbil('kruemel', 'Krümel', 'female', '2025-03-12', 'w-kruemel', 'cv-agouti', 'Aa CC DD EE GG Pp spsp rere'),
      enclosureId: 'enc-gross',
      originContactId: 'con-meier',
      originBreeder: 'Clan-Kleine-Chaoten',
      // NACHVERFOLGUNG: Datenherkunft (vom Import erzeugter JSON-String).
      provenance: JSON.stringify({
        sourceFiles: ['Stammbaum von Krümel.xlsx', 'Wurfchronik-Detail.docx'],
        mergedRecordCount: 2,
        fromWurfchronik: true,
        parentMethod: 'chart-position',
        parentConfidence: 'medium',
        notes: ['aus 2 Datensätzen zusammengeführt'],
        history: [
          'In „Stammbaum von Krümel.xlsx“ gefunden.',
          'Geburtsdatum (12.03.2025) aus „Stammbaum von Krümel.xlsx“.',
          'Genotyp aus „Stammbaum von Krümel.xlsx“.',
          'Auch in „Wurfchronik-Detail.docx“ gefunden → Datensätze zusammengeführt.',
          // VERWORFEN: abweichender Wert aus einer Quelle wurde verworfen (Grund + Ersatz).
          '⚠ Geburtsdatum 14.06.2015 aus „Wurfchronik-Detail.docx“ verworfen — abweichend; 12.03.2025 aus „Stammbaum von Krümel.xlsx“ verwendet (Mehrheit).',
          'Eltern über Position im Stammbaum erkannt (Quelle: „Stammbaum von Krümel.xlsx“).',
          // VERWORFEN: unplausibler Elternteil verworfen, kein Ersatz verwendet.
          '⚠ Vater „Jayjay“ (*19.06.2013) verworfen — unplausibel (9 Jahre älter als das Kind); kein Ersatz.',
          'Angaben aus der Wurfchronik übernommen.',
        ],
      }),
    },
    { ...gerbil('fridolin', 'Fridolin', 'male', '2023-05-01', 'w-fridolin', 'cv-schwarz', 'aa CC DD EE GG PP spsp rere'), enclosureId: 'enc-gross', originBreeder: 'Zoohandlung Meier', profilePhotoUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' },
    gerbil('luna', 'Luna', 'female', '2023-08-15', 'w-luna', 'cv-gold', 'AA CC DD EE GG pp spsp rere'),
    gerbil('balu', 'Balu', 'male', '2021-04-20', 'w-balu', 'cv-agouti'),
    gerbil('maja', 'Maja', 'female', '2021-06-11', null, 'cv-schwarz-schecke', 'aa CC DD EE GG PP Spsp rere'),
    gerbil('karlsson', 'Karlsson', 'male', '2022-02-02', 'w-karlsson', 'cv-blau'),
    gerbil('smilla', 'Smilla', 'female', '2022-09-30', null, 'cv-himalaya'),
    gerbil('anton', 'Anton', 'male', '2019-07-07', 'w-anton', 'cv-agouti'),
    gerbil('greta', 'Greta', 'female', '2019-05-23', null, 'cv-schwarz'),
    gerbil('frieda', 'Frieda', 'female', '2020-01-18', null, 'cv-gold'),
    gerbil('emil', 'Emil', 'male', '2017-03-03', 'w-emil', 'cv-agouti'),
    // BESTAND-FILTER: externe Ahnen (Gründertiere fremder Zuchten, nur für den Stammbaum).
    { ...gerbil('hilde', 'Hilde', 'female', '2017-11-11', null, 'cv-schwarz'), isResident: false, originBreeder: 'Zoohandlung Meier' },
    { ...gerbil('max', 'Max', 'male', '2015-08-08', null, 'cv-agouti'), isResident: false, originBreeder: 'Zoohandlung Meier' },
    // Statistik: Verstorbene + Abgegebene für Verluste/Bestandskurve
    { ...gerbil('willi', 'Willi', 'male', '2019-09-09', null, 'cv-schwarz'), status: 'Deceased', dateOfDeath: '2022-04-04' },
    { ...gerbil('pauli', 'Pauli', 'male', '2023-05-01', null, 'cv-himalaya'), status: 'GivenAway', goHomeDate: '2023-07-15', receiverContactId: 'con-huber' },
    { ...gerbil('rosa', 'Rosa', 'female', '2020-02-02', null, 'cv-gold'), status: 'Deceased', dateOfDeath: '2023-08-15' },
    { ...gerbil('pauli-breeder', 'Pauli Breeder', 'male', '2023-05-01', null, 'cv-himalaya'), status: 'GivenAway', goHomeDate: '2023-07-15', receiverContactId: 'con-meier' },
    { ...gerbil('pauli-neither', 'Pauli Neither', 'male', '2023-05-01', null, 'cv-himalaya'), status: 'GivenAway', goHomeDate: '2023-07-15', receiverContactId: 'con-neither' },
    // ABGABE: zwei Tiere zur Abgabe im Quarantänebecken (enc-leer ist leer, kein Konflikt
    // mit dem Becken-Belegungstest der Großbecken-2-Tiere-Assertion).
    {
      ...gerbil('sale-balu', 'Balu Abgabe', 'male', '2024-03-12', null, 'cv-agouti'),
      status: 'ForSale' as const,
      enclosureId: 'enc-leer',
      notes: 'ruhig, nimmt Leckerlis aus der Hand',
    },
    {
      ...gerbil('sale-benny', 'Benny Abgabe', 'male', '2024-03-12', null, 'cv-schwarz-schecke'),
      status: 'ForSale' as const,
      enclosureId: 'enc-leer',
      notes: 'neugieriger Entdecker',
    },
    // LITTER-JUVENILE-DETAILS: Jungtiere für Wurf K mit Zusatzinfos.
    // JUVENILE-AVATARS: Pippa hat profilePhotoUrl (1×1-PNG data-URI) → Avatar-Img sichtbar.
    {
      ...gerbil('pup-abgabe', 'Pippa', 'female', '2025-03-12', 'w-kruemel', 'cv-gold'),
      status: 'GivenAway' as const,
      goHomeDate: '2025-05-01',
      receiverContactId: 'con-huber',
      profilePhotoUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
    },
    {
      ...gerbil('pup-verstorben', 'Benny', 'male', '2025-03-12', 'w-kruemel', null),
      status: 'Deceased' as const,
      dateOfDeath: '2025-04-15',
      causeOfDeath: 'Altersschwäche',
    },
    // UI-POLISH-1: Import-Stub ohne Namen — testet den '(ohne Namen)'-Platzhalter in Liste + Detail.
    gerbil('nameless-stub', '', 'male', '2023-01-01', null, null),
    // SIBLING-PAIRING: Vollgeschwister-Verpaarung (in der Zucht häufig). Beide
    // Eltern von 'inzucht-kind' stammen aus DEMSELBEN Wurf 'w-zwillinge' → das
    // Diagramm führt ihren Vorfahren-Ast zu einem Verweis-Knoten zusammen.
    gerbil('zwilling-bock', 'Zwilling Bock', 'male', '2020-05-01', 'w-zwillinge', 'cv-agouti'),
    gerbil('zwilling-maus', 'Zwilling Maus', 'female', '2020-05-01', 'w-zwillinge', 'cv-schwarz'),
    { ...gerbil('opa-w', 'Opa W', 'male', '2018-01-01', null, 'cv-agouti'), isResident: false },
    { ...gerbil('oma-u', 'Oma U', 'female', '2018-02-01', null, 'cv-gold'), isResident: false },
    gerbil('inzucht-kind', 'Inzucht Kind', 'female', '2021-06-01', 'w-inzucht', 'cv-agouti'),
  ]

  const litters: Litter[] = [
    { id: 'w-zwillinge', name: 'Wurf Z', date: '2020-05-01', totalBorn: 4, expectedGoHomeDate: null, notes: null, fatherId: 'opa-w', motherId: 'oma-u', showInChronicle: true },
    { id: 'w-inzucht', name: 'Wurf I', date: '2021-06-01', totalBorn: 3, expectedGoHomeDate: null, notes: null, fatherId: 'zwilling-bock', motherId: 'zwilling-maus', showInChronicle: true },
    {
      id: 'w-kruemel', name: 'Wurf K', date: '2025-03-12', totalBorn: 5, expectedGoHomeDate: '2025-04-16', notes: null, fatherId: 'fridolin', motherId: 'luna', deathsWithin8Weeks: 1, stillborn: 1, showInChronicle: true,
      // NACHVERFOLGUNG: Datenherkunft des Wurfs (vom Import erzeugter JSON-String).
      provenance: JSON.stringify({
        sourceFiles: ['Wurfchronik Teil 1_page_0009.md', 'Wurfchronik Teil 1_page_0028.md'],
        mergedRecordCount: 2,
        fromWurfchronik: true,
        notes: ['aus Wurfchronik', 'aus 2 Datensätzen zusammengeführt', 'Geschwister-Würfe zusammengeführt'],
        history: [
          'Wurf aus Wurfchronik „Wurfchronik Teil 1_page_0009.md“.',
          'Auch in „Wurfchronik Teil 1_page_0028.md“ gefunden → Datensätze zusammengeführt.',
          'Geschwister-Würfe zusammengeführt.',
        ],
      }),
    },
    { id: 'w-fridolin', name: 'Wurf F', date: '2023-05-01', totalBorn: 4, expectedGoHomeDate: null, notes: null, fatherId: 'balu', motherId: 'maja', showInChronicle: true },
    { id: 'w-luna', name: 'Wurf L', date: '2023-08-15', totalBorn: 6, expectedGoHomeDate: null, notes: null, fatherId: 'karlsson', motherId: 'smilla', showInChronicle: true },
    { id: 'w-balu', name: 'Wurf B', date: '2021-04-20', totalBorn: 3, expectedGoHomeDate: null, notes: null, fatherId: 'anton', motherId: 'greta', showInChronicle: true },
    // Anton ist auch Karlssons Vater -> gemeinsamer Vorfahre (Inzucht-Demo)
    { id: 'w-karlsson', name: 'Wurf C', date: '2022-02-02', totalBorn: 5, expectedGoHomeDate: null, notes: null, fatherId: 'anton', motherId: 'frieda', showInChronicle: true },
    { id: 'w-anton', name: 'Wurf A', date: '2019-07-07', totalBorn: 4, expectedGoHomeDate: null, notes: null, fatherId: 'emil', motherId: 'hilde', showInChronicle: true },
    { id: 'w-emil', name: 'Wurf E', date: '2017-03-03', totalBorn: 2, expectedGoHomeDate: null, notes: null, fatherId: 'max', motherId: null, showInChronicle: true },
    // WURFCHRONIK-FILTER: dieser Wurf ist NICHT in der Wurfchronik (showInChronicle: false)
    // -> taucht in der Wurf-Liste nicht auf, aber auf Fridolins Tier-Detailseite (parentLitters) weiterhin.
    { id: 'w-versteckt', name: 'Wurf V', date: '2024-02-02', totalBorn: 2, expectedGoHomeDate: null, notes: null, fatherId: 'fridolin', motherId: 'luna', showInChronicle: false },
  ]

  const enclosures: Enclosure[] = [
    // Reinigung überfällig: letzte Reinigung lange her + Zyklus -> nextCleaningDate in der Vergangenheit.
    {
      id: 'enc-gross',
      name: 'Großbecken',
      notes: null,
      size: '120×50 cm',
      capacity: 6,
      lastCleanedDate: '2020-01-01',
      cleaningCycleDays: 14,
      nextCleaningDate: '2020-01-15',
    },
    // Kein Reinigungszyklus hinterlegt.
    {
      id: 'enc-leer',
      name: 'Quarantänebecken',
      notes: null,
      size: null,
      capacity: null,
      lastCleanedDate: null,
      cleaningCycleDays: null,
      nextCleaningDate: null,
    },
  ]

  // FEAT-13: contactInfo (Freitext) wurde durch strukturierte Felder ersetzt.
  const contacts: Contact[] = [
    {
      id: 'con-meier', name: 'Zoohandlung Meier', email: 'meier@example.de', phone: null, address: 'Hauptstraße 1, 12345 Musterstadt', notes: null, isBreeder: true, isReceiver: true,
      // NACHVERFOLGUNG: Datenherkunft des Kontakts (vom Import erzeugter JSON-String).
      provenance: JSON.stringify({
        sourceFiles: ['Wurfchronik Teil 1_page_0001.md', 'Stammbaum von Krümel.xlsx'],
        mergedRecordCount: 2,
        fromWurfchronik: true,
        notes: ['aus 2 Datensätzen zusammengeführt', 'als Züchter erkannt', 'als Abnehmer erkannt'],
        history: [
          'In „Stammbaum von Krümel.xlsx“ als Züchter erkannt.',
          'Auch in „Wurfchronik Teil 1_page_0001.md“ gefunden → Datensätze zusammengeführt.',
          'Sowohl als Züchter als auch als Abnehmer geführt.',
        ],
      }),
    },
    { id: 'con-huber', name: 'Familie Huber', email: null, phone: '0151 2345678', address: null, notes: null, isBreeder: false, isReceiver: true },
    { id: 'con-frei', name: 'Züchterin Frei', email: null, phone: null, address: null, notes: 'unverknüpft', isBreeder: true, isReceiver: false },
    { id: 'con-neither', name: 'Weder Noch', email: null, phone: null, address: null, notes: 'weder züchter noch abnehmer', isBreeder: false, isReceiver: false },
  ]

  const colorVarieties = [
    { id: 'cv-agouti', name: 'Agouti', canonicalGenotype: 'AA CC DD EE GG PP spsp rere', sortOrder: 1 },
    { id: 'cv-schwarz', name: 'Schwarz', canonicalGenotype: 'aa CC DD EE GG PP spsp rere', sortOrder: 2 },
    { id: 'cv-gold', name: 'Gold', canonicalGenotype: 'AA CC DD EE GG pp spsp rere', sortOrder: 3 },
    { id: 'cv-blau', name: 'Blau', canonicalGenotype: 'aa CC dd EE GG PP spsp rere', sortOrder: 4 },
    { id: 'cv-himalaya', name: 'Himalaya', canonicalGenotype: 'AA chch DD EE GG PP spsp rere', sortOrder: 5 },
    { id: 'cv-schwarz-schecke', name: 'Schwarz Schecke', canonicalGenotype: 'aa CC DD EE GG PP Spsp rere', sortOrder: 6 },
  ]

  const healthRecords: HealthRecordRow[] = [
    {
      id: 'hr-1',
      gerbilId: 'kruemel',
      date: '2026-01-15',
      type: 'Vaccination',
      description: 'Jahresimpfung',
      veterinarian: 'Dr. Vogel',
      createdAt: '2026-01-15T10:00:00Z',
    },
  ]

  const weightRecords: WeightRecordRow[] = [
    { id: 'wr-1', gerbilId: 'kruemel', date: '2026-05-01', weightGrams: 78, notes: null },
    { id: 'wr-2', gerbilId: 'kruemel', date: '2026-05-20', weightGrams: 82, notes: null },
  ]

  // WEB-0b: die 6 Webseiten-Seiten (wie vom Backend geseedet), mit ein paar Blöcken.
  const pages: MockPage[] = [
    {
      id: 'page-start',
      slug: 'start',
      title: 'Startseite',
      seoDescription: 'Willkommen bei unserer Rennmauszucht.',
      status: 'Published',
      blocks: [
        { id: 'blk-start-1', order: 0, type: 'Heading', data: { text: 'Willkommen', level: 2 } },
        { id: 'blk-start-2', order: 1, type: 'RichText', data: { markdown: 'Schön, dass du da bist.' } },
      ],
    },
    { id: 'page-zucht', slug: 'ueber-die-zucht', title: 'Über die Zucht', seoDescription: null, status: 'Draft', blocks: [] },
    {
      id: 'page-abgabe',
      slug: 'abgabetiere',
      title: 'Abgabetiere',
      seoDescription: null,
      status: 'Published',
      blocks: [
        { id: 'blk-abgabe-1', order: 0, type: 'AbgabetiereList', data: { mode: 'auto', intro: 'Diese Tiere suchen ein Zuhause.' } },
      ],
    },
    { id: 'page-bedingungen', slug: 'abgabebedingungen', title: 'Abgabebedingungen', seoDescription: null, status: 'Draft', blocks: [] },
    { id: 'page-farben', slug: 'farben-genetik', title: 'Farben & Genetik', seoDescription: null, status: 'Draft', blocks: [] },
    { id: 'page-kontakt', slug: 'kontakt', title: 'Kontakt', seoDescription: null, status: 'Draft', blocks: [] },
  ]

  // INBOX-1: Anfragen (neueste zuerst nach receivedAt sortierbar)
  const requests: InboxRequest[] = [
    {
      id: 'req-anna',
      gmailMessageId: '<anna-1@mail.example>',
      threadId: 'thr-1',
      fromAddress: 'anna@example.de',
      fromName: 'Anna Albrecht',
      subject: 'Anfrage: Pärchen zur Abgabe?',
      bodyText:
        'Hallo,\n\nich habe euer Inserat gesehen — sind die beiden Agouti-Jungs noch zu haben?\n\nViele Grüße\nAnna',
      receivedAt: '2026-06-05T18:30:00Z',
      status: 'New',
      assignedContactId: null,
      draftReply: null,
      answeredAt: null,
    },
    {
      id: 'req-ben',
      gmailMessageId: '<ben-1@mail.example>',
      threadId: 'thr-2',
      fromAddress: 'ben@example.org',
      fromName: 'Ben Berger',
      subject: 'Frage zur Haltung',
      bodyText: 'Guten Tag, was für ein Becken empfehlt ihr für zwei Rennmäuse?',
      receivedAt: '2026-06-04T09:00:00Z',
      status: 'InProgress',
      assignedContactId: null,
      draftReply: 'Hallo Ben, wir empfehlen mindestens 100×50 cm …',
      answeredAt: null,
    },
    {
      id: 'req-clara',
      gmailMessageId: '<clara-1@mail.example>',
      threadId: null,
      fromAddress: 'clara@example.com',
      fromName: null,
      subject: 'Danke!',
      bodyText: 'Die beiden sind super angekommen — danke nochmal!',
      receivedAt: '2026-06-01T12:00:00Z',
      status: 'Answered',
      assignedContactId: 'con-meier',
      draftReply: null,
      answeredAt: '2026-06-02T08:00:00Z',
    },
  ]

  return {
    gerbils,
    litters,
    enclosures,
    contacts,
    colorVarieties,
    healthRecords,
    weightRecords,
    pages,
    requests,
    aiConfigured: true,
    mailConfigured: true,
    // Ein importierter Vertrag (hasFile:false) prüft die Word-Button-Ausblendung.
    contracts: [
      {
        id: 'contract-import-1',
        contactId: 'con-meier',
        price: 30,
        handoverDate: '2023-09-29',
        contractDate: '2023-09-29',
        fileName: 'Zucht der kleinen Chaoten _ (Krümel) - Zoohandlung Meier_.docx',
        createdAt: '2023-09-29T00:00:00Z',
        gerbilIds: ['kruemel'],
        url: '/contracts/contract-import-1/file',
        hasFile: false,
      },
    ],
    saleAdConfigured: true,
    namesConfigured: true,
    // GEPRÜFTE TIERE: startet leer; die Verify-Specs markieren über POST.
    verified: [],
    // FEEDBACK-TICKETS: ein offenes + ein gelöstes Ticket (GET liefert neueste zuerst →
    // db.feedback wird im Mock umgekehrt; das offene steht hier zuletzt = erscheint oben).
    feedback: [
      {
        id: 'feedback-resolved',
        message: 'Der Stammbaum zeigt den falschen Vater bei Krümel.',
        context: 'stammbaum',
        gerbilId: 'kruemel',
        litterId: null,
        contactId: null,
        entityName: 'Krümel',
        url: 'http://localhost:5173/rennmaeuse/kruemel/stammbaum',
        clientTimestamp: '2026-06-10T09:00:00Z',
        userAgent: null,
        createdAt: '2026-06-10T09:00:00Z',
        status: 'Resolved',
        category: 'Stammbaum',
        resolvedAt: '2026-06-12T14:00:00Z',
        question: null,
        answer: null,
        answeredAt: null,
        // Changelog (laienverständlich) für die geschlossene Ansicht.
        fixNote: 'Der Vater von Krümel war falsch — er ist jetzt Balu. Bitte den Stammbaum neu laden.',
        // INTERN: darf NIE in der Züchterin-UI erscheinen.
        agentContext: 'GEHEIM-AGENT-CONTEXT: motherId via conflict-decisions.json gesetzt, re-ingest.',
        thread: [],
      },
      {
        // Ticket mit offener Rückfrage (NeedsInfo): die Züchterin soll hier antworten können.
        // Hat bereits eine frühere, beantwortete Runde im Verlauf (thread).
        id: 'feedback-needsinfo',
        message: 'Der Wurf B hat ein falsches Geburtsdatum.',
        context: 'litter-detail',
        gerbilId: null,
        litterId: 'wurf-b',
        contactId: null,
        entityName: 'Wurf B',
        url: 'http://localhost:5173/wuerfe/wurf-b',
        clientTimestamp: '2026-06-14T08:00:00Z',
        userAgent: null,
        createdAt: '2026-06-14T08:00:00Z',
        status: 'NeedsInfo',
        resolvedAt: null,
        question:
          'Welches Geburtsdatum ist korrekt — der **1.** oder der **2. Juni**?\n\nBitte wähle:\n- 1. Juni\n- 2. Juni',
        answer: null,
        answeredAt: null,
        fixNote: null,
        agentContext: 'GEHEIM-AGENT-CONTEXT: warte auf DOB-Bestätigung für Wurf B.',
        // Frühere, abgeschlossene Runde (älteste zuerst) — bleibt im Verlauf erhalten.
        thread: [
          { role: 'maintainer', text: 'Wurde der Wurf im Mai oder Juni geboren?', at: '2026-06-13T08:00:00Z' },
          { role: 'breeder', text: 'Im Juni.', at: '2026-06-13T18:00:00Z' },
        ],
      },
      {
        // Beantwortetes Ticket (Answered): die KI hat noch NICHT reagiert. Der Erst-Text ist
        // jetzt gesperrt (kein „Bearbeiten"), nur die neueste Antwort ist noch änderbar.
        id: 'feedback-answered',
        message: 'Bei Karlsson stimmt der Farbschlag nicht.',
        context: 'gerbil-detail',
        gerbilId: 'karlsson',
        litterId: null,
        contactId: null,
        entityName: 'Karlsson',
        url: 'http://localhost:5173/rennmaeuse/karlsson',
        clientTimestamp: '2026-06-16T09:00:00Z',
        userAgent: null,
        createdAt: '2026-06-16T09:00:00Z',
        status: 'Answered',
        resolvedAt: null,
        question: 'Welcher Farbschlag ist korrekt?',
        answer: 'Karlsson ist Blau, nicht Schwarz.',
        answeredAt: '2026-06-16T18:00:00Z',
        fixNote: null,
        agentContext: null,
        thread: [],
      },
      {
        id: 'feedback-open',
        message: 'Das Gewicht wird auf der Verlaufskurve falsch gerundet.',
        context: 'gerbil-detail',
        gerbilId: 'fridolin',
        litterId: null,
        contactId: null,
        entityName: 'Fridolin',
        url: 'http://localhost:5173/rennmaeuse/fridolin',
        clientTimestamp: '2026-06-15T11:30:00Z',
        userAgent: null,
        createdAt: '2026-06-15T11:30:00Z',
        status: 'Open',
        resolvedAt: null,
        question: null,
        answer: null,
        answeredAt: null,
        fixNote: null,
        agentContext: null,
        thread: [],
      },
    ],
    rpro3: {
      analyze: {
        counts: {
          ownAnimals: 303,
          externalRaw: 7427,
          externalAfterDedup: 3391,
          litters: 127,
          contacts: 750,
          genotypes: 7732,
          duplicatesMerged: 4036,
          mergeClusters: 782,
        },
        newVsCurrentNew: 280,
        newVsCurrentExisting: 23,
        topMerges: [
          { name: 'Alice', recordCount: 30, dob: '2010-07-19', farbe: 'Schimmel', origin: 'Clan of Kleine Füchse' },
          { name: 'BlackEye', recordCount: 28, dob: '', farbe: 'Silberschimmel', origin: 'Clan of Desert' },
        ],
        ambiguousNames: [
          {
            name: 'Merlin',
            bareCount: 0,
            variants: [
              { count: 4, dob: '2007-08-22', farbe: 'Blaufuchs', origin: 'Clan of the Yankees', isOwn: false },
              { count: 3, dob: '—', farbe: 'Platin-Schecke', origin: '—', isOwn: false },
            ],
          },
          {
            name: 'Bella',
            bareCount: 0,
            variants: [
              { count: 2, dob: '2012-06-21', farbe: 'Blaufuchs', origin: 'Clan of Sunset Glow', isOwn: false },
              { count: 1, dob: '2013-03-20', farbe: 'Algierfuchs, hell', origin: 'eigene Zucht', isOwn: true },
            ],
          },
        ],
        photosProvided: false,
        photoFilesAvailable: 0,
      },
      execute: {
        gerbilsImported: 3694,
        littersImported: 1678,
        contactsImported: 508,
        healthRecordsImported: 39,
        weightRecordsImported: 229,
        photosImported: 0,
        message: 'Import erfolgreich: 3694 Tiere, 1678 Würfe, 508 Kontakte.',
      },
    },
    acquisitions: [],
    // ABGABE-STATUS: eine reservierte + eine abgegebene + eine verfügbare Vormerkung.
    reservations: [
      {
        id: 'res-reserviert',
        gerbilId: 'sale-balu',
        gerbilName: 'Balu Abgabe',
        status: 'reserviert',
        reservedForContactId: 'con-huber',
        contactName: 'Familie Huber',
        appointmentDate: '2026-07-01T00:00:00Z',
        price: 25,
        note: 'Käfig wird mitgebracht.',
        handedOverDate: null,
        createdAt: '2026-06-15T09:00:00Z',
        updatedAt: '2026-06-15T09:00:00Z',
      },
      {
        id: 'res-abgegeben',
        gerbilId: 'pup-abgabe',
        gerbilName: 'Pippa',
        status: 'abgegeben',
        reservedForContactId: 'con-huber',
        contactName: 'Familie Huber',
        appointmentDate: null,
        price: 20,
        note: null,
        handedOverDate: '2025-05-01T00:00:00Z',
        createdAt: '2025-04-20T09:00:00Z',
        updatedAt: '2025-05-01T09:00:00Z',
      },
      {
        id: 'res-verfuegbar',
        gerbilId: 'sale-benny',
        gerbilName: 'Benny Abgabe',
        status: 'verfuegbar',
        reservedForContactId: null,
        contactName: null,
        appointmentDate: null,
        price: null,
        note: null,
        handedOverDate: null,
        createdAt: '2026-06-16T09:00:00Z',
        updatedAt: '2026-06-16T09:00:00Z',
      },
    ],
    waitingList: [
      {
        id: 'wl-seed-1',
        contactId: contacts[0]?.id ?? null,
        contactName: contacts[0]?.name ?? 'Familie Sonntag',
        wishColor: 'Schwarz',
        wishGender: 'female',
        requestedAt: '2026-05-01T00:00:00Z',
        status: 'offen',
        note: 'möchte zwei Weibchen',
        createdAt: '2026-05-01T00:00:00Z',
      },
      {
        id: 'wl-seed-2',
        contactId: null,
        contactName: 'Herr Maier',
        wishColor: null,
        wishGender: 'male',
        requestedAt: '2026-04-10T00:00:00Z',
        status: 'erfuellt',
        note: null,
        createdAt: '2026-04-10T00:00:00Z',
      },
    ],
    returns: [],
    exhibitions: [],
  }
}
