import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { renderHook, act } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import type { ReactNode } from 'react'

import { PLAN_QUERY_KEY } from '@/entities/user/query-keys'
import { useUpgradeSuccessHandler } from '../useUpgradeSuccessHandler'

let invalidateSpy: ReturnType<typeof vi.fn>
let queryClient: QueryClient

function wrapper({ children }: { children: ReactNode }) {
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
}

function setLocation(search: string) {
  window.history.replaceState(null, '', `/dashboard${search}`)
}

beforeEach(() => {
  queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  })
  invalidateSpy = vi.fn().mockResolvedValue(undefined)
  // Spy sur la méthode invalidateQueries pour vérifier la clé exacte.
  queryClient.invalidateQueries = invalidateSpy as unknown as typeof queryClient.invalidateQueries
})

afterEach(() => {
  setLocation('')
})

describe('useUpgradeSuccessHandler', () => {
  it('?upgrade=success → showSuccess=true, invalidate(PLAN_QUERY_KEY) appelé, URL nettoyée', () => {
    setLocation('?upgrade=success')

    const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })

    expect(result.current.showSuccess).toBe(true)
    expect(invalidateSpy).toHaveBeenCalledTimes(1)
    expect(invalidateSpy).toHaveBeenCalledWith({ queryKey: PLAN_QUERY_KEY })
    // URL nettoyée : plus de `upgrade` dans la query string.
    expect(window.location.search).toBe('')
  })

  it('absence de query param → showSuccess=false, invalidate non appelé', () => {
    setLocation('')

    const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })

    expect(result.current.showSuccess).toBe(false)
    expect(invalidateSpy).not.toHaveBeenCalled()
  })

  it("?upgrade=cancelled (autre valeur) → showSuccess=false, pas d'action", () => {
    setLocation('?upgrade=cancelled')

    const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })

    expect(result.current.showSuccess).toBe(false)
    expect(invalidateSpy).not.toHaveBeenCalled()
    // URL conservée intacte (autre valeur, hors scope du nettoyage).
    expect(window.location.search).toBe('?upgrade=cancelled')
  })

  it('dismiss() bascule showSuccess à false', () => {
    setLocation('?upgrade=success')

    const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })
    expect(result.current.showSuccess).toBe(true)

    act(() => {
      result.current.dismiss()
    })
    expect(result.current.showSuccess).toBe(false)
  })

  it('conserve les autres query params (utm_*, etc.) lors du nettoyage', () => {
    setLocation('?upgrade=success&utm_source=email&ref=abc')

    renderHook(() => useUpgradeSuccessHandler(), { wrapper })

    const params = new URLSearchParams(window.location.search)
    expect(params.has('upgrade')).toBe(false)
    expect(params.get('utm_source')).toBe('email')
    expect(params.get('ref')).toBe('abc')
  })
})
