import { describe, it, expect } from 'vitest'
import { waitFor } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { server } from '@/test/mocks/server'
import { renderHookWithProviders } from '@/test/utils'
import { mockAuditLogEntry } from '@/test/mocks/data'
import { useAuditLog } from '@/hooks/useAuditLog'
import type { AuditLogFilters } from '@/hooks/useAuditLog'

describe('useAuditLog', () => {
  const defaultFilters: AuditLogFilters = { skip: 0, limit: 50 }

  it('fetches audit log entries (success)', async () => {
    const { result } = renderHookWithProviders(() => useAuditLog(defaultFilters))

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

    expect(result.current.data).toEqual([mockAuditLogEntry])
    expect(result.current.data).toHaveLength(1)
    expect(result.current.data![0].action).toBe('case.update')
  })

  it('passes filter parameters (user_id, action, date_from, date_to, skip, limit)', async () => {
    const capturedParams: Record<string, string | null> = {}

    server.use(
      http.get('/api/admin/audit-log', ({ request }) => {
        const url = new URL(request.url)
        capturedParams.skip = url.searchParams.get('skip')
        capturedParams.limit = url.searchParams.get('limit')
        capturedParams.user_id = url.searchParams.get('user_id')
        capturedParams.action = url.searchParams.get('action')
        capturedParams.date_from = url.searchParams.get('date_from')
        capturedParams.date_to = url.searchParams.get('date_to')
        return HttpResponse.json([mockAuditLogEntry])
      }),
    )

    const filters: AuditLogFilters = {
      skip: 10,
      limit: 25,
      user_id: '1',
      action: 'case.update',
      date_from: '2026-02-01',
      date_to: '2026-02-28',
    }

    const { result } = renderHookWithProviders(() => useAuditLog(filters))

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

    expect(capturedParams.skip).toBe('10')
    expect(capturedParams.limit).toBe('25')
    expect(capturedParams.user_id).toBe('1')
    expect(capturedParams.action).toBe('case.update')
    expect(capturedParams.date_from).toBe('2026-02-01')
    expect(capturedParams.date_to).toBe('2026-02-28')
  })

  it('does not send optional params when they are undefined', async () => {
    const capturedParams: Record<string, string | null> = {}

    server.use(
      http.get('/api/admin/audit-log', ({ request }) => {
        const url = new URL(request.url)
        capturedParams.skip = url.searchParams.get('skip')
        capturedParams.limit = url.searchParams.get('limit')
        capturedParams.user_id = url.searchParams.get('user_id')
        capturedParams.action = url.searchParams.get('action')
        capturedParams.date_from = url.searchParams.get('date_from')
        capturedParams.date_to = url.searchParams.get('date_to')
        return HttpResponse.json([])
      }),
    )

    const { result } = renderHookWithProviders(() => useAuditLog(defaultFilters))

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

    expect(capturedParams.skip).toBe('0')
    expect(capturedParams.limit).toBe('50')
    expect(capturedParams.user_id).toBeNull()
    expect(capturedParams.action).toBeNull()
    expect(capturedParams.date_from).toBeNull()
    expect(capturedParams.date_to).toBeNull()
  })

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

    const { result } = renderHookWithProviders(() => useAuditLog(defaultFilters))

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

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

  it('handles server error (500)', async () => {
    server.use(
      http.get('/api/admin/audit-log', () => {
        return new HttpResponse(null, { status: 500 })
      }),
    )

    const { result } = renderHookWithProviders(() => useAuditLog(defaultFilters))

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

    expect(result.current.data).toBeUndefined()
  })
})
