import type { CSSProperties } from "vue"
import type { PptxElement } from "./pptxTypes"
import { getCacheKey, getNumber } from "./pptxUtils"

type TableBorderSide = {
  borderColor?: string
  borderWidth?: number
  borderType?: string
  strokeDasharray?: string
}

type TableCellRaw = {
  text?: string
  content?: string
  html?: string
  colSpan?: number
  rowSpan?: number
  hMerge?: number
  vMerge?: number
  fillColor?: string
  fontColor?: string
  fontBold?: boolean
  fontItalic?: boolean
  borders?: {
    top?: TableBorderSide
    right?: TableBorderSide
    bottom?: TableBorderSide
    left?: TableBorderSide
  }
  [key: string]: any
}

type TableCellView = {
  html: string
  colspan: number
  rowspan: number
  skip: boolean
  style: CSSProperties
}

export type TableModel = {
  colWidths: number[]
  rowHeights: number[]
  rows: TableCellView[][]
}

const tableCache = new Map<string, TableModel>()

export function getTableModel(el: PptxElement, slideIndex: number, cacheId: string): TableModel {
  const key = `t-${getCacheKey(slideIndex, cacheId)}`
  const cached = tableCache.get(key)
  if (cached) return cached

  const rawData = (el as any)?.data
  const data: TableCellRaw[][] = Array.isArray(rawData) ? rawData : []
  const colWidthsRaw = (el as any)?.colWidths
  const rowHeightsRaw = (el as any)?.rowHeights
  const colWidths = Array.isArray(colWidthsRaw) ? colWidthsRaw.map(getNumber) : []
  const rowHeights = Array.isArray(rowHeightsRaw) ? rowHeightsRaw.map(getNumber) : []

  const rows: TableCellView[][] = data.map((row) => {
    const r = Array.isArray(row) ? row : []
    return r.map((cellRaw) => normalizeTableCell(el, cellRaw))
  })

  const model: TableModel = {
    colWidths,
    rowHeights,
    rows,
  }
  tableCache.set(key, model)
  return model
}

export function getTableRowStyle(el: PptxElement, slideIndex: number, cacheId: string, rowIndex: number) {
  const model = getTableModel(el, slideIndex, cacheId)
  const h = model.rowHeights[rowIndex]
  if (!h) return undefined
  return {
    height: `${h}px`,
  } as CSSProperties
}

function extractTextAlign(html: string) {
  const m = html.match(/text-align\s*:\s*(left|right|center|justify)/i)
  return m ? m[1].toLowerCase() : "left"
}

function getTableBorderStyle(side?: TableBorderSide) {
  if (!side) return ""
  const color = String(side.borderColor || "")
  const width = Math.max(0, getNumber(side.borderWidth))
  const borderType = String(side.borderType || "solid")
  if (!color || !width) return ""
  const style = borderType === "dashed" || borderType === "dash" ? "dashed" : "solid"
  return `${width}px ${style} ${color}`
}

function normalizeTableCell(tableEl: PptxElement, cellRaw: TableCellRaw): TableCellView {
  const raw = cellRaw && typeof cellRaw === "object" ? cellRaw : ({} as TableCellRaw)

  const html = String(raw.text ?? raw.content ?? raw.html ?? "")
  const colspan = Math.max(1, getNumber(raw.colSpan ?? (raw as any).colspan ?? (raw as any).gridSpan) || 1)
  const rowspan = Math.max(1, getNumber(raw.rowSpan ?? (raw as any).rowspan) || 1)
  const skip = getNumber(raw.hMerge) === 1 || getNumber(raw.vMerge) === 1

  const background = String(raw.fillColor || "") || undefined
  const color = String(raw.fontColor || "") || undefined
  const fontWeight = raw.fontBold ? 700 : undefined
  const fontStyle = raw.fontItalic ? "italic" : undefined
  const textAlign = html ? extractTextAlign(html) : undefined

  const borders = raw.borders || (tableEl as any)?.borders || undefined
  const borderTop = getTableBorderStyle(borders?.top)
  const borderRight = getTableBorderStyle(borders?.right)
  const borderBottom = getTableBorderStyle(borders?.bottom)
  const borderLeft = getTableBorderStyle(borders?.left)

  const style: CSSProperties = {
    padding: "2px 4px",
    verticalAlign: "middle",
    background,
    color,
    fontWeight,
    fontStyle,
    textAlign: textAlign as any,
    borderTop: borderTop || undefined,
    borderRight: borderRight || undefined,
    borderBottom: borderBottom || undefined,
    borderLeft: borderLeft || undefined,
    overflow: "hidden",
  }

  return {
    html,
    colspan,
    rowspan,
    skip,
    style,
  }
}

