import { describe, it, expect } from 'vitest'
import { waitFor, act } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { server } from '@/test/mocks/server'
import { renderHookWithProviders } from '@/test/utils'
import {
  mockDisclosureRequest,
  mockDisclosureApproved,
} from '@/test/mocks/data'
import { useDisclosures, useReviewDisclosure } from '@/hooks/useDisclosures'

// ---------------------------------------------------------------------------
// useDisclosures
// ---------------------------------------------------------------------------

describe('useDisclosures', () => {
  it('fetches disclosures with status filter (success)', async () => {
    let capturedStatus: string | null = null

    server.use(
      http.get('/api/admin/disclosure-requests', ({ request }) => {
        const url = new URL(request.url)
        capturedStatus = url.searchParams.get('status')
        return HttpResponse.json([mockDisclosureRequest])
      }),
    )

    const { result } = renderHookWithProviders(() => useDisclosures('pending'))

    await waitFor(() => expect(result.current.isSuccess).toBe(true))

    expect(capturedStatus).toBe('pending')
    expect(result.current.data).toEqual([mockDisclosureRequest])
    expect(result.current.data).toHaveLength(1)
    expect(result.current.data![0].status).toBe('pending')
  })

  it('handles empty list', async () => {
    server.use(
      http.get('/api/admin/disclosure-requests', () => {
        return HttpResponse.json([])
      }),
    )

    const { result } = renderHookWithProviders(() => useDisclosures('pending'))

    await waitFor(() => expect(result.current.isSuccess).toBe(true))

    expect(result.current.data).toEqual([])
    expect(result.current.data).toHaveLength(0)
  })

  it('works without status parameter (returns all)', async () => {
    let capturedStatus: string | null = null

    server.use(
      http.get('/api/admin/disclosure-requests', ({ request }) => {
        const url = new URL(request.url)
        capturedStatus = url.searchParams.get('status')
        return HttpResponse.json([mockDisclosureRequest])
      }),
    )

    const { result } = renderHookWithProviders(() => useDisclosures())

    await waitFor(() => expect(result.current.isSuccess).toBe(true))

    expect(capturedStatus).toBeNull()
    expect(result.current.data).toHaveLength(1)
  })
})

// ---------------------------------------------------------------------------
// useReviewDisclosure
// ---------------------------------------------------------------------------

describe('useReviewDisclosure', () => {
  it('approves a disclosure (mutation success)', async () => {
    server.use(
      http.put('/api/admin/disclosure-requests/:id', () => {
        return HttpResponse.json(mockDisclosureApproved)
      }),
    )

    const { result } = renderHookWithProviders(() => useReviewDisclosure())

    let response: unknown
    await act(async () => {
      response = await result.current.mutateAsync({ id: 1, status: 'approved' })
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))

    expect((response as { status: string }).status).toBe('approved')
    expect((response as { reviewed_by: number }).reviewed_by).toBe(1)
  })

  it('rejects a disclosure', async () => {
    const rejectedDisclosure = {
      ...mockDisclosureRequest,
      status: 'rejected' as const,
      reviewed_by: 1,
      reviewed_at: '2026-02-26T09:30:00Z',
    }

    server.use(
      http.put('/api/admin/disclosure-requests/:id', () => {
        return HttpResponse.json(rejectedDisclosure)
      }),
    )

    const { result } = renderHookWithProviders(() => useReviewDisclosure())

    let response: unknown
    await act(async () => {
      response = await result.current.mutateAsync({ id: 1, status: 'rejected' })
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))

    expect((response as { status: string }).status).toBe('rejected')
  })

  it('handles error', async () => {
    server.use(
      http.put('/api/admin/disclosure-requests/:id', () => {
        return HttpResponse.json(
          { detail: 'Not found' },
          { status: 404 },
        )
      }),
    )

    const { result } = renderHookWithProviders(() => useReviewDisclosure())

    await act(async () => {
      try {
        await result.current.mutateAsync({ id: 999, status: 'approved' })
      } catch {
        // expected
      }
    })

    await waitFor(() => expect(result.current.isError).toBe(true))
  })
})
