/**
 * Tests de ConfirmInvitePage — flujo de invitación resiliente a email scanners.
 * El token NO se consume al montar: solo cuando el usuario hace click en el botón.
 */
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import React from 'react'

// ─── Referencias mutables para controlar los mocks entre tests ────────────────

const { mockVerifyOtp, mockNavigate, searchRef } = vi.hoisted(() => ({
  mockVerifyOtp: vi.fn(),
  mockNavigate: vi.fn(),
  searchRef: { current: { token_hash: 'valid-hash-abc123', type: 'invite' } as Record<string, string> },
}))

vi.mock('@/lib/supabase', () => ({
  supabase: {
    auth: {
      verifyOtp: mockVerifyOtp,
    },
  },
}))

vi.mock('@tanstack/react-router', () => ({
  useNavigate: () => mockNavigate,
  useSearch: () => searchRef.current,
  Link: ({ children, to, className }: { children: React.ReactNode; to: string; className?: string }) => (
    <a href={to} className={className}>{children}</a>
  ),
}))

// Importar después de los mocks
import { ConfirmInvitePage } from '@/features/auth/ConfirmInvitePage'

// ─── Tests ────────────────────────────────────────────────────────────────────

describe('ConfirmInvitePage', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    searchRef.current = { token_hash: 'valid-hash-abc123', type: 'invite' }
    mockVerifyOtp.mockResolvedValue({ data: {}, error: null })
  })

  it('1. renderiza el botón "Confirmar acceso" sin llamar a verifyOtp al montar', () => {
    render(<ConfirmInvitePage />)

    expect(screen.getByRole('button', { name: /confirmar acceso/i })).toBeInTheDocument()
    expect(mockVerifyOtp).not.toHaveBeenCalled()
  })

  it('2. token_hash vacío muestra estado de error directamente (sin botón de confirmación)', () => {
    searchRef.current = { token_hash: '', type: 'invite' }
    render(<ConfirmInvitePage />)

    expect(screen.queryByRole('button', { name: /confirmar acceso/i })).not.toBeInTheDocument()
    expect(screen.getByText(/link de invitación no es válido o ya fue utilizado/i)).toBeInTheDocument()
    expect(screen.getByRole('link', { name: /ir al login/i })).toBeInTheDocument()
    expect(mockVerifyOtp).not.toHaveBeenCalled()
  })

  it('3. type distinto de "invite" muestra error directamente', () => {
    searchRef.current = { token_hash: 'some-hash', type: 'recovery' }
    render(<ConfirmInvitePage />)

    expect(screen.queryByRole('button', { name: /confirmar acceso/i })).not.toBeInTheDocument()
    expect(screen.getByText(/link de invitación no es válido o ya fue utilizado/i)).toBeInTheDocument()
    expect(mockVerifyOtp).not.toHaveBeenCalled()
  })

  it('4. click en el botón llama verifyOtp con el token_hash y type correctos', async () => {
    render(<ConfirmInvitePage />)

    fireEvent.click(screen.getByRole('button', { name: /confirmar acceso/i }))

    await waitFor(() => {
      expect(mockVerifyOtp).toHaveBeenCalledOnce()
      expect(mockVerifyOtp).toHaveBeenCalledWith({
        type: 'invite',
        token_hash: 'valid-hash-abc123',
      })
    })
  })

  it('5. verifyOtp exitoso navega a /reset-password', async () => {
    mockVerifyOtp.mockResolvedValue({ data: {}, error: null })
    render(<ConfirmInvitePage />)

    fireEvent.click(screen.getByRole('button', { name: /confirmar acceso/i }))

    await waitFor(() => {
      expect(mockNavigate).toHaveBeenCalledWith({ to: '/reset-password' })
    })
    expect(screen.queryByText(/link de invitación no es válido/i)).not.toBeInTheDocument()
  })

  it('6. verifyOtp con error muestra mensaje de error y no navega', async () => {
    mockVerifyOtp.mockResolvedValue({ data: null, error: { message: 'Token has expired or already used' } })
    render(<ConfirmInvitePage />)

    fireEvent.click(screen.getByRole('button', { name: /confirmar acceso/i }))

    await waitFor(() => {
      expect(screen.getByText(/link de invitación no es válido o ya fue utilizado/i)).toBeInTheDocument()
    })
    expect(screen.getByText(/Token has expired or already used/i)).toBeInTheDocument()
    expect(mockNavigate).not.toHaveBeenCalled()
    expect(screen.getByRole('link', { name: /ir al login/i })).toBeInTheDocument()
  })
})
