/**
 * EdictBoard v2.0 — 任务看板
 * 数据模型：v2.6 黑板（扁平任务，无 DAG）
 * Mock 数据用于 UI 预览
 *
 * 司马懿评审修复：
 * - P0: priority 改为 number（1-10），前端映射 label
 * - P1: 状态管线补 review/blocked（6步），VALID_TRANSITIONS 对齐后端 8 状态
 * - P2: V2Task 补 depends_on, parent_task 字段
 */
import { useState } from 'react';
import { useStore } from '../store';

// ── v2.0 Task 类型（对齐后端 tasks 表）──
export interface V2Task {
  id: string;
  title: string;
  description: string;
  status: 'pending' | 'claimed' | 'working' | 'review' | 'done' | 'failed' | 'blocked' | 'cancelled';
  assignee: string | null;
  assigned_by: string | null;
  depends_on: string | null;       // P2: 依赖任务
  parent_task: string | null;      // P2: 父任务
  priority: number;                // P0: 1-10 整数
  task_type: string;
  created_at: string;
  updated_at: string;
  claimed_at: string | null;
  completed_at: string | null;
  started_at: string | null;
  deadline: string | null;
  retry_count: number;
  max_retries: number;
  risk_level: 'low' | 'standard' | 'high' | 'critical';
  escalated: number;               // 0/1 整数，与后端一致
  // 关联数据（API 聚合或 mock）
  comments_count: number;
  outputs_count: number;
  review_status: 'none' | 'pending' | 'approved' | 'rejected' | 'rebuttal';
  latest_event: string | null;
  project_id: string;
}

// ── 状态管线（6 步，对齐后端 VALID_STATUSES）──
// blocked 不在线性管道上，用独立标记
const PIPELINE_STEPS = [
  { key: 'pending', label: '待认领', icon: '📋' },
  { key: 'claimed', label: '已认领', icon: '👤' },
  { key: 'working', label: '执行中', icon: '⚔️' },
  { key: 'review', label: '审查中', icon: '🔍' },
  { key: 'done', label: '已完成', icon: '✅' },
] as const;

// 状态在线性管线中的位置索引（用于判断 done/active/pending）
const PIPELINE_ORDER: Record<string, number> = {
  pending: 0, claimed: 1, working: 2, review: 3, done: 4,
  // 以下不在线性管道上
  failed: 2,   // 标记在 working 位置
  blocked: 2,  // 标记在 working 位置
  cancelled: -1,
};

// ── 状态元信息（8 状态全覆盖）──
const STATUS_META: Record<string, { color: string; bg: string; label: string }> = {
  pending:   { color: '#7a9aff', bg: '#0a1028', label: '待认领' },
  claimed:   { color: '#a07aff', bg: '#110a28', label: '已认领' },
  working:   { color: '#6a9eff', bg: '#0a1530', label: '执行中' },
  review:    { color: '#818cf8', bg: '#0f0a28', label: '审查中' },
  done:      { color: '#2ecc8a', bg: '#0a2018', label: '已完成' },
  failed:    { color: '#ff5270', bg: '#200a10', label: '失败' },
  blocked:   { color: '#f59e0b', bg: '#1a1508', label: '阻塞' },
  cancelled: { color: '#6b7280', bg: '#141824', label: '已取消' },
};

// P0: priority 整数映射
const PRIORITY_META: Record<number, { color: string; label: string }> = {
  1: { color: '#6b7280', label: '低' },
  2: { color: '#6b7280', label: '低' },
  3: { color: '#3b82f6', label: '中' },
  4: { color: '#3b82f6', label: '中' },
  5: { color: '#f59e0b', label: '高' },
  6: { color: '#f59e0b', label: '高' },
  7: { color: '#ff5270', label: '紧急' },
  8: { color: '#ff5270', label: '紧急' },
  9: { color: '#ff5270', label: '紧急' },
  10: { color: '#ff5270', label: '紧急' },
};

const RISK_META: Record<string, { color: string; label: string }> = {
  low:      { color: '#2ecc8a', label: '低风险' },
  standard: { color: '#6b7280', label: '标准' },
  high:     { color: '#f59e0b', label: '高风险' },
  critical: { color: '#ff5270', label: '极高风险' },
};

const REVIEW_META: Record<string, { color: string; label: string; icon: string }> = {
  none:     { color: '#6b7280', label: '无审查', icon: '' },
  pending:  { color: '#f59e0b', label: '审查中', icon: '🔍' },
  approved: { color: '#2ecc8a', label: '已通过', icon: '✅' },
  rejected: { color: '#ff5270', label: '已驳回', icon: '❌' },
  rebuttal: { color: '#818cf8', label: '反驳中', icon: '⚔️' },
};

const AGENT_EMOJI: Record<string, string> = {
  'pangtong-fujunshi': '🐦', 'simayi-challenger': '🦅', 'jiangwei-infra': '🔧',
  'guanyu-dev': '⚔️', 'zhangfei-dev': '💪', 'zhaoyun-data': '📊',
};

// ── Mock 数据 ──
const MOCK_TASKS: V2Task[] = [
  {
    id: 'task-001', title: '动量因子策略回测', description: '基于成交量的日线动量策略回测，持仓周期3-10天波段交易',
    status: 'working', assignee: 'zhangfei-dev', assigned_by: 'pangtong-fujunshi',
    depends_on: null, parent_task: null,
    priority: 7, task_type: 'backtest', created_at: '2026-05-17T08:30:00', updated_at: '2026-05-17T11:20:00',
    claimed_at: '2026-05-17T08:35:00', completed_at: null, started_at: '2026-05-17T08:36:00',
    deadline: '2026-05-17T18:00:00', retry_count: 0, max_retries: 3, risk_level: 'standard', escalated: 0,
    comments_count: 3, outputs_count: 1,
    review_status: 'pending', latest_event: '回测脚本运行中，已完成70%数据回测', project_id: 'demo',
  },
  {
    id: 'task-002', title: '分钟线数据质量检查', description: '检查沪深300成分股1分钟线数据完整性（2024-01至今）',
    status: 'done', assignee: 'zhaoyun-data', assigned_by: 'pangtong-fujunshi',
    depends_on: null, parent_task: null,
    priority: 3, task_type: 'data_verify', created_at: '2026-05-17T07:00:00', updated_at: '2026-05-17T09:15:00',
    claimed_at: '2026-05-17T07:05:00', completed_at: '2026-05-17T09:15:00', started_at: '2026-05-17T07:06:00',
    deadline: null, retry_count: 0, max_retries: 2, risk_level: 'low', escalated: 0,
    comments_count: 5, outputs_count: 2,
    review_status: 'approved', latest_event: '数据质量报告已通过审查', project_id: 'demo',
  },
  {
    id: 'task-003', title: 'vnpy网关接口升级', description: '将CTP网关从6.3.19升级到6.7.0，适配新版API',
    status: 'claimed', assignee: 'jiangwei-infra', assigned_by: 'pangtong-fujunshi',
    depends_on: null, parent_task: null,
    priority: 9, task_type: 'infra', created_at: '2026-05-17T06:00:00', updated_at: '2026-05-17T10:00:00',
    claimed_at: '2026-05-17T10:00:00', completed_at: null, started_at: null,
    deadline: '2026-05-18T18:00:00', retry_count: 0, max_retries: 2, risk_level: 'critical', escalated: 0,
    comments_count: 2, outputs_count: 0,
    review_status: 'none', latest_event: '姜维已认领，准备开始', project_id: 'demo',
  },
  {
    id: 'task-004', title: '风控规则代码审查', description: '审查止损/仓位/滑点检查模块代码质量',
    status: 'pending', assignee: null, assigned_by: 'pangtong-fujunshi',
    depends_on: 'task-006', parent_task: null,
    priority: 5, task_type: 'code_review', created_at: '2026-05-17T09:00:00', updated_at: '2026-05-17T09:00:00',
    claimed_at: null, completed_at: null, started_at: null,
    deadline: null, retry_count: 0, max_retries: 2, risk_level: 'standard', escalated: 0,
    comments_count: 0, outputs_count: 0,
    review_status: 'none', latest_event: null, project_id: 'demo',
  },
  {
    id: 'task-005', title: '策略参数优化实验', description: '使用网格搜索优化动量因子参数（lookback=5-30, threshold=0.01-0.05）',
    status: 'failed', assignee: 'zhangfei-dev', assigned_by: 'pangtong-fujunshi',
    depends_on: null, parent_task: 'task-001',
    priority: 7, task_type: 'research', created_at: '2026-05-16T14:00:00', updated_at: '2026-05-17T03:00:00',
    claimed_at: '2026-05-16T14:10:00', completed_at: null, started_at: '2026-05-16T14:12:00',
    deadline: null, retry_count: 2, max_retries: 3, risk_level: 'high', escalated: 1,
    comments_count: 8, outputs_count: 0,
    review_status: 'rebuttal', latest_event: '网格搜索内存溢出，第2次重试失败', project_id: 'demo',
  },
  {
    id: 'task-006', title: '滑点模型实现', description: '实现基于成交量加权的滑点模型，支持市价单和限价单',
    status: 'review', assignee: 'guanyu-dev', assigned_by: 'pangtong-fujunshi',
    depends_on: null, parent_task: null,
    priority: 6, task_type: 'coding', created_at: '2026-05-17T07:30:00', updated_at: '2026-05-17T11:30:00',
    claimed_at: '2026-05-17T07:45:00', completed_at: null, started_at: '2026-05-17T07:46:00',
    deadline: '2026-05-17T20:00:00', retry_count: 0, max_retries: 2, risk_level: 'standard', escalated: 0,
    comments_count: 1, outputs_count: 1,
    review_status: 'pending', latest_event: '产出已提交，等待司马懿审查', project_id: 'demo',
  },
  {
    id: 'task-007', title: '回测数据下载', description: '从 NAS 下载沪深300历史日线数据（2020-2025）',
    status: 'blocked', assignee: 'zhaoyun-data', assigned_by: 'pangtong-fujunshi',
    depends_on: 'task-003', parent_task: null,
    priority: 4, task_type: 'data', created_at: '2026-05-17T06:30:00', updated_at: '2026-05-17T10:30:00',
    claimed_at: '2026-05-17T06:35:00', completed_at: null, started_at: '2026-05-17T06:36:00',
    deadline: null, retry_count: 0, max_retries: 2, risk_level: 'low', escalated: 0,
    comments_count: 1, outputs_count: 0,
    review_status: 'none', latest_event: '等待 vnpy 网关升级完成后才能下载', project_id: 'demo',
  },
];

// ── 工具函数 ──
function timeAgo(iso: string): string {
  const diff = Date.now() - new Date(iso).getTime();
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return '刚刚';
  if (mins < 60) return `${mins}分钟前`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}小时前`;
  return `${Math.floor(hrs / 24)}天前`;
}

function formatDeadline(iso: string): string {
  const diff = new Date(iso).getTime() - Date.now();
  if (diff < 0) return '已逾期';
  const hrs = Math.floor(diff / 3600000);
  if (hrs < 1) return `${Math.floor(diff / 60000)}分钟后`;
  if (hrs < 24) return `${hrs}小时后`;
  return `${Math.floor(hrs / 24)}天后`;
}

function getPriorityLabel(p: number): { color: string; label: string } {
  return PRIORITY_META[p] || { color: '#6b7280', label: `P${p}` };
}

// ── 状态管线组件 ──
function StatusPipeline({ status }: { status: string }) {
  const isLinear = ['pending', 'claimed', 'working', 'review', 'done'].includes(status);
  const isFailed = status === 'failed';
  const isBlocked = status === 'blocked';
  const isCancelled = status === 'cancelled';
  const curIdx = PIPELINE_ORDER[status] ?? -1;

  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
      {PIPELINE_STEPS.map((stage, i) => {
        const isDone = isLinear && i < curIdx;
        const isActive = (isLinear && i === curIdx) || (isFailed && i === 2) || (isBlocked && i === 2);
        const isFailedNode = isFailed && i === 2;
        const isBlockedNode = isBlocked && i === 2;

        let bg = 'transparent';
        let borderColor = 'transparent';
        let textColor = '#6b7280';
        let icon = stage.icon;

        if (isDone) { bg = '#0a2018'; textColor = '#2ecc8a'; icon = '✓'; }
        if (isActive && !isFailedNode && !isBlockedNode) { bg = '#0a1530'; borderColor = '#6a9eff'; textColor = '#6a9eff'; }
        if (isFailedNode) { bg = '#200a10'; borderColor = '#ff5270'; textColor = '#ff5270'; icon = '✗'; }
        if (isBlockedNode) { bg = '#1a1508'; borderColor = '#f59e0b'; textColor = '#f59e0b'; icon = '🚧'; }

        return (
          <span key={stage.key} style={{ display: 'contents' }}>
            <div style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
              padding: '4px 6px', borderRadius: 6, minWidth: 44,
              background: bg, border: `1px solid ${borderColor}`,
              opacity: isDone || isActive ? 1 : isCancelled ? 0.25 : 0.35,
            }}>
              <span style={{ fontSize: 13 }}>{icon}</span>
              <span style={{ fontSize: 8, whiteSpace: 'nowrap', color: textColor, fontWeight: isActive ? 700 : 400 }}>
                {isFailedNode ? '失败' : isBlockedNode ? '阻塞' : stage.label}
              </span>
            </div>
            {i < PIPELINE_STEPS.length - 1 && (
              <span style={{ fontSize: 10, color: isDone ? '#2ecc8a44' : '#1c2236', padding: '0 1px' }}>›</span>
            )}
          </span>
        );
      })}
    </div>
  );
}

// ── 任务卡片 ──
function TaskCard({ task, onOpen }: { task: V2Task; onOpen: () => void }) {
  const sm = STATUS_META[task.status];
  const pm = getPriorityLabel(task.priority);
  const rm = RISK_META[task.risk_level];
  const rvm = REVIEW_META[task.review_status];
  const agentEmoji = task.assignee ? (AGENT_EMOJI[task.assignee] || '🤖') : '';

  return (
    <div
      onClick={onOpen}
      style={{
        background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 14,
        padding: 18, cursor: 'pointer', transition: 'border-color .15s, transform .1s, box-shadow .15s',
      }}
      onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--acc)'; e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = '0 4px 20px rgba(106,158,255,.1)'; }}
      onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}
    >
      {/* 状态管线 */}
      <StatusPipeline status={task.status} />

      {/* ID + 标题 */}
      <div style={{ fontSize: 10, color: 'var(--acc)', fontWeight: 700, letterSpacing: '.04em', margin: '8px 0 4px' }}>{task.id}</div>
      <div style={{ fontSize: 15, fontWeight: 700, lineHeight: 1.4, marginBottom: 10 }}>{task.title}</div>

      {/* 标签行 */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, alignItems: 'center', marginBottom: 8 }}>
        <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, border: `1px solid ${sm.color}44`, color: sm.color, background: sm.bg }}>{sm.label}</span>
        {task.assignee && (
          <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, border: '1px solid #6b728044', color: '#dde4f8', background: '#141824' }}>
            {agentEmoji} {task.assignee}
          </span>
        )}
        <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, border: `1px solid ${pm.color}44`, color: pm.color, background: '#141824' }}>
          {pm.label}优先级
        </span>
        {task.escalated ? 1 : 0 ? (
          <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, border: '1px solid #ff527044', color: '#ff5270', background: '#200a10' }}>
            ⚠️ 已升级
          </span>
        ) : null}
        {task.depends_on && (
          <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, border: '1px solid #f59e0b44', color: '#f59e0b', background: '#1a1508' }}>
            🔗 依赖 {task.depends_on}
          </span>
        )}
      </div>

      {/* 元信息行 */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, fontSize: 11, color: 'var(--muted)', marginBottom: 8 }}>
        <span>⏱ {timeAgo(task.updated_at)}</span>
        {task.outputs_count > 0 && <span>📦 {task.outputs_count}产出</span>}
        {task.comments_count > 0 && <span>💬 {task.comments_count}评论</span>}
        {rvm.icon && <span style={{ color: rvm.color }}>{rvm.icon}</span>}
      </div>

      {/* 最新事件 */}
      {task.latest_event && (
        <div style={{
          fontSize: 10, color: '#8899aa', lineHeight: 1.4,
          padding: '3px 6px', background: '#1a1f2e', borderRadius: 4,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', marginBottom: 8,
        }}>
          💬 {task.latest_event}
        </div>
      )}

      {/* 底部 */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderTop: '1px solid var(--line)', paddingTop: 8 }}>
        <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
          <span style={{ fontSize: 10, padding: '1px 5px', borderRadius: 3, background: `${rm.color}22`, color: rm.color }}>{rm.label}</span>
          {task.retry_count > 0 && <span style={{ fontSize: 10, color: '#f59e0b' }}>🔄 x{task.retry_count}</span>}
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          {task.deadline && (
            <span style={{ fontSize: 10, color: new Date(task.deadline).getTime() - Date.now() < 3600000 ? '#ff5270' : 'var(--muted)' }}>
              📅 {formatDeadline(task.deadline)}
            </span>
          )}
          <span style={{
            fontSize: 10, padding: '2px 8px', borderRadius: 4,
            background: 'var(--acc)11', color: 'var(--acc)', border: '1px solid var(--acc)33',
            cursor: 'pointer',
          }}>详情 →</span>
        </div>
      </div>
    </div>
  );
}

// ── 主组件 ──
export default function EdictBoard() {
  const setModalTaskId = useStore(s => s.setModalTaskId);
  const [statusFilter, setStatusFilter] = useState<string>('all');
  const [searchQuery, setSearchQuery] = useState('');

  const filters = [
    { key: 'all', label: '全部', icon: '📋' },
    { key: 'pending', label: '待认领', icon: '📋' },
    { key: 'claimed', label: '已认领', icon: '👤' },
    { key: 'working', label: '执行中', icon: '⚔️' },
    { key: 'review', label: '审查中', icon: '🔍' },
    { key: 'done', label: '已完成', icon: '✅' },
    { key: 'failed', label: '失败', icon: '❌' },
    { key: 'blocked', label: '阻塞', icon: '🚧' },
  ];

  let tasks = MOCK_TASKS;
  if (statusFilter !== 'all') tasks = tasks.filter(t => t.status === statusFilter);
  if (searchQuery.trim()) {
    const q = searchQuery.trim().toLowerCase();
    tasks = tasks.filter(t => t.title.toLowerCase().includes(q) || t.id.toLowerCase().includes(q));
  }

  // 排序：working > review > claimed > blocked > pending > failed > done
  const order: Record<string, number> = { working: 0, review: 1, claimed: 2, blocked: 3, pending: 4, failed: 5, done: 6, cancelled: 7 };
  tasks.sort((a, b) => (order[a.status] ?? 8) - (order[b.status] ?? 8));

  const counts: Record<string, number> = { all: MOCK_TASKS.length };
  MOCK_TASKS.forEach(t => { counts[t.status] = (counts[t.status] || 0) + 1; });

  // 统计
  const activeCount = MOCK_TASKS.filter(t => ['working', 'claimed', 'review'].includes(t.status)).length;
  const doneCount = MOCK_TASKS.filter(t => t.status === 'done').length;
  const failedCount = MOCK_TASKS.filter(t => ['failed', 'blocked'].includes(t.status)).length;

  return (
    <div>
      {/* 顶部统计 */}
      <div style={{ display: 'flex', gap: 10, marginBottom: 14 }}>
        <div style={{ flex: 1, padding: '10px 14px', background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10 }}>
          <div style={{ fontSize: 10, color: 'var(--muted)', marginBottom: 2 }}>活跃任务</div>
          <div style={{ fontSize: 22, fontWeight: 700, color: '#6a9eff' }}>{activeCount}</div>
        </div>
        <div style={{ flex: 1, padding: '10px 14px', background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10 }}>
          <div style={{ fontSize: 10, color: 'var(--muted)', marginBottom: 2 }}>已完成</div>
          <div style={{ fontSize: 22, fontWeight: 700, color: '#2ecc8a' }}>{doneCount}</div>
        </div>
        <div style={{ flex: 1, padding: '10px 14px', background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10 }}>
          <div style={{ fontSize: 10, color: 'var(--muted)', marginBottom: 2 }}>失败/阻塞</div>
          <div style={{ fontSize: 22, fontWeight: 700, color: '#ff5270' }}>{failedCount}</div>
        </div>
        <div style={{ flex: 1, padding: '10px 14px', background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10 }}>
          <div style={{ fontSize: 10, color: 'var(--muted)', marginBottom: 2 }}>审查中</div>
          <div style={{ fontSize: 22, fontWeight: 700, color: '#818cf8' }}>{MOCK_TASKS.filter(t => t.status === 'review').length}</div>
        </div>
      </div>

      {/* 筛选 + 搜索 */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '6px 0', flexWrap: 'wrap' }}>
        {filters.map(f => (
          <button key={f.key} onClick={() => setStatusFilter(f.key)} style={{
            padding: '3px 10px', borderRadius: 6, fontSize: 11,
            border: `1px solid ${statusFilter === f.key ? 'var(--acc)' : '#2a3550'}`,
            background: statusFilter === f.key ? 'var(--acc)22' : '#161b2e',
            color: statusFilter === f.key ? 'var(--acc)' : '#8899aa',
            cursor: 'pointer', transition: 'all .15s',
            display: 'flex', alignItems: 'center', gap: 3,
          }}>
            <span>{f.icon}</span><span>{f.label}</span>
            {(counts[f.key] || 0) > 0 && (
              <span style={{
                fontSize: 10, background: statusFilter === f.key ? 'var(--acc)' : '#2a3550',
                color: statusFilter === f.key ? '#000' : '#8899aa',
                borderRadius: 8, padding: '0 4px', minWidth: 16, textAlign: 'center',
              }}>{counts[f.key]}</span>
            )}
          </button>
        ))}
        <div style={{ marginLeft: 'auto', position: 'relative' }}>
          <input type="text" placeholder="搜索任务..." value={searchQuery}
            onChange={e => setSearchQuery(e.target.value)}
            style={{
              padding: '4px 10px 4px 28px', borderRadius: 6, fontSize: 12,
              border: '1px solid #2a3550', background: '#161b2e', color: '#c0ccdd', width: 200, outline: 'none',
            }}
          />
          <span style={{ position: 'absolute', left: 8, top: '50%', transform: 'translateY(-50%)', fontSize: 12, color: '#556' }}>🔍</span>
        </div>
      </div>

      {/* 卡片网格 */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(340px, 1fr))', gap: 12, marginTop: 12 }}>
        {tasks.map(t => (
          <TaskCard key={t.id} task={t} onOpen={() => setModalTaskId(t.id)} />
        ))}
        {tasks.length === 0 && (
          <div style={{ gridColumn: '1/-1', textAlign: 'center', padding: 40, color: 'var(--muted)' }}>
            暂无匹配任务
          </div>
        )}
      </div>
    </div>
  );
}
