import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, waitFor, within } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom'
import StatsPage from '../src/pages/StatsPage.js'
import type { Stats } from '../src/types.js'

vi.mock('../src/api.js', async (importOriginal) => {
  const actual = await importOriginal<typeof import('../src/api.js')>()
  return { ...actual, api: { ...actual.api, getStats: vi.fn() } }
})
import { api } from '../src/api.js'

const stats: Stats = {
  totals: { items: 4, ripped: 1, notRipped: 3, onLoan: 1 },
  ripRatio: 0.25,
  formats: [
    { name: 'CD', count: 3 },
    { name: 'Vinyl', count: 1 },
  ],
  decades: [{ name: '1990s', count: 4 }],
  topGenres: [
    { name: 'Electronic', count: 3 },
    { name: 'Downtempo', count: 2 },
  ],
  topArtists: [{ name: 'Massive Attack', count: 2 }],
  addedByMonth: [
    { month: '2025-10', count: 0 },
    { month: '2025-11', count: 0 },
    { month: '2025-12', count: 0 },
    { month: '2026-01', count: 0 },
    { month: '2026-02', count: 0 },
    { month: '2026-03', count: 0 },
    { month: '2026-04', count: 0 },
    { month: '2026-05', count: 0 },
    { month: '2026-06', count: 0 },
    { month: '2026-07', count: 0 },
    { month: '2026-08', count: 4 },
    { month: '2026-09', count: 0 },
  ],
}

beforeEach(() => {
  vi.mocked(api.getStats).mockReset()
  vi.mocked(api.getStats).mockResolvedValue(stats as never)
})

describe('StatsPage', () => {
  it('renders totals and rip ratio', async () => {
    render(
      <MemoryRouter>
        <StatsPage />
      </MemoryRouter>
    )
    expect((await screen.findAllByText('4')).length).toBeGreaterThanOrEqual(1)
    expect(screen.getByText(/25% ripped/i)).toBeTruthy()
    const onLoanLabel = screen.getByText('on loan')
    expect(within(onLoanLabel.parentElement as HTMLElement).getByText('1')).toBeTruthy()
  })

  it('renders format, genre, artist and month bars', async () => {
    render(
      <MemoryRouter>
        <StatsPage />
      </MemoryRouter>
    )
    expect(await screen.findByText('CD')).toBeTruthy()
    expect(screen.getByText('Electronic')).toBeTruthy()
    expect(screen.getByText('Massive Attack')).toBeTruthy()
    expect(screen.getByText('1990s')).toBeTruthy()
    // month bars: 12 bars rendered
    expect(document.querySelectorAll('[data-bar]').length).toBeGreaterThanOrEqual(12)
  })

  it('error state on failure', async () => {
    vi.mocked(api.getStats).mockRejectedValue(new TypeError('fetch failed'))
    render(
      <MemoryRouter>
        <StatsPage />
      </MemoryRouter>
    )
    expect(await screen.findByText(/could not load stats/i)).toBeTruthy()
  })
})
