import React from 'react'
import { render, screen, waitFor } from '../../../../test-utils'
import userEvent from '@testing-library/user-event'
import Dashboard from '../page'
import useDashboard from '../../../../hooks/useDashboard'

// Mock des hooks
jest.mock('../../../../hooks/useDashboard')
jest.mock('../../../../components/auth/ProtectedRoute', () => {
  return function MockProtectedRoute({ children }: { children: React.ReactNode }) {
    return <div data-testid="protected-route">{children}</div>
  }
})

const mockUseDashboard = useDashboard as jest.MockedFunction<typeof useDashboard>

const mockDashboardData = {
  stats: {
    totalChantiers: 12,
    chiffreAffaires: 125000,
    totalClients: 34,
    facturesEnRetard: 3,
  },
  chantiersRecents: [
    {
      id: '1',
      nom: 'Rénovation Bureau',
      client: 'Entreprise ABC',
      statut: 'EN_COURS' as const,
      dateDebut: '2024-01-15',
      montantPrevu: 45000,
    },
    {
      id: '2',
      nom: 'Construction Garage',
      client: 'Client XYZ',
      statut: 'PLANIFIE' as const,
      dateDebut: '2024-02-01',
      montantPrevu: 25000,
    },
  ],
  facturesEnRetard: [
    {
      id: '1',
      numero: 'F2024-001',
      client: 'Client A',
      montant: 5000,
      dateEcheance: '2024-01-01',
    },
  ],
  devisEnAttente: [
    {
      id: '1',
      numero: 'D2024-001',
      client: 'Client B',
      montant: 8000,
      dateCreation: '2024-01-10',
    },
  ],
  loading: false,
  error: null,
  refresh: jest.fn(),
}

describe('Page Dashboard', () => {
  beforeEach(() => {
    jest.clearAllMocks()
    mockUseDashboard.mockReturnValue(mockDashboardData)
  })

  it('devrait afficher le dashboard avec toutes les sections', () => {
    render(<Dashboard />)
    
    expect(screen.getByTestId('protected-route')).toBeInTheDocument()
    expect(screen.getByText('Tableau de Bord BTP Xpress')).toBeInTheDocument()
    expect(screen.getByText('Bienvenue sur votre plateforme de gestion BTP. Voici un aperçu de vos projets en cours.')).toBeInTheDocument()
  })

  it('devrait afficher les cartes de statistiques', () => {
    render(<Dashboard />)
    
    expect(screen.getByText('Projets actifs')).toBeInTheDocument()
    expect(screen.getByText('Budget total')).toBeInTheDocument()
    expect(screen.getByText('Clients')).toBeInTheDocument()
    expect(screen.getByText('Factures impayées')).toBeInTheDocument()
    
    // Vérifier les valeurs
    expect(screen.getByText('12')).toBeInTheDocument()
    expect(screen.getByText('125 000 €')).toBeInTheDocument()
    expect(screen.getByText('34')).toBeInTheDocument()
    expect(screen.getByText('3')).toBeInTheDocument()
  })

  it('devrait afficher les chantiers récents', () => {
    render(<Dashboard />)
    
    expect(screen.getByText('Rénovation Bureau')).toBeInTheDocument()
    expect(screen.getByText('Construction Garage')).toBeInTheDocument()
    expect(screen.getByText('Entreprise ABC')).toBeInTheDocument()
    expect(screen.getByText('Client XYZ')).toBeInTheDocument()
  })

  it('devrait permettre d\'actualiser les données', async () => {
    const user = userEvent.setup()
    const mockRefresh = jest.fn()
    mockUseDashboard.mockReturnValue({
      ...mockDashboardData,
      refresh: mockRefresh,
    })
    
    render(<Dashboard />)
    
    const refreshButton = screen.getByText('Actualiser')
    await user.click(refreshButton)
    
    expect(mockRefresh).toHaveBeenCalledTimes(1)
  })

  it('devrait afficher l\'état de chargement', () => {
    mockUseDashboard.mockReturnValue({
      ...mockDashboardData,
      loading: true,
    })
    
    render(<Dashboard />)
    
    const refreshButton = screen.getByText('Actualiser')
    expect(refreshButton).toHaveAttribute('data-pc-section', 'loadingicon')
  })

  it('devrait afficher les erreurs', () => {
    mockUseDashboard.mockReturnValue({
      ...mockDashboardData,
      error: 'Erreur de connexion au serveur',
    })
    
    render(<Dashboard />)
    
    expect(screen.getByText('Erreur de connexion au serveur')).toBeInTheDocument()
    expect(screen.getByText('Réessayer')).toBeInTheDocument()
  })

  it('devrait permettre de réessayer après une erreur', async () => {
    const user = userEvent.setup()
    const mockRefresh = jest.fn()
    mockUseDashboard.mockReturnValue({
      ...mockDashboardData,
      error: 'Erreur de connexion',
      refresh: mockRefresh,
    })
    
    render(<Dashboard />)
    
    const retryButton = screen.getByText('Réessayer')
    await user.click(retryButton)
    
    expect(mockRefresh).toHaveBeenCalledTimes(1)
  })

  it('devrait afficher les valeurs par défaut quand les stats sont vides', () => {
    mockUseDashboard.mockReturnValue({
      ...mockDashboardData,
      stats: null,
    })
    
    render(<Dashboard />)
    
    // Vérifier que les valeurs par défaut (0) sont affichées
    expect(screen.getByText('0')).toBeInTheDocument()
  })

  it('devrait afficher les icônes correctes pour chaque statistique', () => {
    render(<Dashboard />)
    
    expect(document.querySelector('.pi-building')).toBeInTheDocument()
    expect(document.querySelector('.pi-euro')).toBeInTheDocument()
    expect(document.querySelector('.pi-users')).toBeInTheDocument()
    expect(document.querySelector('.pi-exclamation-triangle')).toBeInTheDocument()
  })

  it('devrait afficher les tendances sur les cartes', () => {
    render(<Dashboard />)
    
    // Vérifier que les tendances sont affichées
    expect(screen.getByText('+12%')).toBeInTheDocument()
    expect(screen.getByText('+8%')).toBeInTheDocument()
    expect(screen.getByText('+15%')).toBeInTheDocument()
    expect(screen.getByText('-5%')).toBeInTheDocument()
  })

  it('devrait avoir une mise en page responsive', () => {
    const { container } = render(<Dashboard />)
    
    // Vérifier la structure en grille
    expect(container.querySelector('.grid')).toBeInTheDocument()
    expect(container.querySelector('.col-12')).toBeInTheDocument()
    expect(container.querySelector('.col-12.md\\:col-3')).toBeInTheDocument()
    expect(container.querySelector('.col-12.md\\:col-8')).toBeInTheDocument()
    expect(container.querySelector('.col-12.md\\:col-4')).toBeInTheDocument()
  })

  it('devrait gérer les actions sur les chantiers', () => {
    // Spy sur console.log pour vérifier les handlers
    const consoleSpy = jest.spyOn(console, 'log').mockImplementation()
    
    render(<Dashboard />)
    
    // Les handlers sont appelés dans le composant mais pas directement testables
    // On peut vérifier leur présence dans le code
    expect(consoleSpy).not.toHaveBeenCalled()
    
    consoleSpy.mockRestore()
  })

  it('devrait utiliser le ProtectedRoute avec les bonnes permissions', () => {
    render(<Dashboard />)
    
    // Vérifier que le composant est wrappé dans ProtectedRoute
    expect(screen.getByTestId('protected-route')).toBeInTheDocument()
  })

  it('devrait afficher un toast après actualisation', async () => {
    const user = userEvent.setup()
    render(<Dashboard />)
    
    const refreshButton = screen.getByText('Actualiser')
    await user.click(refreshButton)
    
    // Le toast est géré par PrimeReact, on vérifie juste que la fonction est appelée
    await waitFor(() => {
      expect(mockDashboardData.refresh).toHaveBeenCalled()
    })
  })

  it('devrait formater correctement les montants', () => {
    render(<Dashboard />)
    
    // Vérifier que le chiffre d'affaires est formaté
    expect(screen.getByText('125 000 €')).toBeInTheDocument()
  })
})