'use client'

/**
 * StepAnsicht — Split-view page layout comparison.
 *
 * Left:  Original scan with OCR word overlay
 * Right: Reconstructed layout with averaged row heights per section
 *
 * Layout principle: the page is divided into vertical sections separated
 * by boxes.  Each section gets a uniform row height calculated from
 * (last_row_y - first_row_y) / (num_rows - 1).  Boxes are rendered
 * inline between sections (not as floating overlays).
 */

import { useEffect, useMemo, useRef, useState } from 'react'
import { useGridEditor } from '@/components/grid-editor/useGridEditor'
import type { GridZone, GridEditorCell, GridRow } from '@/components/grid-editor/types'

const KLAUSUR_API = '/klausur-api'

interface StepAnsichtProps {
  sessionId: string | null
  onNext: () => void
}

/** A vertical section of the page: either content rows or a box zone. */
interface PageSection {
  type: 'content' | 'box'
  yStart: number   // pixel y in original image
  yEnd: number     // pixel y end
  zone?: GridZone  // for box sections
  rows?: GridRow[] // for content sections — subset of content zone rows
  avgRowH: number  // averaged row height in original pixels
}

function getCellColor(cell: GridEditorCell | undefined): string | null {
  if (!cell) return null
  if (cell.color_override) return cell.color_override
  const colored = cell.word_boxes?.find((wb) => wb.color_name && wb.color_name !== 'black')
  return colored?.color ?? null
}

export function StepAnsicht({ sessionId, onNext }: StepAnsichtProps) {
  const { grid, loading, error, loadGrid } = useGridEditor(sessionId)

  const leftRef = useRef<HTMLDivElement>(null)
  const [panelWidth, setPanelWidth] = useState(0)
  const [showGrid, setShowGrid] = useState(true)
  const [gridSpacing, setGridSpacing] = useState(100)

  useEffect(() => {
    if (sessionId) loadGrid()
  }, [sessionId]) // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (!leftRef.current) return
    const ro = new ResizeObserver(([entry]) => setPanelWidth(entry.contentRect.width))
    ro.observe(leftRef.current)
    return () => ro.disconnect()
  }, [])

  // Build page sections: split content rows around box zones
  const sections = useMemo(() => {
    if (!grid) return []
    const contentZone = grid.zones.find((z) => z.zone_type === 'content')
    const boxZones = grid.zones.filter((z) => z.zone_type === 'box')
      .sort((a, b) => a.bbox_px.y - b.bbox_px.y)

    if (!contentZone) return []

    const allRows = contentZone.rows
    const result: PageSection[] = []

    // Box boundaries sorted by y
    const boxBounds = boxZones.map((bz) => ({
      zone: bz,
      yStart: bz.bbox_px.y,
      yEnd: bz.bbox_px.y + bz.bbox_px.h,
    }))

    // Split content rows into sections around boxes
    let currentRows: GridRow[] = []
    let boxIdx = 0

    for (const row of allRows) {
      const ry = row.y_min_px ?? (row as any).y_min ?? 0

      // Check if we've passed a box boundary — insert box section
      while (boxIdx < boxBounds.length && ry >= boxBounds[boxIdx].yStart) {
        // Flush current content section
        if (currentRows.length > 0) {
          result.push(makeContentSection(currentRows))
          currentRows = []
        }
        // Insert box section
        const bb = boxBounds[boxIdx]
        const bRows = bb.zone.rows || []
        let bAvgH = 35
        if (bRows.length >= 2) {
          const bys = bRows.map((r) => r.y_min_px ?? (r as any).y_min ?? 0)
          bAvgH = (bys[bys.length - 1] - bys[0]) / (bRows.length - 1)
        }
        result.push({
          type: 'box',
          yStart: bb.yStart,
          yEnd: bb.yEnd,
          zone: bb.zone,
          avgRowH: bAvgH,
        })
        boxIdx++
      }

      // Skip rows only if they fall FULLY inside a box (both Y and X overlap).
      // Small boxes (e.g. on the right half) don't cover left-side content rows.
      const rowCells = contentZone!.cells.filter((c) => c.row_index === row.index)
      const rowXMin = rowCells.length > 0
        ? Math.min(...rowCells.map((c) => c.bbox_px?.x ?? contentZone!.bbox_px.x))
        : contentZone!.bbox_px.x
      const insideBox = boxBounds.some((bb) => {
        if (ry < bb.yStart || ry > bb.yEnd) return false
        // Check horizontal overlap: row must be mostly inside box x-range
        const boxXMin = bb.zone.bbox_px.x
        const boxXMax = boxXMin + bb.zone.bbox_px.w
        return rowXMin >= boxXMin - 20 && rowXMin <= boxXMax
      })
      if (!insideBox) {
        currentRows.push(row)
      }
    }

    // Flush remaining content rows
    if (currentRows.length > 0) {
      result.push(makeContentSection(currentRows))
    }

    // Insert remaining boxes (if any rows didn't trigger them)
    while (boxIdx < boxBounds.length) {
      const bb = boxBounds[boxIdx]
      const bRows = bb.zone.rows || []
      let bAvgH = 35
      if (bRows.length >= 2) {
        const bys = bRows.map((r) => r.y_min_px ?? (r as any).y_min ?? 0)
        bAvgH = (bys[bys.length - 1] - bys[0]) / (bRows.length - 1)
      }
      result.push({ type: 'box', yStart: bb.yStart, yEnd: bb.yEnd, zone: bb.zone, avgRowH: bAvgH })
      boxIdx++
    }

    return result
  }, [grid])

  if (loading) {
    return (
      <div className="flex items-center justify-center py-16">
        <div className="w-8 h-8 border-4 border-teal-500 border-t-transparent rounded-full animate-spin" />
        <span className="ml-3 text-gray-500">Lade Vorschau...</span>
      </div>
    )
  }

  if (error || !grid) {
    return (
      <div className="p-8 text-center">
        <p className="text-red-500 mb-4">{error || 'Keine Grid-Daten.'}</p>
        <button onClick={onNext} className="px-5 py-2 bg-teal-600 text-white rounded-lg">Weiter →</button>
      </div>
    )
  }

  const imgW = grid.image_width || 1
  const imgH = grid.image_height || 1
  const scale = panelWidth > 0 ? panelWidth / imgW : 0.5
  const panelHeight = imgH * scale
  const contentZone = grid.zones.find((z) => z.zone_type === 'content')

  return (
    <div className="space-y-3">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h3 className="text-lg font-semibold text-gray-900 dark:text-white">Ansicht — Original vs. Rekonstruktion</h3>
          <p className="text-sm text-gray-500 dark:text-gray-400">
            Links: Original mit OCR. Rechts: Rekonstruktion mit gemittelten Zeilenhöhen.
          </p>
        </div>
        <div className="flex items-center gap-2">
          <label className="flex items-center gap-1.5 text-xs text-gray-500">
            <input type="checkbox" checked={showGrid} onChange={(e) => setShowGrid(e.target.checked)} className="w-3.5 h-3.5 rounded" />
            Gitter
          </label>
          <select value={gridSpacing} onChange={(e) => setGridSpacing(Number(e.target.value))} className="text-xs px-1.5 py-1 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700">
            <option value={50}>50px</option>
            <option value={100}>100px</option>
            <option value={200}>200px</option>
          </select>
          <button onClick={onNext} className="px-5 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 text-sm font-medium">Weiter →</button>
        </div>
      </div>

      {/* Split view */}
      <div className="flex gap-2" style={{ height: `${panelHeight + 40}px` }}>
        {/* LEFT: Original + OCR overlay */}
        <div ref={leftRef} className="flex-1 relative border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden bg-white dark:bg-gray-900">
          <div className="absolute top-0 left-0 px-2 py-0.5 bg-black/60 text-white text-[10px] font-medium rounded-br z-20">Original + OCR</div>
          {sessionId && (
            <img
              src={`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/words-overlay`}
              alt="Original + OCR"
              className="absolute inset-0 w-full h-auto"
              style={{ height: `${panelHeight}px`, objectFit: 'contain' }}
            />
          )}
          {showGrid && <CoordinateGrid imgW={imgW} imgH={imgH} scale={scale} spacing={gridSpacing} />}
        </div>

        {/* RIGHT: Reconstruction */}
        <div className="flex-1 relative border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden bg-white dark:bg-gray-900">
          <div className="absolute top-0 left-0 px-2 py-0.5 bg-teal-600/80 text-white text-[10px] font-medium rounded-br z-20">Rekonstruktion</div>

          {/* Render sections sequentially */}
          {sections.map((sec, si) => {
            if (sec.type === 'box' && sec.zone) {
              return (
                <BoxSectionRenderer
                  key={`box-${si}`}
                  zone={sec.zone}
                  scale={scale}
                  avgRowH={sec.avgRowH}
                />
              )
            }
            if (sec.type === 'content' && sec.rows && contentZone) {
              return (
                <ContentSectionRenderer
                  key={`sec-${si}`}
                  zone={contentZone}
                  rows={sec.rows}
                  yStart={sec.yStart}
                  scale={scale}
                  avgRowH={sec.avgRowH}
                />
              )
            }
            return null
          })}

          {showGrid && <CoordinateGrid imgW={imgW} imgH={imgH} scale={scale} spacing={gridSpacing} />}
        </div>
      </div>
    </div>
  )
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function makeContentSection(rows: GridRow[]): PageSection {
  const ys = rows.map((r) => r.y_min_px ?? (r as any).y_min ?? 0)
  const yEnd = rows[rows.length - 1].y_max_px ?? (rows[rows.length - 1] as any).y_max ?? ys[ys.length - 1] + 30
  let avgRowH = 35
  if (rows.length >= 2) {
    avgRowH = (ys[ys.length - 1] - ys[0]) / (rows.length - 1)
  }
  return { type: 'content', yStart: ys[0], yEnd, rows, avgRowH }
}

// ---------------------------------------------------------------------------
// Content section renderer — rows from content zone at absolute positions
// ---------------------------------------------------------------------------

function ContentSectionRenderer({ zone, rows, yStart, scale, avgRowH }: {
  zone: GridZone; rows: GridRow[]; yStart: number; scale: number; avgRowH: number
}) {
  const cellMap = new Map<string, GridEditorCell>()
  for (const cell of zone.cells) {
    cellMap.set(`${cell.row_index}_${cell.col_index}`, cell)
  }

  const rowH = avgRowH * scale
  const fontSize = Math.max(7, rowH * 0.55)

  return (
    <>
      {rows.map((row, ri) => {
        const rowY = (row.y_min_px ?? (row as any).y_min ?? 0) * scale
        const isSpanning = zone.cells.some((c) => c.row_index === row.index && c.col_type === 'spanning_header')

        // Column widths
        const colWidths = zone.columns.map((col) => Math.max(5, ((col.x_max_px ?? 0) - (col.x_min_px ?? 0)) * scale))
        const zoneLeft = zone.bbox_px.x * scale
        const zoneWidth = zone.bbox_px.w * scale
        const totalColW = colWidths.reduce((s, w) => s + w, 0)
        const colScale = totalColW > 0 ? zoneWidth / totalColW : 1

        return (
          <div
            key={row.index}
            className="absolute"
            style={{
              left: `${zoneLeft}px`,
              top: `${rowY}px`,
              width: `${zoneWidth}px`,
              height: `${rowH}px`,
              display: 'grid',
              gridTemplateColumns: colWidths.map((w) => `${(w * colScale).toFixed(1)}px`).join(' '),
              fontSize: `${fontSize}px`,
              lineHeight: `${rowH}px`,
            }}
          >
            {isSpanning ? (
              zone.cells
                .filter((c) => c.row_index === row.index && c.col_type === 'spanning_header')
                .sort((a, b) => a.col_index - b.col_index)
                .map((cell) => {
                  const colspan = cell.colspan || zone.columns.length
                  const color = getCellColor(cell)
                  return (
                    <div
                      key={cell.cell_id}
                      className={`overflow-hidden ${row.is_header ? 'font-bold' : ''}`}
                      style={{ gridColumn: `${cell.col_index + 1} / ${cell.col_index + 1 + colspan}`, color: color || undefined }}
                    >
                      {cell.text}
                    </div>
                  )
                })
            ) : (
              zone.columns.map((col) => {
                const cell = cellMap.get(`${row.index}_${col.index}`)
                const color = getCellColor(cell)
                const isBold = col.bold || cell?.is_bold || row.is_header
                return (
                  <div
                    key={col.index}
                    className={`overflow-hidden text-ellipsis whitespace-nowrap ${isBold ? 'font-bold' : ''}`}
                    style={{ color: color || undefined }}
                  >
                    {cell?.text ?? ''}
                  </div>
                )
              })
            )}
          </div>
        )
      })}
    </>
  )
}

// ---------------------------------------------------------------------------
// Box section renderer — box zone at absolute position with border
// ---------------------------------------------------------------------------

function BoxSectionRenderer({ zone, scale, avgRowH }: {
  zone: GridZone; scale: number; avgRowH: number
}) {
  const boxColor = (zone as any).box_bg_hex || '#6b7280'
  if (!zone.cells || zone.cells.length === 0) return null

  const left = zone.bbox_px.x * scale
  const top = zone.bbox_px.y * scale
  const width = zone.bbox_px.w * scale
  const height = zone.bbox_px.h * scale
  const rowH = avgRowH * scale
  const fontSize = Math.max(7, rowH * 0.5)

  const cellMap = new Map<string, GridEditorCell>()
  for (const cell of zone.cells) {
    cellMap.set(`${cell.row_index}_${cell.col_index}`, cell)
  }

  const colWidths = zone.columns.map((col) => Math.max(5, ((col.x_max_px ?? 0) - (col.x_min_px ?? 0)) * scale))
  const totalColW = colWidths.reduce((s, w) => s + w, 0)
  const colScale = totalColW > 0 ? width / totalColW : 1
  const numCols = zone.columns.length

  // Evenly distribute rows within the box
  const numRows = zone.rows.length
  const evenRowH = numRows > 0 ? height / numRows : rowH

  return (
    <div
      className="absolute overflow-hidden"
      style={{
        left: `${left}px`,
        top: `${top}px`,
        width: `${width}px`,
        height: `${height}px`,
        border: `${Math.max(1.5, 2 * scale)}px solid ${boxColor}`,
        backgroundColor: `${boxColor}0a`,
        borderRadius: `${Math.max(1, 3 * scale)}px`,
        fontSize: `${fontSize}px`,
        lineHeight: '1.3',
      }}
    >
      <div style={{ display: 'grid', gridTemplateColumns: colWidths.map((w) => `${(w * colScale).toFixed(1)}px`).join(' ') }}>
        {zone.rows.map((row) => {
          const isSpanning = zone.cells.some((c) => c.row_index === row.index && c.col_type === 'spanning_header')

          // Multi-line height
          const maxLines = Math.max(1, ...zone.cells
            .filter((c) => c.row_index === row.index)
            .map((c) => (c.text ?? '').split('\n').length))
          const cellRowH = evenRowH * (maxLines > 1 ? maxLines * 0.7 : 1)

          return (
            <div key={row.index} style={{ display: 'contents' }}>
              {isSpanning ? (
                zone.cells
                  .filter((c) => c.row_index === row.index && c.col_type === 'spanning_header')
                  .sort((a, b) => a.col_index - b.col_index)
                  .map((cell) => {
                    const colspan = cell.colspan || numCols
                    const color = getCellColor(cell)
                    return (
                      <div
                        key={cell.cell_id}
                        className={`px-1 overflow-hidden ${row.is_header ? 'font-bold' : ''}`}
                        style={{
                          gridColumn: `${cell.col_index + 1} / ${cell.col_index + 1 + colspan}`,
                          height: `${cellRowH}px`,
                          color: color || undefined,
                          whiteSpace: 'pre-wrap',
                          display: 'flex',
                          alignItems: 'center',
                        }}
                      >
                        {cell.text}
                      </div>
                    )
                  })
              ) : (
                zone.columns.map((col) => {
                  const cell = cellMap.get(`${row.index}_${col.index}`)
                  const color = getCellColor(cell)
                  const isBold = col.bold || cell?.is_bold || row.is_header
                  const text = cell?.text ?? ''
                  const isMultiLine = text.includes('\n')

                  return (
                    <div
                      key={col.index}
                      className={`px-1 overflow-hidden ${isBold ? 'font-bold' : ''}`}
                      style={{
                        height: `${cellRowH}px`,
                        color: color || undefined,
                        whiteSpace: isMultiLine ? 'pre-wrap' : 'nowrap',
                        textOverflow: isMultiLine ? undefined : 'ellipsis',
                        display: 'flex',
                        alignItems: isMultiLine ? 'flex-start' : 'center',
                        paddingLeft: isMultiLine ? `${fontSize * 0.5}px` : undefined,
                      }}
                    >
                      {text}
                    </div>
                  )
                })
              )}
            </div>
          )
        })}
      </div>
    </div>
  )
}

// ---------------------------------------------------------------------------
// Coordinate grid
// ---------------------------------------------------------------------------

function CoordinateGrid({ imgW, imgH, scale, spacing }: {
  imgW: number; imgH: number; scale: number; spacing: number
}) {
  const lines: JSX.Element[] = []
  for (let x = 0; x <= imgW; x += spacing) {
    const px = x * scale
    lines.push(
      <div key={`v${x}`} className="absolute top-0 bottom-0 pointer-events-none" style={{ left: `${px}px`, width: '1px', background: 'rgba(0,150,255,0.2)' }}>
        <span className="absolute top-0 left-1 text-[8px] text-blue-400 font-mono">{x}</span>
      </div>
    )
  }
  for (let y = 0; y <= imgH; y += spacing) {
    const px = y * scale
    lines.push(
      <div key={`h${y}`} className="absolute left-0 right-0 pointer-events-none" style={{ top: `${px}px`, height: '1px', background: 'rgba(0,150,255,0.2)' }}>
        <span className="absolute left-1 top-0.5 text-[8px] text-blue-400 font-mono">{y}</span>
      </div>
    )
  }
  return <>{lines}</>
}
