import { useCallback, useEffect, useMemo, useState } from 'react'
import { Alert, Card, Empty, Spin, Tag, Timeline } from 'antd'
import {
  CheckCircleOutlined,
  ClockCircleOutlined,
  EditOutlined,
  FileTextOutlined,
  PlayCircleOutlined,
} from '@ant-design/icons'
import {
  intelligentEvalsApi,
  type DecisionLog,
  type ExecutionProgress,
  type IntelligentEval,
  type IntelligentEvalMessage,
  type IntelligentEvalSession,
  type TaskQueueItem,
} from '../../api'
import { SESSION_STATUS, decisionTypeOf } from './status'
import { colors, statusColors } from '../../tokens'
import { formatDateTime } from '../../utils/date'
import { usePolling } from '../../hooks/usePolling'

const ACTIVE_STATUSES = new Set(['planning', 'pending_approval', 'executing'])

const STAGE_CONFIG = [
  { key: 'planning', title: '规划', icon: EditOutlined },
  { key: 'approval', title: '审批', icon: FileTextOutlined },
  { key: 'executing', title: '执行', icon: PlayCircleOutlined },
  { key: 'done', title: '完成', icon: CheckCircleOutlined },
]

interface ActivityEvent {
  time: string
  color: string
  text: string
}

function personaLabel(persona: Record<string, unknown>): string {
  if (typeof persona.name === 'string' && persona.name) return persona.name
  if (typeof persona.background === 'string' && persona.background) return persona.background
  return '虚拟用户'
}

function sessionEvents(ev: IntelligentEval): ActivityEvent[] {
  const events: ActivityEvent[] = []
  for (const s of ev.sessions ?? []) {
    if (s.created_at) {
      events.push({
        time: s.created_at,
        color: 'blue',
        text: `创建会话：${personaLabel(s.persona)} · 目标「${s.goal}」`,
      })
    }
    if (s.closed_at) {
      const meta = SESSION_STATUS[s.status] ?? { label: s.status, color: 'default' }
      events.push({
        time: s.closed_at,
        color: s.status === 'completed' ? 'green' : s.status === 'failed' ? 'red' : 'gray',
        text: `会话结束（${meta.label}）：${personaLabel(s.persona)} · ${s.turn_count} 轮`,
      })
    }
  }
  return events
}

function taskEvents(tasks: TaskQueueItem[]): ActivityEvent[] {
  const events: ActivityEvent[] = []
  for (const t of tasks) {
    if (t.created_at) {
      events.push({ time: t.created_at, color: 'gray', text: `任务入队：${t.reason}` })
    }
    if (t.assigned_at) {
      events.push({ time: t.assigned_at, color: 'blue', text: '任务被 worker 认领' })
    }
    if (t.status === 'completed' && t.completed_at) {
      events.push({ time: t.completed_at, color: 'green', text: '任务完成' })
    }
    if (t.status === 'failed' && t.completed_at) {
      events.push({ time: t.completed_at, color: 'red', text: `任务失败：${t.error ?? '未知原因'}` })
    }
  }
  return events
}

function decisionEvents(logs: DecisionLog[]): ActivityEvent[] {
  return logs
    .filter((log) => log.created_at != null)
    .map((log) => ({
      time: log.created_at as string,
      color: log.decision_type === 'start_analysis' ? 'green' : log.decision_type === 'wait' ? 'gray' : 'blue',
      text: `决策·${decisionTypeOf(log.decision_type).label}：${log.reason}`,
    }))
}

function LifecycleTimeline({ ev, currentStage, abnormal }: { ev: IntelligentEval; currentStage: string; abnormal: boolean }) {
  const currentIndex = STAGE_CONFIG.findIndex((s) => s.key === currentStage)

  // Map stages to timestamps
  const stageTimes: Record<string, string | null> = {
    planning: ev.created_at,
    approval: ev.started_at, // Approval completed when execution started
    executing: ev.started_at,
    done: ev.completed_at,
  }

  return (
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8, padding: '12px 0' }}>
      {STAGE_CONFIG.map((stage, idx) => {
        const Icon = stage.icon
        const isCompleted = idx < currentIndex
        const isCurrent = idx === currentIndex
        const isError = isCurrent && abnormal

        const bgColor = isError
          ? statusColors.failed
          : isCompleted
            ? statusColors.completed
            : isCurrent
              ? colors.primary
              : colors.bgSubtle

        const textColor = isCompleted || isCurrent ? '#fff' : colors.textSecondary
        const time = stageTimes[stage.key]

        return (
          <div key={stage.key} style={{ display: 'flex', alignItems: 'flex-start', flex: idx < STAGE_CONFIG.length - 1 ? 1 : 'none' }}>
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, minWidth: 80 }}>
              <div
                style={{
                  width: 40,
                  height: 40,
                  borderRadius: '50%',
                  background: bgColor,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  color: textColor,
                  fontSize: 18,
                  transition: 'all 0.3s',
                  border: isCurrent ? `2px solid ${colors.primary}` : 'none',
                  position: 'relative',
                }}
              >
                {isCompleted ? <CheckCircleOutlined /> : <Icon />}
                {isCurrent && (
                  <div style={{
                    position: 'absolute',
                    top: -8,
                    right: -8,
                    background: colors.primary,
                    color: '#fff',
                    fontSize: 10,
                    padding: '2px 6px',
                    borderRadius: 10,
                    whiteSpace: 'nowrap',
                    border: '2px solid #fff',
                    boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
                  }}>
                    当前
                  </div>
                )}
              </div>
              <div style={{ fontSize: 12, color: isCurrent ? colors.primary : colors.textSecondary, fontWeight: isCurrent ? 600 : 400, textAlign: 'center' }}>
                {stage.title}
              </div>
              {time && (
                <div style={{ fontSize: 11, color: colors.textMuted, textAlign: 'center', marginTop: 2 }}>
                  {formatDateTime(time)}
                </div>
              )}
            </div>
            {idx < STAGE_CONFIG.length - 1 && (
              <div
                style={{
                  flex: 1,
                  height: 2,
                  background: isCompleted ? statusColors.completed : colors.border,
                  margin: '20px 8px 0',
                  transition: 'all 0.3s',
                }}
              />
            )}
          </div>
        )
      })}
    </div>
  )
}

function TimeDistributionTable({ slots }: { slots: ExecutionProgress['slots'] }) {
  return (
    <div style={{ border: `1px solid ${colors.border}`, borderRadius: 8, overflow: 'hidden' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
        <thead>
          <tr style={{ background: colors.bgSubtle, borderBottom: `1px solid ${colors.border}` }}>
            <th style={{ padding: '10px 12px', textAlign: 'left', fontWeight: 500, fontSize: 12, color: colors.textSecondary }}>时段</th>
            <th style={{ padding: '10px 12px', textAlign: 'center', fontWeight: 500, fontSize: 12, color: colors.textSecondary }}>计划</th>
            <th style={{ padding: '10px 12px', textAlign: 'center', fontWeight: 500, fontSize: 12, color: colors.textSecondary }}>已创建</th>
            <th style={{ padding: '10px 12px', textAlign: 'center', fontWeight: 500, fontSize: 12, color: colors.textSecondary }}>已完成</th>
            <th style={{ padding: '10px 12px', textAlign: 'left', fontWeight: 500, fontSize: 12, color: colors.textSecondary, minWidth: 120 }}>进度</th>
            <th style={{ padding: '10px 12px', textAlign: 'center', fontWeight: 500, fontSize: 12, color: colors.textSecondary }}>状态</th>
          </tr>
        </thead>
        <tbody>
          {slots.map((slot) => {
            const pct = slot.planned > 0 ? Math.round((slot.completed / slot.planned) * 100) : 0
            const isComplete = slot.completed >= slot.planned && slot.planned > 0
            const isPast = slot.is_past

            return (
              <tr
                key={slot.time_slot}
                style={{
                  borderBottom: `1px solid ${colors.border}`,
                  background: slot.is_current ? `${colors.primary}08` : 'transparent',
                }}
              >
                <td style={{ padding: '12px', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontWeight: 500 }}>{slot.time_slot}</span>
                  {slot.is_current && (
                    <Tag color={colors.primary} style={{ fontSize: 11, margin: 0, padding: '0 6px' }}>
                      <ClockCircleOutlined style={{ marginRight: 2 }} />
                      当前
                    </Tag>
                  )}
                </td>
                <td style={{ padding: '12px', textAlign: 'center' }}>{slot.planned}</td>
                <td style={{ padding: '12px', textAlign: 'center', color: slot.created > 0 ? colors.text : colors.textMuted }}>
                  {slot.created}
                </td>
                <td style={{ padding: '12px', textAlign: 'center', color: slot.completed > 0 ? statusColors.completed : colors.textMuted }}>
                  {slot.completed}
                </td>
                <td style={{ padding: '12px' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <div style={{ flex: 1, height: 6, background: colors.bgSubtle, borderRadius: 3, overflow: 'hidden' }}>
                      <div
                        style={{
                          width: `${pct}%`,
                          height: '100%',
                          background: isComplete ? statusColors.completed : colors.primary,
                          borderRadius: 3,
                          transition: 'width 0.3s',
                        }}
                      />
                    </div>
                    <span style={{ fontSize: 12, color: colors.textSecondary, minWidth: 36, textAlign: 'right' }}>{pct}%</span>
                  </div>
                </td>
                <td style={{ padding: '12px', textAlign: 'center' }}>
                  {isComplete ? (
                    <Tag color={statusColors.completed} style={{ fontSize: 11, margin: 0 }}>已完成</Tag>
                  ) : isPast ? (
                    <Tag color={statusColors.failed} style={{ fontSize: 11, margin: 0 }}>未达标</Tag>
                  ) : slot.is_current ? (
                    <Tag color={colors.primary} style={{ fontSize: 11, margin: 0 }}>进行中</Tag>
                  ) : (
                    <Tag style={{ fontSize: 11, margin: 0 }}>待执行</Tag>
                  )}
                </td>
              </tr>
            )
          })}
        </tbody>
      </table>
    </div>
  )
}

const PREVIEW_MESSAGE_COUNT = 3
const PREVIEW_MAX_CHARS = 80

function truncate(text: string): string {
  return text.length > PREVIEW_MAX_CHARS ? `${text.slice(0, PREVIEW_MAX_CHARS)}…` : text
}

const ROLE_LABEL: Record<string, string> = { user: '虚拟用户', assistant: '数字员工' }

function LiveSessionsCard({
  stage,
  runningSessions,
  messagesBySession,
  nextAction,
}: {
  stage: string
  runningSessions: IntelligentEvalSession[]
  messagesBySession: Record<string, IntelligentEvalMessage[]>
  nextAction: string | null
}) {
  let body
  if (runningSessions.length > 0) {
    body = (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        {runningSessions.map((s) => {
          const messages = messagesBySession[s.id] ?? []
          return (
            <div key={s.id} style={{ border: `1px solid ${colors.border}`, borderRadius: 8, padding: 12 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                <Tag color="processing" style={{ margin: 0 }}>进行中</Tag>
                <span style={{ fontWeight: 500 }}>{personaLabel(s.persona)}</span>
                <span style={{ fontSize: 12, color: colors.textSecondary }}>目标「{s.goal}」</span>
                <span style={{ fontSize: 12, color: colors.textSecondary, marginLeft: 'auto' }}>
                  {messages.length} 条消息
                </span>
              </div>
              {messages.length === 0 ? (
                <div style={{ fontSize: 12, color: colors.textMuted }}>等待首条消息…</div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {messages.slice(-PREVIEW_MESSAGE_COUNT).map((m) => (
                    <div key={m.id} style={{ fontSize: 13, lineHeight: 1.5 }}>
                      <Tag style={{ fontSize: 11, margin: '0 6px 0 0', padding: '0 6px' }}>
                        {ROLE_LABEL[m.role] ?? m.role}
                      </Tag>
                      {truncate(m.content)}
                    </div>
                  ))}
                </div>
              )}
            </div>
          )
        })}
      </div>
    )
  } else if (stage === 'executing') {
    body = (
      <div style={{ fontSize: 13, color: colors.textSecondary }}>
        当前没有进行中的会话：{nextAction ?? '等待下一步'}
      </div>
    )
  } else if (stage === 'done') {
    body = <div style={{ fontSize: 13, color: colors.textSecondary }}>执行已结束，无进行中的会话</div>
  } else {
    body = <div style={{ fontSize: 13, color: colors.textSecondary }}>评估尚未开始执行</div>
  }

  return (
    <Card size="small" title="进行中的会话" style={{ marginBottom: 16 }}>
      {body}
    </Card>
  )
}

export default function ExecutionProcess({ ev }: { ev: IntelligentEval }) {
  const [progress, setProgress] = useState<ExecutionProgress | null>(null)
  const [logs, setLogs] = useState<DecisionLog[]>([])
  const [tasks, setTasks] = useState<TaskQueueItem[]>([])
  const [messagesBySession, setMessagesBySession] = useState<Record<string, IntelligentEvalMessage[]>>({})
  const [loading, setLoading] = useState(true)

  // 依赖稳定的 id 键而非 ev.sessions 数组身份：父组件轮询会不断替换 ev，
  // 若以数组为依赖，load 会每个轮询周期重建并触发重复全量加载。
  const runningKey = (ev.sessions ?? [])
    .filter((s) => s.status === 'running')
    .map((s) => s.id)
    .sort()
    .join('|')

  const load = useCallback(async () => {
    try {
      const [progressRes, logsRes, tasksRes] = await Promise.all([
        intelligentEvalsApi.getExecutionProgress(ev.id),
        intelligentEvalsApi.listDecisionLogs(ev.id),
        intelligentEvalsApi.listTasks({ eval_id: ev.id, limit: 100 }),
      ])
      setProgress(progressRes.data)
      setLogs(logsRes.data.logs)
      setTasks(tasksRes.data.tasks)

      const runningIds = runningKey === '' ? [] : runningKey.split('|')
      if (runningIds.length > 0) {
        const msgResults = await Promise.all(runningIds.map((sid) => intelligentEvalsApi.listMessages(ev.id, sid)))
        const next: Record<string, IntelligentEvalMessage[]> = {}
        runningIds.forEach((sid, i) => {
          next[sid] = msgResults[i].data.messages
        })
        setMessagesBySession(next)
      } else {
        setMessagesBySession({})
      }
    } finally {
      setLoading(false)
    }
  }, [ev.id, runningKey])

  useEffect(() => {
    setLoading(true)
    void load()
  }, [load])

  usePolling(() => { void load() }, 5000, ACTIVE_STATUSES.has(ev.status))

  const activities = useMemo(() => {
    const all = [...sessionEvents(ev), ...taskEvents(tasks), ...decisionEvents(logs)]
    all.sort((a, b) => (a.time < b.time ? 1 : -1))
    return all
  }, [ev, tasks, logs])

  if (loading && progress == null) {
    return <div style={{ padding: 48, textAlign: 'center' }}><Spin /></div>
  }
  if (progress == null) {
    return <Empty description="执行过程数据不可用" style={{ padding: 48 }} />
  }

  const abnormal = progress.abnormal_outcome != null
  const runningSessions = (ev.sessions ?? []).filter((s) => s.status === 'running')

  return (
    <div style={{ height: '100%', overflowY: 'auto', padding: '16px 16px 24px' }}>
      <Card size="small" title="生命周期" style={{ marginBottom: 16 }}>
        <LifecycleTimeline ev={ev} currentStage={progress.current_stage} abnormal={abnormal} />
        {progress.blocker != null && (
          <Alert
            type={abnormal ? 'error' : 'warning'}
            showIcon
            style={{ marginTop: 16 }}
            message={progress.blocker}
          />
        )}
        {progress.next_action != null && (
          <Alert
            type="info"
            showIcon
            style={{ marginTop: 12 }}
            message={`下一步：${progress.next_action}`}
          />
        )}
      </Card>

      <LiveSessionsCard
        stage={progress.current_stage}
        runningSessions={runningSessions}
        messagesBySession={messagesBySession}
        nextAction={progress.next_action}
      />

      <Card size="small" title="时段分布：计划 vs 实际" style={{ marginBottom: 16 }}>
        {progress.slots.length === 0 ? (
          <Empty description="暂无时段分布（粗计划未提交或评估未开始执行）" />
        ) : (
          <TimeDistributionTable slots={progress.slots} />
        )}
      </Card>

      <Card size="small" title="活动流" style={{ marginBottom: 16 }}>
        {activities.length === 0 ? (
          <Empty description="暂无活动" />
        ) : (
          <>
            <Timeline
              items={activities.map((a) => ({
                color: a.color,
                children: (
                  <div>
                    <div style={{ fontSize: 13, lineHeight: 1.5 }}>{a.text}</div>
                    <div style={{ fontSize: 12, color: colors.textSecondary }}>{formatDateTime(a.time)}</div>
                  </div>
                ),
              }))}
            />
            <div style={{ fontSize: 12, color: colors.textMuted, marginTop: 8 }}>
              {`共 ${activities.length} 条活动，完整决策历史见「决策过程」`}
            </div>
          </>
        )}
        {tasks.some((t) => t.status === 'failed') && (
          <div style={{ marginTop: 8 }}>
            <Tag color={statusColors.failed}>存在失败任务</Tag>
          </div>
        )}
      </Card>
    </div>
  )
}
