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 React from 'react'
import { useLogin } from '../../../features/auth/hooks/useLogin'
import { useAuthStore } from '../../../stores/authStore'

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

const mockLoginResponseWithPermisos = {
  accessToken: 'eyJhbGciOiJSUzI1NiJ9.payload.sig',
  refreshToken: 'refresh-token-abc',
  expiresIn: 3600,
  usuario: {
    id: 1,
    username: 'admin',
    nombre: 'Admin Sistema',
    rol: 'admin',
    permisos: ['administracion:usuarios:gestionar', 'administracion:roles:gestionar'],
    mustChangePassword: false,
  },
}

const mockLoginResponseEmptyPermisos = {
  accessToken: 'eyJhbGciOiJSUzI1NiJ9.payload.sig',
  refreshToken: 'refresh-token-abc',
  expiresIn: 3600,
  usuario: {
    id: 2,
    username: 'cajero',
    nombre: 'Cajero Test',
    rol: 'cajero',
    permisos: [],
    mustChangePassword: false,
  },
}

const mockLoginResponseMustChange = {
  accessToken: 'eyJhbGciOiJSUzI1NiJ9.payload.sig',
  refreshToken: 'refresh-token-abc',
  expiresIn: 3600,
  usuario: {
    id: 3,
    username: 'newuser',
    nombre: 'New User',
    rol: 'cajero',
    permisos: [],
    mustChangePassword: true,
  },
}

const server = setupServer()

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

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

describe('useLogin — permisos propagation', () => {
  it('F-login-01: response con permisos → store.user.permisos poblado', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/auth/login`, () =>
        HttpResponse.json(mockLoginResponseWithPermisos, { status: 200 }),
      ),
    )

    const { result } = renderHook(() => useLogin(), { wrapper: createWrapper() })

    act(() => {
      result.current.mutate({ username: 'admin', password: 'password' })
    })

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

    const state = useAuthStore.getState()
    expect(state.user?.permisos).toContain('administracion:usuarios:gestionar')
    expect(state.user?.permisos).toContain('administracion:roles:gestionar')
    expect(state.user?.permisos).toHaveLength(2)
  })

  it('F-login-02: response con permisos vacíos → store.user.permisos = []', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/auth/login`, () =>
        HttpResponse.json(mockLoginResponseEmptyPermisos, { status: 200 }),
      ),
    )

    const { result } = renderHook(() => useLogin(), { wrapper: createWrapper() })

    act(() => {
      result.current.mutate({ username: 'cajero', password: 'password' })
    })

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

    const state = useAuthStore.getState()
    expect(state.user?.permisos).toEqual([])
    expect(state.user?.permisos).not.toBeNull()
  })
})

describe('useLogin — mustChangePassword propagation', () => {
  it('F-login-03: persists mustChangePassword=false from login response', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/auth/login`, () =>
        HttpResponse.json(mockLoginResponseWithPermisos, { status: 200 }),
      ),
    )

    const { result } = renderHook(() => useLogin(), { wrapper: createWrapper() })

    act(() => {
      result.current.mutate({ username: 'admin', password: 'password' })
    })

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

    const state = useAuthStore.getState()
    expect(state.user?.mustChangePassword).toBe(false)
  })

  it('F-login-04: persists mustChangePassword=true from login response', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/auth/login`, () =>
        HttpResponse.json(mockLoginResponseMustChange, { status: 200 }),
      ),
    )

    const { result } = renderHook(() => useLogin(), { wrapper: createWrapper() })

    act(() => {
      result.current.mutate({ username: 'newuser', password: 'password' })
    })

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

    const state = useAuthStore.getState()
    expect(state.user?.mustChangePassword).toBe(true)
    expect(state.user?.username).toBe('newuser')
  })
})
