import { describe, it, expect, beforeAll, afterAll, afterEach, vi } from 'vitest'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { MemoryRouter } from 'react-router-dom'
import { ResetPasswordModal } from '../../../features/users/components/ResetPasswordModal'
import { useAuthStore } from '../../../stores/authStore'

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

const adminUser = {
  id: 1, username: 'admin', nombre: 'Admin', rol: 'admin',
  permisos: ['administracion:usuarios:gestionar'],
  mustChangePassword: false,
}

const server = setupServer()

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

function renderModal(userId = 5) {
  useAuthStore.setState({ user: adminUser })
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } })
  return render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>
        <ResetPasswordModal userId={userId} />
      </MemoryRouter>
    </QueryClientProvider>,
  )
}

describe('ResetPasswordModal', () => {
  it('shows trigger button and modal closed by default', () => {
    renderModal()
    expect(screen.getByRole('button', { name: /resetear|reset.*contraseña/i })).toBeInTheDocument()
    expect(screen.queryByText(/confirmar|advertencia|única vez/i)).not.toBeInTheDocument()
  })

  it('trigger button → modal opens with confirmation', async () => {
    renderModal()

    await userEvent.click(screen.getByRole('button', { name: /resetear contraseña/i }))

    // Modal should now show the confirm button
    expect(screen.getByRole('button', { name: /confirmar/i })).toBeInTheDocument()
    expect(screen.getByRole('button', { name: /cancelar/i })).toBeInTheDocument()
  })

  it('cancel → modal closes without HTTP call', async () => {
    let httpCalled = false
    server.use(
      http.post(`${API_URL}/api/v1/users/5/password/reset`, () => {
        httpCalled = true
        return HttpResponse.json({ tempPassword: 'Ax!k9mQ3@rT2', mustChangeOnLogin: true })
      }),
    )

    renderModal()

    await userEvent.click(screen.getByRole('button', { name: /resetear|reset.*contraseña/i }))
    await userEvent.click(screen.getByRole('button', { name: /cancelar|cancel/i }))

    await new Promise((r) => setTimeout(r, 100))
    expect(httpCalled).toBe(false)
    expect(screen.queryByText(/contraseña temporal|tempPassword/i)).not.toBeInTheDocument()
  })

  it('confirm → calls POST and shows tempPassword + warning', async () => {
    server.use(
      http.post(`${API_URL}/api/v1/users/5/password/reset`, () =>
        HttpResponse.json({ tempPassword: 'Ax!k9mQ3@rT2', mustChangeOnLogin: true }),
      ),
    )

    renderModal()

    await userEvent.click(screen.getByRole('button', { name: /resetear|reset.*contraseña/i }))
    await userEvent.click(screen.getByRole('button', { name: /confirmar|confirm/i }))

    await waitFor(() => expect(screen.getByText('Ax!k9mQ3@rT2')).toBeInTheDocument())
    expect(screen.getByText(/única vez|solo una vez|this is the only time/i)).toBeInTheDocument()
  })

  it('copy button calls clipboard.writeText with tempPassword', async () => {
    const clipboardWriteText = vi.fn().mockResolvedValue(undefined)
    Object.defineProperty(navigator, 'clipboard', {
      value: { writeText: clipboardWriteText },
      writable: true,
    })

    server.use(
      http.post(`${API_URL}/api/v1/users/5/password/reset`, () =>
        HttpResponse.json({ tempPassword: 'Ax!k9mQ3@rT2', mustChangeOnLogin: true }),
      ),
    )

    renderModal()

    await userEvent.click(screen.getByRole('button', { name: /resetear|reset.*contraseña/i }))
    await userEvent.click(screen.getByRole('button', { name: /confirmar|confirm/i }))

    await waitFor(() => expect(screen.getByText('Ax!k9mQ3@rT2')).toBeInTheDocument())

    await userEvent.click(screen.getByRole('button', { name: /copiar|copy/i }))

    expect(clipboardWriteText).toHaveBeenCalledWith('Ax!k9mQ3@rT2')
  })
})
