// @vitest-environment jsdom
//
// KAR-985 additions (bottom of this file): prefill from persisted
// user_inputs, debounced save-callback, and the "Gespeichert" indicator for
// Section 12 "Hochrechnung & Potenzial in €"'s autosave wiring. The
// pre-existing pure-function tests above are unchanged.

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
import QafProjection, { formatMEur, updateYearRow, addYearRow, prependYearRow, removeYearRow } from '../qaf-projection'

const VALID_UUID = '11111111-1111-4111-8111-111111111111'

const saveMock = vi.fn()
vi.mock('@/app/qaf-differences/qaf-comparison-user-inputs-actions', () => ({
  saveQafComparisonUserInputs: (...args: unknown[]) => saveMock(...args),
}))

async function flush() {
  await Promise.resolve()
  await Promise.resolve()
}

describe('QafProjection — formatMEur', () => {
  it('formats totals in millions like V11 (0,00 M€)', () => {
    expect(formatMEur(0, 'EUR')).toBe('0,00 M€')
    expect(formatMEur(36900, 'EUR')).toBe('0,04 M€')
    expect(formatMEur(-1234567, 'EUR')).toBe('-1,23 M€')
  })

  it('falls back to the raw code for unknown currencies', () => {
    expect(formatMEur(1000000, 'XYZ')).toBe('1,00 Mio. XYZ')
  })
})

describe('QafProjection — year-row state helpers', () => {
  const rows = [
    { year: 2026, volume: 0, included: true },
    { year: 2027, volume: 100, included: true },
  ]

  it('updates a single row immutably', () => {
    const next = updateYearRow(rows, 1, { volume: 500 })
    expect(next[1].volume).toBe(500)
    expect(rows[1].volume).toBe(100)
    expect(next[0]).toBe(rows[0])
  })

  it('appends the next consecutive year', () => {
    const next = addYearRow(rows)
    expect(next).toHaveLength(3)
    expect(next[2]).toEqual({ year: 2028, volume: 0, included: true })
  })

  it('starts from the fallback year when the list is empty', () => {
    expect(addYearRow([], 2026)[0].year).toBe(2026)
  })
})

describe('prependYearRow / removeYearRow (KAR-842 C)', () => {
  const rows = [
    { year: 2026, volume: 10, included: true },
    { year: 2027, volume: 20, included: true },
  ]

  it('prepends the previous year', () => {
    const out = prependYearRow(rows)
    expect(out[0]).toEqual({ year: 2025, volume: 0, included: true })
    expect(out).toHaveLength(3)
  })

  it('uses the fallback year on an empty list', () => {
    expect(prependYearRow([], 2031)[0].year).toBe(2031)
  })

  it('removes exactly the indexed row', () => {
    const out = removeYearRow(rows, 0)
    expect(out).toEqual([{ year: 2027, volume: 20, included: true }])
  })

  it('ignores out-of-range indices', () => {
    expect(removeYearRow(rows, 5)).toHaveLength(2)
  })
})

describe('QafProjection — KAR-985 autosave', () => {
  beforeEach(() => {
    vi.useFakeTimers()
    saveMock.mockReset()
    saveMock.mockResolvedValue({ ok: true, data: null })
  })

  afterEach(() => {
    cleanup()
    vi.useRealTimers()
  })

  it('prefills years/Δ-override/Abwehrquote from initialUserInputs — taking priority over initialYears (G60 prefill)', () => {
    render(
      <QafProjection
        deltaComputed={10}
        currency="EUR"
        comparisonId={VALID_UUID}
        initialYears={[{ year: 2020, volume: 1, included: true }]}
        initialUserInputs={{ years: [{ year: 2030, volume: 555, included: true }], overrideDelta: 2.5, defendPct: 0.4 }}
      />,
    )
    expect(screen.getByText('2030')).toBeTruthy()
    expect(screen.queryByText('2020')).toBeNull()
    expect((screen.getByLabelText('Volumen 2030') as HTMLInputElement).value).toBe('555')
    expect((screen.getByLabelText('Mehrkosten je Einheit') as HTMLInputElement).value).toBe('2.5')
    expect((document.querySelector('input[type="range"]') as HTMLInputElement).value).toBe('40')
  })

  it('starts from initialYears (unchanged pre-KAR-985 behavior) when nothing was saved yet', () => {
    render(
      <QafProjection
        deltaComputed={10}
        currency="EUR"
        comparisonId={VALID_UUID}
        initialYears={[{ year: 2020, volume: 1, included: true }]}
        initialUserInputs={null}
      />,
    )
    expect(screen.getByText('2020')).toBeTruthy()
  })

  it('debounced-saves the projection namespace after a change (Δ-override commit)', async () => {
    render(<QafProjection deltaComputed={10} currency="EUR" comparisonId={VALID_UUID} initialUserInputs={null} />)
    fireEvent.change(screen.getByLabelText('Mehrkosten je Einheit'), { target: { value: '3.25' } })

    await act(async () => {
      vi.advanceTimersByTime(799)
    })
    expect(saveMock).not.toHaveBeenCalled()

    await act(async () => {
      vi.advanceTimersByTime(1)
      await flush()
    })
    expect(saveMock).toHaveBeenCalledTimes(1)
    const [comparisonId, patch] = saveMock.mock.calls[0]
    expect(comparisonId).toBe(VALID_UUID)
    expect(patch.projection.overrideDelta).toBe(3.25)
    expect(patch.projection.defendPct).toBe(0)
  })

  it('shows the "Gespeichert" indicator after a successful autosave', async () => {
    render(<QafProjection deltaComputed={10} currency="EUR" comparisonId={VALID_UUID} initialUserInputs={null} />)
    fireEvent.change(screen.getByLabelText('Mehrkosten je Einheit'), { target: { value: '9' } })
    await act(async () => {
      vi.advanceTimersByTime(800)
      await flush()
    })
    expect(screen.getByText('Gespeichert')).toBeTruthy()
  })

  it('never autosaves without a comparisonId (qaf-g60-detail.tsx usage stays session-only)', async () => {
    render(<QafProjection deltaComputed={10} currency="EUR" initialUserInputs={null} />)
    fireEvent.change(screen.getByLabelText('Mehrkosten je Einheit'), { target: { value: '9' } })
    await act(async () => {
      vi.advanceTimersByTime(2000)
      await flush()
    })
    expect(saveMock).not.toHaveBeenCalled()
    expect(screen.queryByText('Gespeichert')).toBeNull()
  })
})
