import { describe, it, expect, beforeEach, vi } from 'vitest'
import { screen, waitFor } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { server } from '@/test/mocks/server'
import { renderWithProviders } from '@/test/utils'
import { DashboardPage } from '@/pages/DashboardPage'

// Recharts ResponsiveContainer needs ResizeObserver as a proper constructor
class ResizeObserverStub {
  observe() {}
  unobserve() {}
  disconnect() {}
}
vi.stubGlobal('ResizeObserver', ResizeObserverStub)

// Mock recharts to avoid SVG rendering issues in jsdom
// We render a simplified version that outputs the data as text
vi.mock('recharts', async () => {
  const actual = await vi.importActual<typeof import('recharts')>('recharts')
  return {
    ...actual,
    ResponsiveContainer: ({ children }: { children: React.ReactNode }) => (
      <div data-testid="responsive-container">{children}</div>
    ),
    PieChart: ({ children }: { children: React.ReactNode }) => (
      <div data-testid="pie-chart">{children}</div>
    ),
    BarChart: ({ children }: { children: React.ReactNode }) => (
      <div data-testid="bar-chart">{children}</div>
    ),
    Pie: ({ data }: { data?: Array<{ name: string; value: number }> }) => (
      <div data-testid="pie">
        {data?.map((entry) => (
          <span key={entry.name}>{entry.name}</span>
        ))}
      </div>
    ),
    Bar: () => <div data-testid="bar" />,
    Cell: () => <div />,
    XAxis: () => <div />,
    YAxis: () => <div />,
    CartesianGrid: () => <div />,
    Tooltip: () => <div />,
    Legend: () => <div />,
  }
})

describe('DashboardPage', () => {
  beforeEach(() => {
    localStorage.setItem('access_token', 'test-token')
  })

  it('renders KPI cards with correct values once loaded', async () => {
    renderWithProviders(<DashboardPage />)

    await waitFor(() => {
      expect(screen.getByText('Fälle gesamt')).toBeInTheDocument()
    })

    // Check all four KPI card titles
    expect(screen.getByText('Offene ICD')).toBeInTheDocument()
    expect(screen.getByText('Offene Codierung')).toBeInTheDocument()
    expect(screen.getByText('Gutachten gesamt')).toBeInTheDocument()

    // Check KPI values from mockDashboardKPIs (142, 18, 7, 89)
    expect(screen.getByText('142')).toBeInTheDocument()
    expect(screen.getByText('18')).toBeInTheDocument()
    expect(screen.getByText('7')).toBeInTheDocument()
    expect(screen.getByText('89')).toBeInTheDocument()
  })

  it('shows year selector', async () => {
    renderWithProviders(<DashboardPage />)

    // The Select trigger should show the current year
    const currentYear = new Date().getFullYear()
    await waitFor(() => {
      expect(screen.getByText(String(currentYear))).toBeInTheDocument()
    })

    // The heading should be present
    expect(screen.getByText('Dashboard')).toBeInTheDocument()
  })

  it('shows loading skeleton initially', () => {
    // Delay the API response so we can observe the loading state
    server.use(
      http.get('/api/reports/dashboard', async () => {
        await new Promise((resolve) => setTimeout(resolve, 500))
        return HttpResponse.json({ kpis: {}, weekly: [] })
      }),
    )

    renderWithProviders(<DashboardPage />)

    // During loading, the KPI titles should not be visible yet
    expect(screen.queryByText('Fälle gesamt')).not.toBeInTheDocument()

    // The heading is always visible
    expect(screen.getByText('Dashboard')).toBeInTheDocument()
  })

  it('filters 0-value Fallgruppen from pie chart data', async () => {
    // The mock data has: onko: 65, ortho: 42, kardio: 20, neuro: 15
    // FALLGRUPPEN_LABELS maps onko->Onkologie, kardio->Kardiologie
    // ortho and neuro are not in FALLGRUPPEN_LABELS so they use the raw key
    // All values are > 0, so all should appear in the pie chart
    // sd, intensiv, galle are NOT in mock data, so they should not appear
    renderWithProviders(<DashboardPage />)

    await waitFor(() => {
      expect(screen.getByText('Fälle gesamt')).toBeInTheDocument()
    })

    // The chart section title should appear
    expect(screen.getByText('Fallgruppen')).toBeInTheDocument()

    // Onkologie and Kardiologie should appear (mapped from FALLGRUPPEN_LABELS)
    expect(screen.getByText('Onkologie')).toBeInTheDocument()
    expect(screen.getByText('Kardiologie')).toBeInTheDocument()

    // ortho and neuro use raw keys since they are not in FALLGRUPPEN_LABELS
    expect(screen.getByText('ortho')).toBeInTheDocument()
    expect(screen.getByText('neuro')).toBeInTheDocument()

    // Schilddrüse should NOT appear (sd is not in mock data)
    expect(screen.queryByText('Schilddrüse')).not.toBeInTheDocument()
    // Intensivmedizin should NOT appear (intensiv is not in mock data)
    expect(screen.queryByText('Intensivmedizin')).not.toBeInTheDocument()
    // Gallenblase should NOT appear (galle is not in mock data)
    expect(screen.queryByText('Gallenblase')).not.toBeInTheDocument()
  })

  it('handles error state when API returns 500', async () => {
    server.use(
      http.get('/api/reports/dashboard', () => {
        return new HttpResponse(null, { status: 500 })
      }),
    )

    renderWithProviders(<DashboardPage />)

    // When data is null and loading is false, it shows the fallback message
    await waitFor(() => {
      expect(screen.getByText('Keine Daten verfügbar.')).toBeInTheDocument()
    })
  })
})
