/**
 * 策略结果表格。
 *
 * 表格骨架（表头排序/sticky/遍历）由共享的 StockDataTable 承担；本组件只负责
 * 策略页特有的单元格内容：symbol 列（含加自选按钮 + 失效行灰显）、strategies、
 * score、signals、candle、ext 列。其余纯数据列（价格/指标/财务…）交给共享原语。
 */
import { useState, type CSSProperties, type ReactNode } from 'react'
import { Check, Plus, Eye, EyeOff } from 'lucide-react'
import type { KlineRow } from '@/lib/api'
import { fmtPrice } from '@/lib/format'
import type { ColumnConfig } from '@/lib/screener-columns'
import { getSignals, signalCls } from '@/lib/stock-table'
import { boardTag, renderBuiltinDataCell } from '@/components/stock-table/primitives'
import { resolveCandleConfig } from '@/lib/list-columns'
import { MiniCandlestick } from '@/components/stock-table/MiniCandlestick'
import { StockDataTable, type SortState } from '@/components/stock-table/StockDataTable'

interface ScreenerTableProps {
  rows: any[]
  columns: ColumnConfig[]
  strategyIdToName: Record<string, string>
  symbolStrategyMap: Map<string, string[]>
  activeStrategy: string | null
  watchlistSet: Set<string>
  onPreview: (symbol: string, name: string) => void
  onToggleWatchlist: (symbol: string, inList: boolean) => void
  watchlistPending: boolean
  /** symbol → 日k 数据，仅当启用日k列时传入 */
  klineData?: Record<string, KlineRow[]>
  /** 日k蜡烛图是否显示（表头眼睛开关） */
  dailyKChartVisible?: boolean
  onToggleDailyKChart?: () => void
  /** 表头排序（受控，由 Screener.tsx 传入） */
  sort?: SortState | null
  onSortToggle?: (colId: string) => void
}

/** 渲染标签数组（含 maxTags 折叠/展开、横竖排列）。策略列与 ext 列共用。 */
function renderTagList(
  tags: string[],
  col: ColumnConfig,
  expanded: boolean,
  onToggle: () => void,
  tagClassName: string,
): ReactNode {
  if (tags.length === 0) return <span className="text-muted">—</span>

  const cfg = col.extDisplay
  const maxTags = cfg?.maxTags ?? 0
  const showAll = maxTags <= 0 || expanded || tags.length <= maxTags
  const sliced = showAll ? tags : tags.slice(0, maxTags)
  const hiddenIndices = maxTags > 0 ? cfg?.hiddenIndices : undefined
  const visibleTags = hiddenIndices?.length
    ? sliced.filter((_, i) => !hiddenIndices.includes(i))
    : sliced
  const hiddenCount = tags.length - visibleTags.length
  const isVertical = cfg?.tagLayout === 'vertical' && !expanded

  return (
    <div className={isVertical ? 'flex flex-col items-start gap-0.5' : 'flex flex-wrap gap-0.5'}>
      {visibleTags.map((tag, i) => (
        <span key={i} className={tagClassName}>{tag}</span>
      ))}
      {!showAll && hiddenCount > 0 && (
        <button
          onClick={onToggle}
          className="inline-block px-1.5 py-px rounded text-[10px] font-medium leading-tight text-accent bg-accent/10 hover:bg-accent/20 transition-colors"
        >
          +{hiddenCount}
        </button>
      )}
      {showAll && maxTags > 0 && tags.length > maxTags && (
        <button
          onClick={onToggle}
          className="inline-block px-1.5 py-px rounded text-[10px] font-medium leading-tight text-muted hover:text-foreground transition-colors"
        >
          收起
        </button>
      )}
    </div>
  )
}

const EXT_TAG_CLS = 'inline-block px-1.5 py-px rounded text-[10px] font-medium leading-tight text-yellow-500 bg-yellow-500/10'
const STRATEGY_TAG_CLS = 'inline-block px-1.5 py-px rounded text-[10px] font-medium leading-tight bg-amber-500/10 text-amber-600 border border-amber-500/20'

function renderExtValue(
  val: any,
  col: ColumnConfig,
  expanded: boolean,
  onToggle: () => void,
): ReactNode {
  if (val == null || Number.isNaN(val)) return <span className="text-muted">—</span>
  if (typeof val === 'number') {
    const displayVal = Number.isInteger(val) ? fmtPrice(val, 0) : fmtPrice(val)
    return <span className="tabular-nums">{displayVal}</span>
  }
  if (typeof val === 'boolean') {
    return <span className={val ? 'text-bull' : 'text-muted'}>{val ? '是' : '否'}</span>
  }

  const cfg = col.extDisplay
  const str = String(val)
  if (cfg?.displayMode === 'text') return <span className="text-foreground">{str}</span>

  const separator = cfg?.separator?.trim() || null
  const tags = separator
    ? str.split(separator).map(s => s.trim()).filter(Boolean)
    : str.split(/[、,，;；\-]/).map(s => s.trim()).filter(Boolean)

  return renderTagList(tags, col, expanded, onToggle, EXT_TAG_CLS)
}

export function ScreenerTable({
  rows, columns, strategyIdToName, symbolStrategyMap, activeStrategy,
  watchlistSet, onPreview, onToggleWatchlist, watchlistPending, klineData = {},
  dailyKChartVisible = true, onToggleDailyKChart,
  sort, onSortToggle,
}: ScreenerTableProps) {
  const [expandedCells, setExpandedCells] = useState<Set<string>>(new Set())

  // 日k列渲染尺寸（按眼睛开关取开启/收起尺寸）
  const candleCol = columns.find(c => c.source.type === 'builtin' && c.source.key === 'candle' && c.visible)
  const candleResolved = resolveCandleConfig(candleCol?.candleConfig)
  const candleSize = dailyKChartVisible
    ? { width: candleResolved.enabledWidth, height: candleResolved.enabledHeight }
    : { width: candleResolved.disabledWidth, height: candleResolved.disabledHeight }

  const toggleExpand = (key: string) => {
    setExpandedCells(prev => {
      const next = new Set(prev)
      if (next.has(key)) next.delete(key)
      else next.add(key)
      return next
    })
  }

  const renderCell = (r: any, col: ColumnConfig): ReactNode => {
    // ext 列
    if (col.source.type === 'ext') {
      const { configId, fieldName } = col.source
      const val = r[`${configId}__${fieldName}`]
      const cellKey = `${r.symbol}::${col.id}`
      const expanded = expandedCells.has(cellKey)
      const tdClass = val == null || Number.isNaN(val)
        ? 'px-3 py-2 text-center text-muted'
        : typeof val === 'number'
          ? 'px-3 py-2 text-right num tabular-nums'
          : 'px-3 py-2 text-center'
      const style: CSSProperties = {}
      if (col.extDisplay?.maxWidth) style.maxWidth = col.extDisplay.maxWidth
      return (
        <td key={col.id} className={tdClass} style={style}>
          {renderExtValue(val, col, expanded, () => toggleExpand(cellKey))}
        </td>
      )
    }

    const isExpired = !!r._expired
    const key = col.source.key

    // 策略页特有 / 需上下文的列
    switch (key) {
      case 'symbol': {
        const board = boardTag(r.symbol)
        const inWatchlist = watchlistSet.has(r.symbol)
        return (
          <td key={col.id} className="px-4 py-2">
            <div className="flex items-center gap-2">
              <button
                type="button"
                onClick={() => onPreview(r.symbol, r.name ?? '')}
                className={`flex items-center gap-2 text-left ${isExpired ? 'cursor-default' : ''}`}
              >
                {board ? (
                  <span className={`shrink-0 inline-flex items-center justify-center w-[18px] h-[18px] rounded text-[9px] font-bold leading-none border ${board.color}`}>
                    {board.label}
                  </span>
                ) : (
                  <span className="shrink-0 w-[18px]" />
                )}
                <span className="font-mono text-secondary group-hover:text-accent transition-colors duration-150 leading-snug">
                  {r.symbol}
                </span>
                {r.name && (
                  <span className="text-[11px] text-muted truncate group-hover:text-secondary transition-colors duration-150 leading-snug">
                    {r.name}
                  </span>
                )}
              </button>
              {isExpired ? (
                <span className="shrink-0 inline-flex items-center px-1.5 py-px rounded text-[9px] font-medium leading-tight bg-red-500/10 text-red-400/60 border border-red-500/15">
                  失效
                </span>
              ) : (
                <button
                  type="button"
                  onClick={() => onToggleWatchlist(r.symbol, inWatchlist)}
                  disabled={watchlistPending}
                  className={`shrink-0 inline-flex items-center justify-center w-5 h-5 rounded-full border transition-colors cursor-pointer
                    disabled:opacity-50
                    ${inWatchlist
                      ? 'border-accent/40 bg-accent/10 text-accent'
                      : 'border-border text-muted hover:border-accent/40 hover:text-accent'
                    }`}
                  title={inWatchlist ? '移出自选' : '加入自选'}
                >
                  {inWatchlist ? <Check className="h-3 w-3" /> : <Plus className="h-3 w-3" />}
                </button>
              )}
            </div>
          </td>
        )
      }
      case 'strategies': {
        const strats = symbolStrategyMap.get(r.symbol) ?? (activeStrategy ? [activeStrategy] : [])
        const tags = strats.map(sid => strategyIdToName[sid] ?? sid)
        const cellKey = `${r.symbol}::${col.id}`
        const expanded = expandedCells.has(cellKey)
        return (
          <td key={col.id} className="px-3 py-2">
            {renderTagList(tags, col, expanded, () => toggleExpand(cellKey), STRATEGY_TAG_CLS)}
          </td>
        )
      }
      case 'score': {
        const numCls = 'px-3 py-2 text-right num tabular-nums'
        return (
          <td key={col.id} className={numCls}>
            {r.score != null ? (
              <span className={r.score >= 70 ? 'text-accent font-medium' : r.score >= 50 ? 'text-amber-400' : 'text-secondary'}>
                {Number(r.score).toFixed(1)}
              </span>
            ) : (
              <span className="text-muted">—</span>
            )}
          </td>
        )
      }
      case 'signals': {
        const signals = getSignals(r)
        return (
          <td key={col.id} className="px-3 py-2">
            {signals.length > 0 ? (
              <div className="flex flex-wrap gap-0.5">
                {signals.slice(0, 3).map((s) => (
                  <span key={s.label} className={`inline-block px-1.5 py-px rounded text-[10px] font-medium leading-tight ${signalCls(s.type)}`}>
                    {s.label}
                  </span>
                ))}
                {signals.length > 3 && (
                  <span className="text-[10px] text-muted">+{signals.length - 3}</span>
                )}
              </div>
            ) : (
              <span className="text-muted text-xs">—</span>
            )}
          </td>
        )
      }
      case 'candle': {
        const candleRows = klineData[r.symbol] ?? []
        // 锁定列宽与行高：minWidth=maxWidth 防止 kline 加载前后整列宽度跳动（闪烁）
        return (
          <td
            key={col.id}
            className="px-3 py-2"
            style={{ width: candleSize.width, minWidth: candleSize.width, maxWidth: candleSize.width, height: candleSize.height }}
          >
            <MiniCandlestick rows={candleRows} width={candleSize.width} height={candleSize.height} />
          </td>
        )
      }
      default:
        // 纯数据列 → 共享原语
        return renderBuiltinDataCell(r, col)
    }
  }

  return (
    <StockDataTable
      columns={columns}
      rows={rows}
      renderCell={renderCell}
      sort={sort}
      onSortToggle={onSortToggle}
      minWidth={Math.max(900, columns.filter(c => c.visible).length * 110)}
      rowKey={(r: any) => `${r.symbol}${r._expired ? '-expired' : ''}`}
      rowClassName={(r: any) => r._expired
        ? 'border-border/50 opacity-40'
        : 'border-border hover:bg-elevated/50'
      }
      // 日k列表头：标签 + 显示/隐藏蜡烛图眼睛按钮（与自选页一致）
      renderHeaderContent={onToggleDailyKChart ? (col) => {
        if (col.source.type === 'builtin' && col.source.key === 'candle') {
          return (
            <span className="inline-flex items-center justify-center gap-1.5">
              <span>{col.label}</span>
              <button
                type="button"
                onClick={(event) => { event.stopPropagation(); onToggleDailyKChart() }}
                className={`inline-flex items-center justify-center w-5 h-5 rounded transition-colors ${
                  dailyKChartVisible
                    ? 'text-accent bg-accent/10 hover:bg-accent/20'
                    : 'text-muted hover:text-foreground hover:bg-elevated'
                }`}
                title={dailyKChartVisible ? '隐藏日k蜡烛' : '显示日k蜡烛'}
                aria-label={dailyKChartVisible ? '隐藏日k蜡烛' : '显示日k蜡烛'}
              >
                {dailyKChartVisible ? <Eye className="h-3.5 w-3.5" /> : <EyeOff className="h-3.5 w-3.5" />}
              </button>
            </span>
          )
        }
        return undefined
      } : undefined}
    />
  )
}
