import { describe, it, expect, beforeEach, vi } from 'vitest'
import { renderHook, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useSourceStore } from '../../providers/sources/store'
import type { AllExternalSources } from '../../providers/sources/types'
import { useFormula } from '../formula'

/**
 * Regression: previously `getModelQueryOptions` hardcoded
 * `sourceIndex = 0, totalSources = 1`, so any multi-source hook call with
 * an array `column` (one entry per source) would either return the wrong
 * slice (always index 0) or throw an array-length validation error from
 * `resolvePropertyForSource`. Now `createModel` threads `index` and
 * `sourcesArray.length` through `buildQuery`.
 */
describe('createModel multi-source path', () => {
  beforeEach(() => {
    useSourceStore.setState({ sources: {}, filters: {} })
  })

  it('resolves array column per-source and runs one fetch per source', async () => {
    useSourceStore.getState().setSource<AllExternalSources>('src_a', {
      type: 'query',
      data: 'SELECT 1',
      connectionName: 'conn',
      apiBaseUrl: 'http://api',
    })
    useSourceStore.getState().setSource<AllExternalSources>('src_b', {
      type: 'query',
      data: 'SELECT 2',
      connectionName: 'conn',
      apiBaseUrl: 'http://api',
    })

    const seenColumns: string[] = []
    const formulaSpy = vi.fn((params: { column?: string }) => {
      const col = params.column ?? ''
      seenColumns.push(col)
      return Promise.resolve({ value: col === 'col_a' ? 1 : 2 })
    })

    const stateA = useSourceStore.getState().sources.src_a
    const stateB = useSourceStore.getState().sources.src_b
    if (stateA?.widgets) {
      ;(
        stateA.widgets as unknown as { getFormula: typeof formulaSpy }
      ).getFormula = formulaSpy
    }
    if (stateB?.widgets) {
      ;(
        stateB.widgets as unknown as { getFormula: typeof formulaSpy }
      ).getFormula = formulaSpy
    }

    const queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false, staleTime: Infinity } },
    })
    const wrapper = ({ children }: { children: React.ReactNode }) => (
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    )

    const { result } = renderHook(
      () =>
        useFormula({
          accessToken: 'tok',
          sourcesId: ['src_a', 'src_b'],
          widgetProps: { column: ['col_a', 'col_b'], operation: 'sum' },
        }),
      { wrapper },
    )

    await waitFor(() => {
      expect(result.current.data).toEqual([{ value: 1 }, { value: 2 }])
    })

    expect(formulaSpy).toHaveBeenCalledTimes(2)
    expect(seenColumns.sort()).toEqual(['col_a', 'col_b'])
  })

  it('throws when the array column length does not match the number of sources', () => {
    useSourceStore.getState().setSource<AllExternalSources>('src_a', {
      type: 'query',
      data: 'SELECT 1',
      connectionName: 'conn',
      apiBaseUrl: 'http://api',
    })

    const queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false, staleTime: Infinity } },
    })
    const wrapper = ({ children }: { children: React.ReactNode }) => (
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    )

    expect(() =>
      renderHook(
        () =>
          useFormula({
            accessToken: 'tok',
            sourcesId: ['src_a'],
            widgetProps: { column: ['col_a', 'col_b'], operation: 'sum' },
          }),
        { wrapper },
      ),
    ).toThrow(/column array length \(2\) must match sources length \(1\)/i)
  })
})
