/**
 * E2E-Test fuer den Founding-Wizard
 *
 * Prueft den vollstaendigen 8-Step-Flow:
 *  - Application-Errors / Console-Errors auf jeder Seite
 *  - StepBasics: Prefill-Button + Registergericht/HRB-Felder
 *  - StepGesellschafter: Rollen-Dropdown + IP-Bereiche fuer 2 Gruender
 *  - Per-Person Generation: 2 IP-Assignment-Dokumente
 *  - localStorage-Persistenz
 *
 * Backend wird per route.fulfill() gemockt — Test ist hermetisch.
 */

import { test, expect, type Page, type ConsoleMessage } from '@playwright/test'

const BASE = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:3002'
const WIZARD_PATH = '/sdk/founding-wizard'

/** Filtert Browser-Console auf echte App-Errors (ignoriert Next.js / Hydration / 3rd-party Warnings). */
function isRealAppError(msg: ConsoleMessage): boolean {
  if (msg.type() !== 'error') return false
  const text = msg.text()
  // Bekanntes Rauschen ausschliessen
  const ignored = [
    'Failed to load resource',           // 404 fuer Icons etc.
    'Download the React DevTools',       // React-Hinweis
    'net::ERR_',                          // Netzwerk (gemockt → erwartete Misses)
    'Hydration failed because',           // Next 15 Pseudo-Errors bei dev
    '[founding-wizard] prefill failed',   // Intentional UX-Logging im Prefill-Fehlerpfad
  ]
  return !ignored.some(p => text.includes(p))
}

const IGNORED_PAGE_ERRORS = [
  // Hydration mismatches durch dynamische Zeitstempel ("Gerade eben" vs "vor 1 Min")
  // im SDK-Header — pure dev-Mode-Symptom, kein App-Bug.
  'Hydration failed because the server rendered text didn',
  'There was an error while hydrating',
  // Next.js dev-mode signals fuer Hydration-Issues
  'Text content does not match server-rendered HTML',
]

function isIgnoredPageError(err: Error): boolean {
  return IGNORED_PAGE_ERRORS.some(p => err.message.includes(p))
}

/** Setzt Console-Error- und PageError-Listener. Wirft am Ende, wenn welche aufgetreten sind. */
function installErrorTraps(page: Page): { assertNoErrors: () => void } {
  const consoleErrors: string[] = []
  const pageErrors: string[] = []

  page.on('console', msg => {
    if (isRealAppError(msg)) consoleErrors.push(msg.text())
  })
  page.on('pageerror', err => {
    if (!isIgnoredPageError(err)) pageErrors.push(`${err.name}: ${err.message}`)
  })

  return {
    assertNoErrors() {
      const all = [...pageErrors.map(e => `[pageerror] ${e}`), ...consoleErrors.map(e => `[console.error] ${e}`)]
      if (all.length > 0) {
        throw new Error(`Application-Errors waehrend des Flows:\n${all.join('\n')}`)
      }
    },
  }
}

/** Mockt die zwei API-Endpoints, die der Wizard aufruft. */
async function mockBackend(page: Page) {
  // 1) Company-Profile Prefill
  await page.route('**/api/sdk/v1/company-profile**', async route => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        profile: {
          companyName: 'Breakpilot GmbH',
          legalForm: 'GmbH',
          industry: ['Software', 'KI/ML'],
          businessModel: 'SaaS',
          offerings: ['SaaS-Plattform', 'Compliance-API'],
          headquartersStreet: 'Königstraße 1',
          headquartersZip: '70173',
          headquartersCity: 'Stuttgart',
        },
      }),
    })
  })

  // 2) Founding-Wizard Generate (gibt 9 Dokumente zurueck: 7 normale + 2 per-person IP-Assignments)
  await page.route('**/api/v1/founding-wizard/generate', async route => {
    const request = route.request()
    const body = JSON.parse(request.postData() || '{}')
    const selected: string[] = body.selected_documents || []
    const gesellschafter: Array<{ name?: string; is_geschaeftsfuehrer?: boolean }> = body.gesellschafter || []

    const PER_PERSON = ['ip_assignment_agreement', 'managing_director_employment_contract']
    const docs: unknown[] = []
    const tinyDocx = 'UEsDBBQAAAAIAA==' // gueltige base64-Stub (Playwright braucht keinen echten DOCX)

    for (const docType of selected) {
      if (PER_PERSON.includes(docType)) {
        const persons = docType === 'managing_director_employment_contract'
          ? gesellschafter.filter(g => g.is_geschaeftsfuehrer)
          : gesellschafter
        for (const p of persons) {
          docs.push({
            document_type: docType,
            title: `${docType} — ${p.name}`,
            filename: `${docType}_${(p.name || 'X').replace(/\s/g, '_')}.docx`,
            download_url: `data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,${tinyDocx}`,
            size_bytes: 12345,
            generated_at: '2026-05-21T12:00:00Z',
          })
        }
      } else {
        docs.push({
          document_type: docType,
          title: docType,
          filename: `${docType}.docx`,
          download_url: `data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,${tinyDocx}`,
          size_bytes: 12345,
          generated_at: '2026-05-21T12:00:00Z',
        })
      }
    }

    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ documents: docs, warnings: [] }),
    })
  })
}

/** Clears wizard-state and pre-accepts cookies so the CookieBannerOverlay
 *  does not intercept clicks during the test. */
async function resetWizardState(page: Page) {
  await page.addInitScript(() => {
    try {
      window.localStorage.removeItem('breakpilot:founding-wizard:state:v1')
      // CookieBannerOverlay liest 'bp-sdk-cookie-consent' und blendet sich aus,
      // sobald ein Eintrag existiert. Wir setzen Minimal-Consent.
      window.localStorage.setItem('bp-sdk-cookie-consent', JSON.stringify({
        necessary: true, statistics: false, marketing: false, functional: false,
        ewrOnly: false, blockedVendors: [], timestamp: new Date().toISOString(),
      }))
    } catch {}
  })
}

test.describe('Founding-Wizard E2E', () => {
  test.beforeEach(async ({ page }) => {
    await resetWizardState(page)
    await mockBackend(page)
  })

  test('vollstaendiger 8-Step-Flow ohne Application-Errors', async ({ page }) => {
    const errors = installErrorTraps(page)

    await page.goto(`${BASE}${WIZARD_PATH}`)
    await expect(page.getByTestId('founding-wizard')).toBeVisible()
    await expect(page.getByTestId('step-content-1')).toBeVisible()

    // --- Step 1: Basics + Prefill ---
    await page.getByRole('button', { name: /Aus Unternehmensprofil vorbef/i }).click()
    await expect(page.getByTestId('company-name')).toHaveValue('Breakpilot GmbH', { timeout: 5000 })
    await expect(page.getByTestId('company-seat')).toHaveValue('Stuttgart')

    // Pflichtfeld: company_purpose_description (mind. 10 Zeichen)
    await page.getByTestId('company-purpose').fill(
      'die Entwicklung, Bereitstellung und der Betrieb von KI-gestuetzten Compliance-Werkzeugen sowie damit verbundener Beratungsleistungen.'
    )

    // Neue Felder: Registergericht + HRB
    await page.getByTestId('register-court').fill('Amtsgericht Stuttgart')
    await page.getByTestId('hrb-number').fill('')  // noch nicht eingetragen

    await page.getByTestId('next-step').click()

    // --- Step 2: Gesellschafter ---
    await expect(page.getByTestId('step-content-2')).toBeVisible()

    // Benjamin (CEO, IP: Compliance + RAG)
    await page.getByTestId('gs-name').fill('Benjamin Bönisch')
    await page.getByTestId('gs-birthdate').fill('1985-01-15')
    await page.getByTestId('gs-address').fill('Teststraße 1, 70173 Stuttgart')
    await page.getByTestId('gs-email').fill('benjamin@breakpilot.ai')
    await page.getByTestId('gs-nennbetrag').fill('12500')
    await page.getByTestId('gs-role').selectOption('CEO')
    await page.getByTestId('gs-ip-areas').fill(
      'Compliance-Engine (Quellcode + Architektur)\nRAG-Pipeline\nProdukt-Konzepte'
    )
    await page.getByTestId('add-gesellschafter').click()
    await expect(page.getByTestId('gs-row-1')).toBeVisible()

    // Sharang (CTO, IP: Security + Infrastruktur)
    await page.getByTestId('gs-name').fill('Sharang Parnerkar')
    await page.getByTestId('gs-birthdate').fill('1990-06-20')
    await page.getByTestId('gs-address').fill('Teststraße 2, 70173 Stuttgart')
    await page.getByTestId('gs-email').fill('sharang@breakpilot.ai')
    await page.getByTestId('gs-nennbetrag').fill('12500')
    await page.getByTestId('gs-role').selectOption('CTO')
    await page.getByTestId('gs-ip-areas').fill('Security-Modul\nInfrastructure-as-Code')
    await page.getByTestId('add-gesellschafter').click()
    await expect(page.getByTestId('gs-row-2')).toBeVisible()

    // Summe Nennbetraege muss Stammkapital entsprechen (25.000)
    await expect(page.getByTestId('gs-total')).toContainText('25.000')

    await page.getByTestId('next-step').click()

    // --- Step 3: GF-Assignment (Defaults sind ok, beide bereits GF) ---
    await expect(page.getByTestId('step-content-3')).toBeVisible()
    await expect(page.getByTestId('gf-assignment-table')).toBeVisible()
    await page.getByTestId('next-step').click()

    // --- Step 4: Kapital (Defaults: 25000) ---
    await expect(page.getByTestId('step-content-4')).toBeVisible()
    await expect(page.getByTestId('stammkapital')).toHaveValue('25000')
    await page.getByTestId('next-step').click()

    // --- Step 5: Notar ---
    await expect(page.getByTestId('step-content-5')).toBeVisible()
    await page.getByTestId('notary-name').fill('Dr. Max Mustermann')
    await page.getByTestId('notary-place').fill('Stuttgart')
    await page.getByTestId('notary-address').fill('Königstraße 99, 70173 Stuttgart')
    await page.getByTestId('notarial-date').fill('2026-06-15')
    await page.getByTestId('next-step').click()

    // --- Step 6: SHA-Optionen (Defaults sind ok) ---
    await expect(page.getByTestId('step-content-6')).toBeVisible()
    await expect(page.getByTestId('has-sha')).toBeChecked()
    await page.getByTestId('next-step').click()

    // --- Step 7: GF-Vertraege (fuer jeden GF einen) ---
    await expect(page.getByTestId('step-content-7')).toBeVisible()
    // Beide GF-Contract-Karten muessen sichtbar sein
    const contractCards = page.locator('[data-testid^="contract-"]')
    await expect(contractCards).toHaveCount(2)
    // Salary in beiden Cards anfassen → registriert Contracts (canProceed-Bedingung).
    // Wir setzen einen anderen Wert als Default (84000) damit React onChange feuert.
    const salaryInputs = page.locator('[data-testid^="salary-"]')
    const salaryCount = await salaryInputs.count()
    for (let i = 0; i < salaryCount; i++) {
      await salaryInputs.nth(i).fill('90000')
    }
    // Warten bis "Weiter" enabled ist
    await expect(page.getByTestId('next-step')).toBeEnabled()
    await page.getByTestId('next-step').click()

    // --- Step 8: Generate ---
    await expect(page.getByTestId('step-content-8')).toBeVisible()
    await expect(page.getByTestId('generate-summary')).toContainText('Breakpilot GmbH')
    await expect(page.getByTestId('generate-summary')).toContainText('2', { useInnerText: true })

    // Notartermin-Bundle auswaehlen
    await page.getByTestId('select-notary-bundle').click()

    // Generieren (Backend gemockt)
    await page.getByTestId('generate-docs').click()

    // Generated-Docs-Block muss erscheinen
    await expect(page.getByTestId('generated-docs')).toBeVisible({ timeout: 10000 })

    // Per-Person Verifikation: zwei IP-Assignment-Downloads erwartet
    const ipDownloads = page.locator('[data-testid="download-ip_assignment_agreement"]')
    await expect(ipDownloads).toHaveCount(2)

    // Per-Person Verifikation: zwei GF-Vertraege erwartet
    const gfDownloads = page.locator('[data-testid="download-managing_director_employment_contract"]')
    await expect(gfDownloads).toHaveCount(2)

    // Kein generate-error sichtbar
    await expect(page.getByTestId('generate-error')).toBeHidden()

    // Final: keine Errors auf der Konsole
    errors.assertNoErrors()
  })

  test('Prefill-Button setzt Fehler bei Backend-Fehler ohne Application-Error', async ({ page }) => {
    // Spezial-Mock: company-profile gibt 500 zurueck
    await page.route('**/api/sdk/v1/company-profile**', async route => {
      await route.fulfill({ status: 500, body: 'boom' })
    })

    const errors = installErrorTraps(page)
    await page.goto(`${BASE}${WIZARD_PATH}`)

    await page.getByRole('button', { name: /Aus Unternehmensprofil vorbef/i }).click()
    // UI muss Fehlermeldung anzeigen, NICHT crashen
    await expect(page.getByText('Konnte Unternehmensprofil nicht laden')).toBeVisible()

    errors.assertNoErrors()
  })

  test('Step-Navigation: Zurueck und Reset funktionieren ohne Errors', async ({ page }) => {
    const errors = installErrorTraps(page)
    await page.goto(`${BASE}${WIZARD_PATH}`)

    // Minimum Step 1 fuellen
    await page.getByTestId('company-name').fill('Breakpilot GmbH')
    await page.getByTestId('company-seat').fill('Stuttgart')
    await page.getByTestId('company-purpose').fill('die Entwicklung von Compliance-Software fuer Unternehmen.')

    await page.getByTestId('next-step').click()
    await expect(page.getByTestId('step-content-2')).toBeVisible()

    // Zurueck
    await page.getByTestId('prev-step').click()
    await expect(page.getByTestId('step-content-1')).toBeVisible()

    // Eingaben muessen erhalten geblieben sein (localStorage-persistence)
    await expect(page.getByTestId('company-name')).toHaveValue('Breakpilot GmbH')

    // Reset (mit Dialog-Bestaetigung)
    page.once('dialog', dialog => dialog.accept())
    await page.getByTestId('reset-wizard').click()
    await expect(page.getByTestId('company-name')).toHaveValue('')

    errors.assertNoErrors()
  })

  test('IP-Areas + Rollen-Dropdown in Step 2', async ({ page }) => {
    const errors = installErrorTraps(page)
    await page.goto(`${BASE}${WIZARD_PATH}`)

    // Step 1 zuegig fuellen
    await page.getByTestId('company-name').fill('Breakpilot GmbH')
    await page.getByTestId('company-seat').fill('Stuttgart')
    await page.getByTestId('company-purpose').fill('die Entwicklung von Compliance-Software fuer Unternehmen.')
    await page.getByTestId('next-step').click()

    // Rollen-Dropdown muss ein <select> sein, nicht <input>
    const role = page.getByTestId('gs-role')
    await expect(role).toHaveJSProperty('tagName', 'SELECT')

    // CEO-Option waehlbar
    await page.getByTestId('gs-name').fill('Benjamin Bönisch')
    await page.getByTestId('gs-address').fill('Test 1')
    await page.getByTestId('gs-nennbetrag').fill('25000')
    await role.selectOption('CEO')
    await page.getByTestId('gs-ip-areas').fill('Compliance-Engine\nRAG-Pipeline')
    await page.getByTestId('add-gesellschafter').click()

    // Tabelle muss IP-Bereiche anzeigen
    const row = page.getByTestId('gs-row-1')
    await expect(row).toContainText('Benjamin Bönisch')
    await expect(row).toContainText('CEO')
    await expect(row).toContainText('Compliance-Engine')

    errors.assertNoErrors()
  })
})
