<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useTask } from '@/composables/useTask'
import { getLog } from '@/api/backtest'

const route = useRoute()
const router = useRouter()
const taskId = String(route.params.id)
const isFactor = computed(() => route.path.startsWith('/factor'))
const isOptimize = computed(() => taskId.startsWith('opt_'))

const { status, stage, start } = useTask(taskId)

// 同时拉日志（3s）
const logText = ref('')
const logBox = ref<HTMLElement | null>(null)
let logTimer: ReturnType<typeof setInterval> | null = null

async function pullLog(): Promise<void> {
  try {
    logText.value = await getLog(taskId)
    await nextTick()
    if (logBox.value) logBox.value.scrollTop = logBox.value.scrollHeight
  } catch {
    /* log optional */
  }
}

onMounted(() => {
  start()
  void pullLog()
  logTimer = setInterval(pullLog, 3000)
})
onUnmounted(() => {
  if (logTimer) clearInterval(logTimer)
})

watch(status, (s) => {
  if (s === 'done') {
    if (isFactor.value) {
      router.push(`/factor/result/${taskId}`)
    } else if (isOptimize.value) {
      router.push(`/backtest/optimize-result/${taskId}`)
    } else {
      router.push(`/backtest/result/${taskId}`)
    }
  }
})

// 步骤推导
interface Step { key: string; label: string }
const steps: Step[] = [
  { key: 'submit', label: '任务提交' },
  { key: 'data', label: '数据加载' },
  { key: 'run', label: '回测执行' },
  { key: 'metrics', label: '指标计算' },
  { key: 'done', label: '完成' },
]

function stepState(idx: number): 'done' | 'active' | 'pending' {
  const s = status.value
  if (s === 'done') return 'done'
  if (s === 'failed') {
    // 失败：当前进行到的步骤标 active(红)，之前标 done
    return idx < currentIdx.value ? 'done' : idx === currentIdx.value ? 'active' : 'pending'
  }
  if (idx < currentIdx.value) return 'done'
  if (idx === currentIdx.value) return 'active'
  return 'pending'
}

const currentIdx = computed(() => {
  const st = (stage.value || '').toLowerCase()
  const s = status.value
  if (s === 'done') return steps.length - 1
  if (s === 'pending' || s === 'unknown') return 0
  if (st.includes('metric') || st.includes('指标')) return 3
  if (st.includes('run') || st.includes('backtest') || st.includes('回测')) return 2
  if (st.includes('data') || st.includes('load') || st.includes('数据')) return 1
  return 1
})

const pct = computed(() => {
  if (status.value === 'done') return 100
  if (status.value === 'failed') return Math.round((currentIdx.value / (steps.length - 1)) * 100)
  return Math.round((currentIdx.value / (steps.length - 1)) * 100)
})

const statusLabel: Record<string, string> = { running: '运行中', done: '完成', failed: '失败', pending: '排队中', unknown: '初始化' }
const statusChipClass: Record<string, string> = { running: 'st-running', done: 'st-done', failed: 'st-failed', pending: 'st-pending', unknown: 'st-pending' }
</script>

<template>
  <div class="page progress-page">
    <div class="page-head">
      <div>
        <h2 class="page-title">{{ isFactor ? '因子分析' : isOptimize ? '参数优化' : '回测' }}进行中</h2>
        <p class="page-subtitle">任务 ID：<span class="mono">{{ taskId }}</span></p>
      </div>
      <span class="chip" :class="statusChipClass[status]">{{ statusLabel[status] }}</span>
    </div>

    <!-- 进度条 -->
    <el-card class="blk" shadow="never">
      <el-progress
        :percentage="pct"
        :status="status === 'failed' ? 'exception' : status === 'done' ? 'success' : undefined"
        :stroke-width="10"
      />
      <div class="stage-text muted">当前阶段：{{ stage || '—' }}</div>
    </el-card>

    <!-- 步骤时间线 -->
    <el-card class="blk" shadow="never">
      <template #header><span class="section-title">执行步骤</span></template>
      <div class="timeline">
        <div
          v-for="(s, i) in steps" :key="s.key"
          class="tl-node"
          :class="[stepState(i), { failed: status === 'failed' && i === currentIdx }]"
          :style="{ flex: i === steps.length - 1 ? '0 0 auto' : '1' }"
        >
          <div class="tl-dot">
            <span v-if="stepState(i) === 'done'">✓</span>
            <span v-else>{{ i + 1 }}</span>
          </div>
          <div class="tl-label">{{ s.label }}</div>
          <div v-if="i < steps.length - 1" class="tl-bar" />
        </div>
      </div>
    </el-card>

    <!-- 日志 -->
    <el-card class="blk" shadow="never">
      <template #header><span class="section-title">运行日志 <em class="muted">（每 3s 刷新）</em></span></template>
      <div ref="logBox" class="log-box">
        <pre v-if="logText">{{ logText }}</pre>
        <span v-else class="muted">暂无日志输出…</span>
      </div>
    </el-card>
  </div>
</template>

<style scoped>
.progress-page { display: flex; flex-direction: column; gap: 16px; }
.blk { border: 1px solid var(--border-2); }
.stage-text { margin-top: 10px; }

.timeline { display: flex; align-items: flex-start; }
.tl-node { display: flex; flex-direction: column; align-items: center; position: relative; padding: 0 8px; }
.tl-dot {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
  background: var(--bg-hover); color: var(--text-3);
  border: 1px solid var(--border-2);
  z-index: 1;
}
.tl-label { margin-top: 8px; font-size: 12px; color: var(--text-3); }
.tl-bar { position: absolute; top: 13px; left: 50%; width: 100%; height: 2px; background: var(--border-2); z-index: 0; }

.tl-node.done .tl-dot { background: var(--down); color: #fff; border-color: var(--down); }
.tl-node.done .tl-label { color: var(--text); }
.tl-node.done + .tl-node .tl-bar,
.tl-node.done .tl-bar { background: var(--down); }
.tl-node.active .tl-dot { background: var(--brand); color: #fff; border-color: var(--brand); }
.tl-node.active .tl-label { color: var(--brand); }
.tl-node.active.failed .tl-dot { background: var(--danger); border-color: var(--danger); }
.tl-node.active.failed .tl-label { color: var(--danger); }

.log-box {
  background: var(--bg);
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  padding: 12px;
  max-height: 360px;
  overflow: auto;
}
.log-box pre {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-all;
}
</style>
