// multi-qaf-context.ts tests (QVS-P4, KAR-973, gap-analysis G5, ux-flow.md §4,
// Review-Fix 1: evidence-scoped variant binding).
//
// FIXTURE-DATEN-REGEL: every id/name/number below is FREE INVENTION.
//
// deserializeMultiQafContainer is mocked (not exercised for real here) —
// its own serialization round-trip is already covered by
// lib/qaf-differences/internal/multi-qaf/__tests__/*; this file isolates
// loadMultiQafVariantContext's OWN logic (query shape, degraded-vs-null
// distinction, selectedVariantId resolution, profile-binding-scoped variant
// summary derivation).

import { describe, it, expect, vi, beforeEach } from 'vitest'
import type { VariantDefinition, VariantProfileBinding } from '@/lib/qaf-differences'

const { deserializeMock } = vi.hoisted(() => ({ deserializeMock: vi.fn() }))
vi.mock('@/lib/qaf-differences', () => ({ deserializeMultiQafContainer: deserializeMock }))

import { loadMultiQafVariantContext } from '../multi-qaf-context'

function makeVariant(overrides: Partial<VariantDefinition> = {}): VariantDefinition {
  return {
    stableInternalId: 'slot-1',
    originalColumn: 'Q',
    originalColumnIndex: 17,
    originalVariantNumber: '1',
    originalLabels: ['EU-Variante'],
    normalizedLabels: ['eu-variante'],
    compositeCanonicalKey: 'region=eu',
    dimensions: {},
    annualVolume: 1000,
    peakVolume: 1200,
    lifetimeVolume: null,
    currency: 'EUR',
    activeState: 'active',
    sourceReferences: [],
    confidence: 0.8,
    ...overrides,
  }
}

function makeBinding(overrides: Partial<VariantProfileBinding> = {}): VariantProfileBinding {
  return {
    variantId: 'slot-1',
    profileId: 'profile-1',
    bindingEvidence: { kind: 'cellReference', source: null, detail: 'test fixture' },
    ...overrides,
  }
}

interface MockOpts {
  comparisonRows?: Array<{ id: string; comparison_file_id: string | null; engine_version: unknown }>
  comparisonError?: unknown
  fileRow?: { g60_meta: unknown } | null
  fileError?: unknown
}

function makeSupabase(opts: MockOpts) {
  return {
    from: vi.fn((table: string) => {
      if (table === 'qaf_comparison') {
        return {
          select: vi.fn(() => ({
            eq: vi.fn(() => ({
              eq: vi.fn(() => ({
                order: vi.fn(() => ({
                  limit: vi.fn(() => Promise.resolve({ data: opts.comparisonRows ?? [], error: opts.comparisonError ?? null })),
                })),
              })),
            })),
          })),
        }
      }
      if (table === 'qaf_file') {
        return {
          select: vi.fn(() => ({
            eq: vi.fn(() => ({
              maybeSingle: vi.fn(() => Promise.resolve({ data: opts.fileRow ?? null, error: opts.fileError ?? null })),
            })),
          })),
        }
      }
      throw new Error(`unexpected table queried: ${table}`)
    }),
  }
}

const CONTAINER_FILE_ROW = { g60_meta: { multiQafContainer: { modelVersion: 1, container: {} } } }

beforeEach(() => {
  deserializeMock.mockReset()
})

describe('loadMultiQafVariantContext', () => {
  it('returns null when this file is not the alt/baseline side of any multi_qaf_variant_vs_standard comparison', async () => {
    const supabase = makeSupabase({ comparisonRows: [] })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toBeNull()
  })

  it('degrades (never null) when the qaf_comparison query itself fails', async () => {
    const supabase = makeSupabase({ comparisonError: { message: 'boom', code: '500' } })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({ variants: [], degraded: true, sharedProfileConfirmed: false })
  })

  // Review-Fix 1: engine_version.selectedVariantId is now read — a
  // comparison row matching this query but missing it is structurally
  // unexpected and must fail closed, never silently proceed as "all variants".
  it('degrades when the comparison row carries no engine_version.selectedVariantId', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: {} }],
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({ variants: [], degraded: true, sharedProfileConfirmed: false })
    expect(deserializeMock).not.toHaveBeenCalled()
  })

  it('degrades when a matching comparison exists but its container file query fails', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileError: { message: 'boom', code: '500' },
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({ variants: [], degraded: true, sharedProfileConfirmed: false })
  })

  it('degrades when the comparison exists but the container file carries no multiQafContainer payload', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: { g60_meta: {} },
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({ variants: [], degraded: true, sharedProfileConfirmed: false })
    expect(deserializeMock).not.toHaveBeenCalled()
  })

  it('degrades when deserializeMultiQafContainer throws (corrupt/unsupported envelope)', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockImplementation(() => {
      throw new Error('Unsupported Multi-QAF container modelVersion')
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({ variants: [], degraded: true, sharedProfileConfirmed: false })
  })

  // Review-Fix 1: a selectedVariantId that does not resolve to a real active
  // variant in the (possibly since-changed) container must fail closed too —
  // never silently render an empty/wrong list.
  it('degrades when selectedVariantId does not resolve to any activeVariant in the container', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-999' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockReturnValue({ activeVariants: [makeVariant({ stableInternalId: 'slot-1' })], variantProfileBindings: [] })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({ variants: [], degraded: true, sharedProfileConfirmed: false })
  })

  it('passes the WHOLE {modelVersion, container} envelope (not just .container) to deserializeMultiQafContainer', async () => {
    const envelope = { modelVersion: 1, container: { activeVariants: [] } }
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: { g60_meta: { multiQafContainer: envelope } },
    })
    deserializeMock.mockReturnValue({ activeVariants: [], variantProfileBindings: [] })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(deserializeMock).toHaveBeenCalledWith(JSON.stringify(envelope))
  })

  // ── Review-Fix 1: the core evidence-scoping behavior ──────────────────────

  it('returns ONLY the compared variant when it has zero variantProfileBindings entries (bindings missing/empty)', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockReturnValue({
      activeVariants: [
        makeVariant({ stableInternalId: 'slot-1', compositeCanonicalKey: 'region=eu', originalLabels: ['EU'] }),
        makeVariant({ stableInternalId: 'slot-2', compositeCanonicalKey: 'region=us', originalLabels: ['US'] }),
      ],
      variantProfileBindings: [],
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result).toEqual({
      variants: [{ variantKey: 'region=eu', label: 'EU', volume: 1000 }],
      degraded: false,
      sharedProfileConfirmed: false,
    })
  })

  it('returns ONLY the compared variant when the container carries no variantProfileBindings field at all', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockReturnValue({
      activeVariants: [makeVariant({ stableInternalId: 'slot-1', compositeCanonicalKey: 'region=eu', originalLabels: ['EU'] })],
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result?.sharedProfileConfirmed).toBe(false)
    expect(result?.variants).toEqual([{ variantKey: 'region=eu', label: 'EU', volume: 1000 }])
  })

  it('includes another active variant ONLY when it is bound to the SAME profileId as the compared variant', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockReturnValue({
      activeVariants: [
        makeVariant({ stableInternalId: 'slot-1', compositeCanonicalKey: 'region=eu', originalLabels: ['EU'] }),
        makeVariant({ stableInternalId: 'slot-2', compositeCanonicalKey: 'region=de', originalLabels: ['DE'] }), // same profile
        makeVariant({ stableInternalId: 'slot-3', compositeCanonicalKey: 'region=us', originalLabels: ['US'] }), // different profile
        makeVariant({ stableInternalId: 'slot-4', compositeCanonicalKey: 'region=cn', originalLabels: ['CN'] }), // no binding at all
      ],
      variantProfileBindings: [
        makeBinding({ variantId: 'slot-1', profileId: 'manufacturing-profile-a' }),
        makeBinding({ variantId: 'slot-2', profileId: 'manufacturing-profile-a' }),
        makeBinding({ variantId: 'slot-3', profileId: 'manufacturing-profile-b' }),
      ],
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result?.sharedProfileConfirmed).toBe(true)
    expect(result?.variants).toEqual([
      { variantKey: 'region=eu', label: 'EU', volume: 1000 },
      { variantKey: 'region=de', label: 'DE', volume: 1000 },
    ])
  })

  it('never includes an inactive/reserved variant even if it happens to share a profileId (activeVariants-only)', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-1' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockReturnValue({
      activeVariants: [makeVariant({ stableInternalId: 'slot-1', compositeCanonicalKey: 'region=eu', originalLabels: ['EU'] })],
      inactiveVariants: [makeVariant({ stableInternalId: 'slot-9', compositeCanonicalKey: 'region=zz', originalLabels: ['ZZ'] })],
      variantProfileBindings: [
        makeBinding({ variantId: 'slot-1', profileId: 'p1' }),
        makeBinding({ variantId: 'slot-9', profileId: 'p1' }),
      ],
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result?.variants).toEqual([{ variantKey: 'region=eu', label: 'EU', volume: 1000 }])
  })

  it('falls back to stableInternalId as the variantKey when compositeCanonicalKey is the empty-string sentinel', async () => {
    const supabase = makeSupabase({
      comparisonRows: [{ id: 'cmp-1', comparison_file_id: 'container-file-1', engine_version: { selectedVariantId: 'slot-3' } }],
      fileRow: CONTAINER_FILE_ROW,
    })
    deserializeMock.mockReturnValue({
      activeVariants: [
        makeVariant({
          compositeCanonicalKey: '',
          stableInternalId: 'slot-3',
          originalLabels: [],
          originalVariantNumber: null,
          annualVolume: null,
        }),
      ],
      variantProfileBindings: [],
    })
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const result = await loadMultiQafVariantContext(supabase as any, 'file-1')
    expect(result?.variants).toEqual([{ variantKey: 'slot-3', label: 'slot-3', volume: 1200 }])
  })
})
