/** FEEDBACK: "Fehler melden" Dialog + Stammbaum-Rechtsklick ("ID kopieren" / "Fehler melden"). */
import { de, expect, skipUnlessMock, test } from './fixtures'

const f = de.feedback
const st = de.pages.stammbaum

test('Tierakte: "Fehler melden"-Button öffnet den Dialog, Senden zeigt Erfolg', async ({ page, mockDb }) => {
  skipUnlessMock()
  await page.goto('/rennmaeuse/kruemel')

  // Button in den Aktionen öffnet den Dialog.
  await page.getByRole('button', { name: f.button }).click()
  const dialog = page.getByRole('dialog', { name: f.dialogTitle })
  await expect(dialog).toBeVisible()

  // Debug-Kontext ist sichtbar (automatisch erfasst).
  await expect(dialog).toContainText(f.debugTitle)
  await expect(dialog).toContainText(f.contexts['gerbil-detail'])

  // Beschreibung eintragen + senden.
  await dialog.getByLabel(f.label).fill('Der Farbschlag stimmt nicht.')
  await dialog.getByRole('button', { name: f.submit }).click()

  // Erfolgs-Toast + Dialog schließt.
  await expect(page.getByText(f.success)).toBeVisible()
  await expect(dialog).not.toBeVisible()

  // Der Bericht wurde mit Debug-Kontext gespeichert (zuletzt eingereichter Eintrag;
  // die Mock-DB ist mit Beispiel-Tickets vorbefüllt).
  expect(mockDb).not.toBeNull()
  const report = mockDb!.feedback.find((r) => r.message === 'Der Farbschlag stimmt nicht.')
  expect(report).toMatchObject({
    message: 'Der Farbschlag stimmt nicht.',
    context: 'gerbil-detail',
    gerbilId: 'kruemel',
  })
  expect(report!.url).toContain('/rennmaeuse/kruemel')
  expect(typeof report!.clientTimestamp).toBe('string')
})

test('Entwurf bleibt nach Schließen + Navigation + Wiederöffnen erhalten', async ({ page }) => {
  skipUnlessMock()
  // Auf einer Tier-Seite anfangen zu schreiben …
  await page.goto('/rennmaeuse/kruemel')
  await page.getByRole('button', { name: f.button }).click()
  const dialog = page.getByRole('dialog', { name: f.dialogTitle })
  await dialog.getByLabel(f.label).fill('Halb fertiger Text, will kurz was nachschauen …')

  // … Fenster (versehentlich) schließen …
  await dialog.getByRole('button', { name: f.close }).click()
  await expect(dialog).not.toBeVisible()

  // … in der App woanders hin navigieren (anderer Kontext) …
  await page.goto('/wuerfe/w-kruemel')

  // … „Fehler melden" erneut öffnen: der Text ist noch da.
  await page.getByRole('button', { name: f.button }).click()
  const dialog2 = page.getByRole('dialog', { name: f.dialogTitle })
  await expect(dialog2.getByLabel(f.label)).toHaveValue('Halb fertiger Text, will kurz was nachschauen …')
})

test('Wurf-Ansicht: "Fehler melden"-Button öffnet den Dialog und sendet mit Wurf-Kontext', async ({ page, mockDb }) => {
  skipUnlessMock()
  await page.goto('/wuerfe/w-kruemel')

  await page.getByRole('button', { name: f.button }).click()
  const dialog = page.getByRole('dialog', { name: f.dialogTitle })
  await expect(dialog).toBeVisible()
  await expect(dialog).toContainText(f.contexts['litter-detail'])

  await dialog.getByLabel(f.label).fill('Die Wurfstärke ist falsch.')
  await dialog.getByRole('button', { name: f.submit }).click()
  await expect(page.getByText(f.success)).toBeVisible()

  const report = mockDb!.feedback.find((r) => r.message === 'Die Wurfstärke ist falsch.')
  expect(report).toMatchObject({ context: 'litter-detail', litterId: 'w-kruemel' })
})

test('Kontakt-Detail: "Fehler melden"-Button sendet mit Kontakt-Kontext', async ({ page, mockDb }) => {
  skipUnlessMock()
  await page.goto('/kontakte/con-meier')

  await page.getByRole('button', { name: f.button }).click()
  const dialog = page.getByRole('dialog', { name: f.dialogTitle })
  await expect(dialog).toBeVisible()
  await expect(dialog).toContainText(f.contexts['contact-detail'])

  await dialog.getByLabel(f.label).fill('Die Adresse stimmt nicht.')
  await dialog.getByRole('button', { name: f.submit }).click()
  await expect(page.getByText(f.success)).toBeVisible()

  const report = mockDb!.feedback.find((r) => r.message === 'Die Adresse stimmt nicht.')
  expect(report).toMatchObject({ context: 'contact-detail', contactId: 'con-meier' })
})

test('Stammbaum: Rechtsklick auf eine Karte zeigt "ID kopieren" + "Fehler melden"', async ({ page, mockDb }) => {
  skipUnlessMock()
  await page.goto('/rennmaeuse/kruemel/stammbaum')
  await expect(page.locator('.pedigree-card').first()).toBeVisible()

  // Rechtsklick auf die Wurzelkarte (Krümel).
  await page.locator('.pedigree-card--root').click({ button: 'right' })

  const menu = page.locator('.stammbaum-context-menu')
  await expect(menu).toBeVisible()
  await expect(menu.getByRole('menuitem', { name: st.contextMenu.copyId })).toBeVisible()
  await expect(menu.getByRole('menuitem', { name: st.contextMenu.reportError })).toBeVisible()

  // "Fehler melden" öffnet den Dialog mit Stammbaum-Kontext.
  await menu.getByRole('menuitem', { name: st.contextMenu.reportError }).click()
  const dialog = page.getByRole('dialog', { name: f.dialogTitle })
  await expect(dialog).toBeVisible()
  await expect(dialog).toContainText(f.contexts.stammbaum)

  await dialog.getByLabel(f.label).fill('Stammbaum-Bug.')
  await dialog.getByRole('button', { name: f.submit }).click()
  await expect(page.getByText(f.success)).toBeVisible()

  const report = mockDb!.feedback.find((r) => r.message === 'Stammbaum-Bug.')
  expect(report).toMatchObject({ context: 'stammbaum', gerbilId: 'kruemel' })
})

test('Stammbaum: langer Druck (Long-Press) öffnet dasselbe Kontextmenü', async ({ page }, testInfo) => {
  skipUnlessMock()
  // Der Long-Press-Code-Pfad (onTouchStart → Timer → Menü) ist projekt-unabhängig
  // identisch; im Touch-emulierten phone-Projekt ist das Auslösen eines
  // synthetischen TouchEvents unzuverlässig, daher hier auf das desktop-Projekt
  // beschränkt (validiert dieselbe Logik).
  testInfo.skip(testInfo.project.name === 'phone', 'synthetischer Long-Press im phone-Projekt instabil')
  await page.goto('/rennmaeuse/kruemel/stammbaum')
  const card = page.locator('.pedigree-card--root')
  await expect(card).toBeVisible()

  // Long-Press simulieren: echtes touchstart (mit Touch-Objekt) auslösen; der
  // Timer im PedigreeCard öffnet nach ~500 ms das Menü.
  const dispatched = await card.evaluate((el) => {
    if (typeof Touch === 'undefined' || typeof TouchEvent === 'undefined') return false
    const r = el.getBoundingClientRect()
    const t = new Touch({ identifier: 1, target: el, clientX: r.left + 10, clientY: r.top + 10 })
    el.dispatchEvent(
      new TouchEvent('touchstart', { bubbles: true, cancelable: true, touches: [t], targetTouches: [t], changedTouches: [t] }),
    )
    return true
  })
  test.skip(!dispatched, 'TouchEvent in diesem Projekt nicht verfügbar')
  await expect(page.locator('.stammbaum-context-menu')).toBeVisible({ timeout: 2000 })
  await expect(
    page.locator('.stammbaum-context-menu').getByRole('menuitem', { name: st.contextMenu.copyId }),
  ).toBeVisible()
})
