import { describe, it, expect, vi } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { GridOverlay, GridStats, GridLegend, getCellBlockNumber } from '../GridOverlay'
import type { GridData, GridCell } from '../GridOverlay'

// Helper to create mock grid data
const createMockGrid = (rows: number = 3, cols: number = 3): GridData => {
  const cells: GridCell[][] = []
  for (let r = 0; r < rows; r++) {
    const row: GridCell[] = []
    for (let c = 0; c < cols; c++) {
      row.push({
        row: r,
        col: c,
        x: (c / cols) * 100,
        y: (r / rows) * 100,
        width: 100 / cols,
        height: 100 / rows,
        text: `cell-${r}-${c}`,
        confidence: 0.85,
        status: r === 0 ? 'empty' : c === 0 ? 'problematic' : 'recognized',
        column_type: c === 1 ? 'english' : c === 2 ? 'german' : 'unknown',
      })
    }
    cells.push(row)
  }

  return {
    rows,
    columns: cols,
    cells,
    column_types: ['unknown', 'english', 'german'],
    column_boundaries: [0, 33.33, 66.66, 100],
    row_boundaries: [0, 33.33, 66.66, 100],
    deskew_angle: 0,
    stats: {
      recognized: 4,
      problematic: 2,
      empty: 3,
      manual: 0,
      total: 9,
      coverage: 0.67,
    },
  }
}

describe('getCellBlockNumber', () => {
  it('should return correct block number for first cell', () => {
    const grid = createMockGrid(3, 4)
    const cell: GridCell = { row: 0, col: 0, x: 0, y: 0, width: 25, height: 33, text: '', confidence: 1, status: 'empty' }

    expect(getCellBlockNumber(cell, grid)).toBe(1)
  })

  it('should return correct block number for cell in second row', () => {
    const grid = createMockGrid(3, 4)
    const cell: GridCell = { row: 1, col: 0, x: 0, y: 33, width: 25, height: 33, text: '', confidence: 1, status: 'empty' }

    expect(getCellBlockNumber(cell, grid)).toBe(5)
  })

  it('should return correct block number for last cell', () => {
    const grid = createMockGrid(3, 4)
    const cell: GridCell = { row: 2, col: 3, x: 75, y: 66, width: 25, height: 33, text: '', confidence: 1, status: 'empty' }

    expect(getCellBlockNumber(cell, grid)).toBe(12)
  })

  it('should calculate correctly for different grid sizes', () => {
    const grid = createMockGrid(5, 5)
    const cell: GridCell = { row: 2, col: 3, x: 60, y: 40, width: 20, height: 20, text: '', confidence: 1, status: 'empty' }

    expect(getCellBlockNumber(cell, grid)).toBe(14) // row 2 * 5 cols + col 3 + 1 = 14
  })
})

describe('GridOverlay', () => {
  it('should render without crashing', () => {
    render(<GridOverlay grid={createMockGrid()} />)
    expect(document.querySelector('svg')).toBeInTheDocument()
  })

  it('should render image when imageUrl is provided', () => {
    render(<GridOverlay grid={createMockGrid()} imageUrl="https://example.com/image.jpg" />)
    const img = screen.getByAltText('Document')
    expect(img).toBeInTheDocument()
    expect(img).toHaveAttribute('src', 'https://example.com/image.jpg')
  })

  it('should call onCellClick when a non-empty cell is clicked', () => {
    const mockOnClick = vi.fn()
    const grid = createMockGrid()

    render(<GridOverlay grid={grid} onCellClick={mockOnClick} />)

    // Find a recognized cell (non-empty) and click it
    const recognizedCells = document.querySelectorAll('rect')
    // Click on a cell that should be clickable (recognized status)
    recognizedCells.forEach(rect => {
      if (rect.getAttribute('fill')?.includes('34, 197, 94')) {
        fireEvent.click(rect)
      }
    })

    // onCellClick should have been called for recognized cells
    expect(mockOnClick).toHaveBeenCalled()
  })

  it('should not call onCellClick for empty cells', () => {
    const mockOnClick = vi.fn()
    const emptyGrid: GridData = {
      ...createMockGrid(),
      cells: [[{ row: 0, col: 0, x: 0, y: 0, width: 100, height: 100, text: '', confidence: 0, status: 'empty' }]],
    }

    render(<GridOverlay grid={emptyGrid} onCellClick={mockOnClick} showEmpty />)

    const cell = document.querySelector('rect')
    if (cell) {
      fireEvent.click(cell)
    }

    expect(mockOnClick).not.toHaveBeenCalled()
  })

  it('should show column labels when showLabels is true', () => {
    render(<GridOverlay grid={createMockGrid()} showLabels />)

    // Check for column type labels
    const svgTexts = document.querySelectorAll('text')
    const labels = Array.from(svgTexts).map(t => t.textContent)
    expect(labels).toContain('EN')
    expect(labels).toContain('DE')
  })

  it('should hide empty cells when showEmpty is false', () => {
    const grid = createMockGrid()
    const emptyCellCount = grid.cells.flat().filter(c => c.status === 'empty').length

    const { container } = render(<GridOverlay grid={grid} showEmpty={false} />)
    const allRects = container.querySelectorAll('g > rect')

    // Should have fewer rects when empty cells are hidden
    const totalCells = grid.rows * grid.columns
    expect(allRects.length).toBeLessThan(totalCells * 2) // each cell can have multiple rects
  })

  it('should show block numbers when showNumbers is true', () => {
    render(<GridOverlay grid={createMockGrid()} showNumbers />)

    const svgTexts = document.querySelectorAll('text')
    const numbers = Array.from(svgTexts).map(t => t.textContent).filter(t => /^\d+$/.test(t || ''))

    expect(numbers.length).toBeGreaterThan(0)
  })

  it('should highlight a specific block when highlightedBlockNumber is set', () => {
    const grid = createMockGrid()

    render(<GridOverlay grid={grid} showNumbers highlightedBlockNumber={5} />)

    // Check that there's a highlighted element (with indigo color)
    const rects = document.querySelectorAll('rect')
    const highlightedRect = Array.from(rects).find(
      rect => rect.getAttribute('stroke') === '#4f46e5'
    )

    expect(highlightedRect).toBeTruthy()
  })

  it('should apply custom className', () => {
    const { container } = render(<GridOverlay grid={createMockGrid()} className="custom-class" />)

    expect(container.firstChild).toHaveClass('custom-class')
  })

  it('should render row and column boundary lines', () => {
    render(<GridOverlay grid={createMockGrid()} />)

    const lines = document.querySelectorAll('line')
    expect(lines.length).toBeGreaterThan(0)
  })
})

describe('GridStats', () => {
  const mockStats = {
    recognized: 10,
    problematic: 3,
    empty: 5,
    manual: 2,
    total: 20,
    coverage: 0.75,
  }

  it('should display recognized count', () => {
    render(<GridStats stats={mockStats} />)
    expect(screen.getByText('Erkannt: 10')).toBeInTheDocument()
  })

  it('should display problematic count when greater than 0', () => {
    render(<GridStats stats={mockStats} />)
    expect(screen.getByText('Problematisch: 3')).toBeInTheDocument()
  })

  it('should not display problematic when count is 0', () => {
    render(<GridStats stats={{ ...mockStats, problematic: 0 }} />)
    expect(screen.queryByText(/Problematisch:/)).not.toBeInTheDocument()
  })

  it('should display manual count when greater than 0', () => {
    render(<GridStats stats={mockStats} />)
    expect(screen.getByText('Manuell: 2')).toBeInTheDocument()
  })

  it('should not display manual when count is 0', () => {
    render(<GridStats stats={{ ...mockStats, manual: 0 }} />)
    expect(screen.queryByText(/Manuell:/)).not.toBeInTheDocument()
  })

  it('should display empty count', () => {
    render(<GridStats stats={mockStats} />)
    expect(screen.getByText('Leer: 5')).toBeInTheDocument()
  })

  it('should display coverage percentage', () => {
    render(<GridStats stats={mockStats} />)
    expect(screen.getByText('Abdeckung: 75%')).toBeInTheDocument()
  })

  it('should display deskew angle when provided and non-zero', () => {
    render(<GridStats stats={mockStats} deskewAngle={2.5} />)
    expect(screen.getByText('Begradigt: 2.5')).toBeInTheDocument()
  })

  it('should not display deskew angle when 0', () => {
    render(<GridStats stats={mockStats} deskewAngle={0} />)
    expect(screen.queryByText(/Begradigt:/)).not.toBeInTheDocument()
  })

  it('should apply custom className', () => {
    const { container } = render(<GridStats stats={mockStats} className="custom-stats" />)
    expect(container.firstChild).toHaveClass('custom-stats')
  })
})

describe('GridLegend', () => {
  it('should display all status labels', () => {
    render(<GridLegend />)

    expect(screen.getByText('Erkannt')).toBeInTheDocument()
    expect(screen.getByText('Problematisch')).toBeInTheDocument()
    expect(screen.getByText('Manuell korrigiert')).toBeInTheDocument()
    expect(screen.getByText('Leer')).toBeInTheDocument()
  })

  it('should render color indicators for each status', () => {
    const { container } = render(<GridLegend />)

    const colorIndicators = container.querySelectorAll('.w-4.h-4.rounded')
    expect(colorIndicators.length).toBe(4)
  })

  it('should apply custom className', () => {
    const { container } = render(<GridLegend className="custom-legend" />)
    expect(container.firstChild).toHaveClass('custom-legend')
  })
})
