import { Tooltip } from 'antd'
import type { ReactNode } from 'react'
import { colors, fontSizes } from '../tokens'

// A read-only horizontal timeline: one axis representing a service-cycle window,
// with markers positioned by their window offset. It is domain-agnostic — the
// ②计划预览 and ④过程时间轴 callers each adapt their data into markers. Colours
// are assigned stably per `colorKey` (same key → same colour, order-independent).

export interface TimelineMarker {
  key: string
  offsetSeconds: number
  colorKey: string
  label?: string
  badge?: number | string
  tooltip: ReactNode
  onClick?: () => void
}

interface WindowTimelineProps {
  windowSeconds: number
  markers: TimelineMarker[]
  /** colorKey → explicit colour; keys not present fall back to the auto palette. */
  colorMap?: Record<string, string>
  /** colorKey → legend display name; falls back to the raw key. */
  colorLabels?: Record<string, string>
  showLegend?: boolean
  height?: number
  /** Spread markers that would overlap onto separate vertical rows. */
  stagger?: boolean
}

const PALETTE = [
  '#1677ff', '#52c41a', '#fa8c16', '#722ed1',
  '#13c2c2', '#eb2f96', '#faad14', '#2f54eb',
]

const TICK_COUNT = 6

/** Markers closer than this fraction of the window collide and need their own row. */
const STAGGER_GAP = 0.04
const STAGGER_ROW_PX = 16

export function fmtTick(seconds: number): string {
  if (seconds < 3600) return `${Math.round(seconds / 60)}m`
  const h = seconds / 3600
  return `${Number.isInteger(h) ? h : h.toFixed(1)}h`
}

export default function WindowTimeline({
  windowSeconds, markers, colorMap, colorLabels, showLegend = false, height = 64, stagger = false,
}: WindowTimelineProps) {
  const window = windowSeconds > 0 ? windowSeconds : 1
  const uniqueKeys = Array.from(new Set(markers.map((m) => m.colorKey))).sort()
  const colorOf = (key: string) =>
    colorMap?.[key] ?? PALETTE[Math.max(0, uniqueKeys.indexOf(key)) % PALETTE.length]
  const leftPct = (offset: number) => `${Math.min(1, Math.max(0, offset / window)) * 100}%`

  // Greedy row assignment in offset order: a marker joins the first row whose
  // previous marker is far enough away, otherwise it opens a new row.
  const slotOf: number[] = markers.map(() => 0)
  let rowCount = 1
  if (stagger) {
    const lastEnd: number[] = []
    const order = markers.map((_, i) => i).sort((a, b) => markers[a].offsetSeconds - markers[b].offsetSeconds)
    for (const i of order) {
      const off = markers[i].offsetSeconds
      let s = lastEnd.findIndex((last) => off - last >= STAGGER_GAP * window)
      if (s === -1) {
        s = lastEnd.length
        lastEnd.push(0)
      }
      lastEnd[s] = off
      slotOf[i] = s
    }
    rowCount = Math.max(1, lastEnd.length)
  }
  const rowY = (slot: number) => (slot - (rowCount - 1) / 2) * STAGGER_ROW_PX
  const trackHeight = rowCount > 1 ? 24 + rowCount * STAGGER_ROW_PX : height

  const ticks = Array.from({ length: TICK_COUNT + 1 }, (_, i) => i / TICK_COUNT)

  return (
    <div>
      <div style={{ position: 'relative', height: trackHeight, margin: '0 12px' }}>
        <div style={{
          position: 'absolute', left: 0, right: 0, top: '50%',
          height: 2, background: colors.border,
        }} />

        {ticks.map((t) => (
          <div key={t} style={{ position: 'absolute', left: `${t * 100}%`, top: 0, bottom: 0 }}>
            <div style={{
              position: 'absolute', top: '50%', width: 1, height: 8,
              marginTop: -4, background: colors.textMuted,
            }} />
            <span style={{
              position: 'absolute', top: '50%', marginTop: 8, transform: 'translateX(-50%)',
              fontSize: fontSizes.meta, color: colors.textMuted, whiteSpace: 'nowrap',
            }}>
              {fmtTick(t * window)}
            </span>
          </div>
        ))}

        {markers.map((m, idx) => {
          const c = colorOf(m.colorKey)
          return (
            <Tooltip key={m.key} title={m.tooltip}>
              <div
                onClick={m.onClick}
                style={{
                  position: 'absolute', left: leftPct(m.offsetSeconds), top: '50%',
                  transform: `translate(-50%, -50%)${stagger ? ` translateY(${rowY(slotOf[idx])}px)` : ''}`,
                  cursor: m.onClick ? 'pointer' : 'default',
                }}
              >
                {m.label != null ? (
                  <span style={{
                    padding: '1px 6px', borderRadius: 10, background: c, color: '#fff',
                    fontSize: fontSizes.meta, whiteSpace: 'nowrap',
                  }}>
                    {m.label}
                    {m.badge != null && <b style={{ marginLeft: 4 }}>{m.badge}</b>}
                  </span>
                ) : (
                  <span style={{
                    display: 'block', width: 12, height: 12, borderRadius: '50%',
                    background: c, border: '2px solid #fff', boxShadow: '0 0 0 1px rgba(0,0,0,0.1)',
                  }} />
                )}
              </div>
            </Tooltip>
          )
        })}
      </div>

      {showLegend && uniqueKeys.length > 0 && (
        <div style={{
          display: 'flex', flexWrap: 'wrap', gap: 12, marginTop: 24,
          fontSize: fontSizes.meta, color: colors.textSecondary,
        }}>
          {uniqueKeys.map((k) => (
            <span key={k} style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
              <span style={{ width: 10, height: 10, borderRadius: 2, background: colorOf(k) }} />
              {colorLabels?.[k] ?? k}
            </span>
          ))}
        </div>
      )}
    </div>
  )
}
