'use client'

/**
 * SpreadsheetView — Fortune Sheet with multi-sheet support.
 *
 * Each zone (content + boxes) becomes its own Excel sheet tab,
 * so each can have independent column widths optimized for its content.
 */

import { useMemo } from 'react'
import dynamic from 'next/dynamic'

const Workbook = dynamic(
  () => import('@fortune-sheet/react').then((m) => m.Workbook),
  { ssr: false, loading: () => <div className="py-8 text-center text-sm text-gray-400">Spreadsheet wird geladen...</div> },
)

import '@fortune-sheet/react/dist/index.css'

import type { GridZone } from '@/components/grid-editor/types'

interface SpreadsheetViewProps {
  gridData: any
  height?: number
}

/** Convert a single zone to a Fortune Sheet sheet object. */
function zoneToSheet(zone: GridZone, sheetIndex: number, isFirst: boolean): any {
  const isBox = zone.zone_type === 'box'
  const boxColor = (zone as any).box_bg_hex || ''
  const layoutType = (zone as any).box_layout_type || ''

  // Sheet name
  let name: string
  if (!isBox) {
    name = 'Vokabeln'
  } else {
    const firstText = zone.cells?.[0]?.text ?? `Box ${sheetIndex}`
    const cleaned = firstText.replace(/[^\w\s\u00C0-\u024F„"]/g, '').trim()
    name = cleaned.length > 25 ? cleaned.slice(0, 25) + '…' : cleaned || `Box ${sheetIndex}`
  }

  const numRows = zone.rows?.length || 0
  const numCols = zone.columns?.length || 1

  // Build celldata
  const celldata: any[] = []
  const merges: Record<string, any> = {}

  for (const cell of (zone.cells || [])) {
    const r = cell.row_index
    const c = cell.col_index
    let text = cell.text ?? ''

    // Detect if this is a header row
    const row = zone.rows?.find((rr) => rr.index === r)
    const isHeader = row?.is_header ?? false

    // Detect if word_boxes indicate larger font (header detection)
    const avgWordHeight = cell.word_boxes?.length
      ? cell.word_boxes.reduce((s: number, wb: any) => s + (wb.height || 0), 0) / cell.word_boxes.length
      : 0
    const zoneAvgHeight = zone.cells
      .flatMap((c: any) => (c.word_boxes || []).map((wb: any) => wb.height || 0))
      .filter((h: number) => h > 0)
    const medianHeight = zoneAvgHeight.length
      ? [...zoneAvgHeight].sort((a, b) => a - b)[Math.floor(zoneAvgHeight.length / 2)]
      : 0
    const isLargerFont = avgWordHeight > 0 && medianHeight > 0 && avgWordHeight > medianHeight * 1.3

    const v: any = {
      v: text,
      m: text,
    }

    // Bold: header rows, is_bold cells, or cells with detectably larger font
    if (cell.is_bold || isHeader || isLargerFont) {
      v.bl = 1
    }

    // Larger font for detected large text (e.g., box titles)
    if (isLargerFont && isBox) {
      v.fs = 12 // slightly larger
    }

    // Header row light background
    if (isHeader) {
      v.bg = isBox ? `${boxColor || '#2563eb'}18` : '#f0f4ff'
    }

    // Box cells get light tinted background
    if (isBox && !isHeader && boxColor) {
      v.bg = `${boxColor}08`
    }

    // Text color from OCR word_boxes
    const color = cell.color_override
      ?? cell.word_boxes?.find((wb: any) => wb.color_name && wb.color_name !== 'black')?.color
    if (color) v.fc = color

    // Multi-line text: enable text wrap and preserve formatting
    if (text.includes('\n')) {
      v.tb = '2'  // text wrap enabled
    }

    celldata.push({ r, c, v })

    // Colspan → merge
    const colspan = cell.colspan || 0
    if (colspan > 1 || cell.col_type === 'spanning_header') {
      const cs = colspan || numCols
      merges[`${r}_${c}`] = { r, c, rs: 1, cs }
    }
  }

  // Column widths — auto-fit based on longest text in each column
  const columnlen: Record<string, number> = {}
  for (const col of (zone.columns || [])) {
    // Find the longest text in this column (considering only non-spanning cells)
    const colCells = (zone.cells || []).filter(
      (c: any) => c.col_index === col.index && c.col_type !== 'spanning_header'
    )
    let maxTextLen = 0
    for (const c of colCells) {
      const text = c.text ?? ''
      // For multi-line cells, use the longest line
      const lines = text.split('\n')
      const longestLine = Math.max(0, ...lines.map((l: string) => l.length))
      if (longestLine > maxTextLen) maxTextLen = longestLine
    }
    // ~7px per character as a rough estimate, minimum 60px
    const autoWidth = Math.max(60, maxTextLen * 7.5 + 16)
    // Also consider original pixel width (scaled down)
    const pxW = (col.x_max_px ?? 0) - (col.x_min_px ?? 0)
    const scaledPxW = Math.max(60, Math.round(pxW * (numCols <= 2 ? 0.6 : 0.4)))
    // Use the larger of auto-fit or scaled pixel width
    columnlen[String(col.index)] = Math.round(Math.max(autoWidth, scaledPxW))
  }

  // Row heights — taller for multi-line cells
  const rowlen: Record<string, number> = {}
  for (const row of (zone.rows || [])) {
    const rowCells = (zone.cells || []).filter((c: any) => c.row_index === row.index)
    const maxLines = Math.max(1, ...rowCells.map((c: any) => (c.text ?? '').split('\n').length))
    const baseH = isBox ? 22 : 24
    rowlen[String(row.index)] = Math.max(baseH, baseH * maxLines)
  }

  // Border info
  const borderInfo: any[] = []

  // Box: colored outside border around entire sheet content
  if (isBox && boxColor && numRows > 0 && numCols > 0) {
    borderInfo.push({
      rangeType: 'range',
      borderType: 'border-outside',
      color: boxColor,
      style: 5, // thick (style 5 = thick in Fortune Sheet)
      range: [{
        row: [0, numRows - 1],
        column: [0, numCols - 1],
      }],
    })
    // Also add light inner borders for box cells
    borderInfo.push({
      rangeType: 'range',
      borderType: 'border-inside',
      color: `${boxColor}40`,
      style: 1, // thin
      range: [{
        row: [0, numRows - 1],
        column: [0, numCols - 1],
      }],
    })
  }

  // Content zone: light grid lines
  if (!isBox && numRows > 0 && numCols > 0) {
    borderInfo.push({
      rangeType: 'range',
      borderType: 'border-all',
      color: '#e5e7eb',
      style: 1,
      range: [{
        row: [0, numRows - 1],
        column: [0, numCols - 1],
      }],
    })
  }

  return {
    name,
    id: `zone_${zone.zone_index}`,
    celldata,
    row: numRows,  // exact row count — no padding
    column: Math.max(numCols, 1),
    status: isFirst ? 1 : 0,
    color: isBox ? boxColor : undefined,
    config: {
      merge: Object.keys(merges).length > 0 ? merges : undefined,
      columnlen,
      rowlen,
      borderInfo: borderInfo.length > 0 ? borderInfo : undefined,
    },
  }
}

export function SpreadsheetView({ gridData, height = 600 }: SpreadsheetViewProps) {
  const sheets = useMemo(() => {
    if (!gridData?.zones) return []

    const sorted = [...gridData.zones].sort((a: GridZone, b: GridZone) => {
      if (a.zone_type === 'content' && b.zone_type !== 'content') return -1
      if (a.zone_type !== 'content' && b.zone_type === 'content') return 1
      return (a.bbox_px?.y ?? 0) - (b.bbox_px?.y ?? 0)
    })

    return sorted
      .filter((z: GridZone) => z.cells && z.cells.length > 0)
      .map((z: GridZone, i: number) => zoneToSheet(z, i, i === 0))
  }, [gridData])

  // Calculate minimum height to show all rows of the largest sheet
  const maxRows = Math.max(0, ...sheets.map((s: any) => s.row || 0))
  const estimatedHeight = Math.max(height, maxRows * 26 + 80) // 26px per row + toolbar

  if (sheets.length === 0) {
    return <div className="p-4 text-center text-gray-400">Keine Daten für Spreadsheet.</div>
  }

  return (
    <div style={{ width: '100%', height: `${estimatedHeight}px` }}>
      <Workbook
        data={sheets}
        lang="en"
        showToolbar
        showFormulaBar={false}
        showSheetTabs
        toolbarItems={[
          'undo', 'redo', '|',
          'font-bold', 'font-italic', 'font-strikethrough', '|',
          'font-color', 'background', '|',
          'font-size', '|',
          'horizontal-align', 'vertical-align', '|',
          'text-wrap', 'merge-cell', '|',
          'border',
        ]}
      />
    </div>
  )
}
