import { fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { TimeSeriesChart } from './TimeSeriesChart'

const points = [
  { ts: '2026-08-13T00:00:00.000Z', value: 2 },
  { ts: '2026-08-13T00:15:00.000Z', value: 5 },
]

describe('TimeSeriesChart', () => {
  it('renders measured points, coverage, gaps, and an accessible data view', () => {
    render(<TimeSeriesChart label="Active agents" points={points} status="available" coverageFrom="2026-08-13T00:00:00.000Z" gaps={[{ reason: 'agent-session retention unknown' }]} valueLabel="agents" />)

    expect(screen.getByRole('img', { name: 'Active agents over time' })).toBeInTheDocument()
    expect(screen.getByText(/Measured from 2026-08-13T00:00:00.000Z/)).toBeInTheDocument()
    expect(screen.getByText('Coverage gap: agent-session retention unknown')).toBeInTheDocument()
    expect(screen.getByText('View data table')).toBeInTheDocument()
    expect(screen.getAllByText('Time').length).toBeGreaterThan(0)
    expect(screen.getAllByText('agents').length).toBeGreaterThan(0)
    expect(screen.getAllByText('5').length).toBeGreaterThan(0)
    expect(screen.getByRole('button', { name: '2026-08-13T00:15:00.000Z: 5 agents' })).toBeInTheDocument()
  })

  it('reveals the exact point value on keyboard focus', () => {
    render(<TimeSeriesChart label="Builds" points={points} status="available" valueLabel="builds" />)
    const point = screen.getByRole('button', { name: '2026-08-13T00:15:00.000Z: 5 builds' })

    fireEvent.focus(point)
    expect(screen.getByText('2026-08-13T00:15:00.000Z: 5 builds')).toBeInTheDocument()
  })

  it('splits the line at declared gaps and keeps targets in SVG coordinates', () => {
    const { container } = render(<TimeSeriesChart label="Builds" points={[...points, { ts: '2026-08-13T00:30:00.000Z', value: 3 }]} status="available" gaps={[{ from: '2026-08-13T00:10:00.000Z', to: '2026-08-13T00:20:00.000Z', reason: 'collector offline' }]} valueLabel="builds" />)
    const segments = Array.from(container.querySelectorAll('[data-series-segment]'))
    expect(segments).toHaveLength(3)
    expect(segments.every((segment) => !segment.getAttribute('d')?.includes(' L'))).toBe(true)
    const target = screen.getByRole('button', { name: '2026-08-13T00:15:00.000Z: 5 builds' })
    expect(target.closest('svg')).not.toBeNull()
    expect(target).toHaveAttribute('data-point-x')
    expect(target).toHaveAttribute('data-point-y')
  })

  it('includes calendar dates on cross-midnight ticks and states locale semantics', () => {
    const beforeMidnight = new Date(2026, 7, 13, 23, 30)
    const afterMidnight = new Date(2026, 7, 14, 0, 30)
    render(<TimeSeriesChart label="Sessions" points={[
      { ts: beforeMidnight.toISOString(), value: 2 },
      { ts: afterMidnight.toISOString(), value: 1 },
    ]} status="available" valueLabel="sessions" />)

    const firstDate = beforeMidnight.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })
    const lastDate = afterMidnight.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })
    expect(firstDate).not.toBe(lastDate)
    expect(screen.getAllByText(firstDate).length).toBeGreaterThan(0)
    expect(screen.getAllByText(lastDate).length).toBeGreaterThan(0)
    expect(screen.getByText(/Times use your browser locale and time zone/)).toBeInTheDocument()
    expect(screen.getByRole('button', { name: `${afterMidnight.toISOString()}: 1 sessions` })).toBeInTheDocument()
  })

  it('uses unique tick identities for a single measured point', () => {
    const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined)
    render(<TimeSeriesChart label="Builds" points={[points[0]]} status="available" valueLabel="builds" />)

    expect(screen.getByRole('img', { name: 'Builds over time' })).toBeInTheDocument()
    expect(consoleError).not.toHaveBeenCalled()
    consoleError.mockRestore()
  })

  it('states unavailable and measured-empty ranges without drawing false data', () => {
    const { rerender } = render(<TimeSeriesChart label="Commits" points={[]} status="unavailable" reason="No authoritative source" />)
    expect(screen.getByRole('status')).toHaveTextContent('Commits unavailable — No authoritative source')
    expect(screen.queryByRole('img')).not.toBeInTheDocument()

    rerender(<TimeSeriesChart label="Commits" points={[]} status="available" />)
    expect(screen.getByRole('status')).toHaveTextContent('No measured commits points in this covered range.')
  })
})
