import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'
import { renderHook, act, waitFor } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { createElement } from 'react'
import { useCreateUser } from '../../../features/users/hooks/useCreateUser'

const API_URL = 'http://localhost:5000'

const mockCreatedUser = {
  id: 42,
  username: 'jdoe',
  nombre: 'Juan',
  apellido: 'Doe',
  email: 'jdoe@example.com',
  rol: 'vendedor',
  activo: true,
}

const server = setupServer()

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

function makeWrapper() {
  const queryClient = new QueryClient({
    defaultOptions: { mutations: { retry: false } },
  })
  return ({ children }: { children: React.ReactNode }) =>
    createElement(QueryClientProvider, { client: queryClient }, children)
}

describe('useCreateUser', () => {
  it('mutation succeeds (201) and resolves with created user', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/users`, async () => {
        return HttpResponse.json(mockCreatedUser, { status: 201 })
      }),
    )

    const { result } = renderHook(() => useCreateUser(), { wrapper: makeWrapper() })

    act(() => {
      result.current.mutate({
        username: 'jdoe',
        password: 'Secret1234',
        nombre: 'Juan',
        apellido: 'Doe',
        email: 'jdoe@example.com',
        rol: 'vendedor',
      })
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data).toEqual(mockCreatedUser)
  })

  it('mutation fails with 409 username_taken', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/users`, async () => {
        return HttpResponse.json(
          { error: 'username_taken', message: 'El usuario ya existe' },
          { status: 409 },
        )
      }),
    )

    const { result } = renderHook(() => useCreateUser(), { wrapper: makeWrapper() })

    act(() => {
      result.current.mutate({
        username: 'existing',
        password: 'Secret1234',
        nombre: 'Juan',
        apellido: 'Doe',
        rol: 'vendedor',
      })
    })

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

  it('mutation fails with 400 validation error', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/users`, async () => {
        return HttpResponse.json(
          { errors: { username: ['Username is required'] } },
          { status: 400 },
        )
      }),
    )

    const { result } = renderHook(() => useCreateUser(), { wrapper: makeWrapper() })

    act(() => {
      result.current.mutate({
        username: '',
        password: 'Secret1234',
        nombre: 'Juan',
        apellido: 'Doe',
        rol: 'vendedor',
      })
    })

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