/**
 * Zustand Store — 三国量化编排台状态管理
 * 基于 Edict 前端适配 moziplus 后端
 * HTTP 5s 轮询，无 WebSocket
 */

import { create } from 'zustand';
import {
  api,
  setApiProjectId,
  type Task,
  type LiveStatus,
  type AgentConfig,
  type OfficialsData,
  type AgentsStatusData,
  type MorningBrief,
  type SubConfig,
  type ChangeLogEntry,
  type TaskNode,
} from './api';

// ── v2.6 V2Task 类型（对齐后端 tasks 表）──
export interface V2Task {
  id: string;
  title: string;
  description: string | null;
  status: 'pending' | 'claimed' | 'working' | 'review' | 'done' | 'failed' | 'blocked' | 'cancelled';
  assignee: string | null;
  assigned_by: string | null;
  depends_on: string | null;
  parent_task: string | null;
  priority: number;
  task_type: string | null;
  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;
  must_haves: string | null;
  risk_level: string | null;
  estimated_duration_minutes: number | null;
  escalated: number;
  // API 聚合字段
  comments_count?: number;
  outputs_count?: number;
  review_status?: string | null;
  latest_event_detail?: string | null;
  // v2.7
  stage?: string | null;
  stages_json?: string;
  // expand=all 时附加
  comments?: any[];
  outputs?: any[];
  reviews?: any[];
  decisions?: any[];
  events?: any[];
  experiences?: any[];
}

// ── Pipeline Definition (PIPE) ──

export const PIPE = [
  { key: 'created',    dept: '主公',   icon: '👑', action: '提交' },
  { key: 'planning',   dept: '庞统',   icon: '🐦', action: '拆解' },
  { key: 'challenge',  dept: '司马懿', icon: '🦅', action: '审核' },
  { key: 'assigned',   dept: '引擎',   icon: '📮', action: '派发' },
  { key: 'executing',  dept: '将军',   icon: '⚔️', action: '执行' },
  { key: 'reviewing',  dept: '司马懿', icon: '🔎', action: '验收' },
  { key: 'done',       dept: '完成',   icon: '🏆', action: '完成' },
] as const;

export const PIPE_STATE_IDX: Record<string, number> = {
  // moziplus states
  created: 0,
  planning: 1,
  challenging: 2,
  assigned: 3,
  executing: 4,
  cancelling: 4,  // BUG-6: 同 executing 位置
  pausing: 4,     // BUG-6: 同 executing 位置
  paused: 4,
  reviewing: 5,
  completed: 6,
  failed: 4,
  cancelled: 6,
  escalated: 4,
  // legacy edict states (backward compat)
  Inbox: 0, Menxia: 1, Zhongshu: 2, Assigned: 3,
  Doing: 4, Review: 5, Done: 6, Blocked: 4, Cancelled: 6, Next: 0,
  Taizi: 0, Pending: 0,
};

export const DEPT_COLOR: Record<string, string> = {
  '主公': '#ffd700', '庞统': '#a07aff', '司马懿': '#6a9eff', '引擎': '#6aef9a',
  '张飞': '#ff5270', '关羽': '#f5c842', '赵云': '#44aaff', '姜维': '#2ecc8a',
  '诸葛亮': '#e8a040', '交付': '#2ecc8a',
};

export const STATE_LABEL: Record<string, string> = {
  created: '新建', planning: '规划中', challenging: '审核中',
  assigned: '已派发', executing: '执行中', paused: '已暂停',
  cancelling: '取消中', pausing: '暂停中',  // BUG-6
  reviewing: '验收中', completed: '已完成', failed: '已失败',
  cancelled: '已取消', escalated: '已升级',
};

export function deptColor(d: string): string {
  return DEPT_COLOR[d] || '#6a9eff';
}

export function stateLabel(t: Task): string {
  const r = t.review_round || 0;
  const s = t.status || t.state; // moziplus status or legacy edict state
  // moziplus states
  if (s === 'challenging' && r > 1) return `审核中（第${r}轮）`;
  if (s === 'planning' && r > 0) return `修订方案（第${r}轮）`;
  // plan_status refinement
  const planStatus = t.plan_status;
  if (s === 'planning' && planStatus === 'approved') return '待派发';
  if (s === 'planning' && planStatus === 'rejected') return '方案驳回';
  if (s === 'planning' && planStatus === 'challenging') return '审核中';
  // BUG-6: 中间态标签
  if (s === 'cancelling') return '⏳ 取消中';
  if (s === 'pausing') return '⏳ 暂停中';
  return STATE_LABEL[s] || s;
}

export function isEdict(t: Task): boolean {
  // moziplus tasks: UUIDs or random short IDs (M2-08); Edict tasks: TSK-xxx
  const id = t.id || '';
  return /^TSK-/i.test(id) || /^[0-9a-f]{8}-/i.test(id) || /^[A-Za-z0-9]{10,16}$/.test(id);
}

export function isSession(t: Task): boolean {
  return /^(OC-|MC-)/i.test(t.id || '');
}

export function isArchived(t: Task): boolean {
  return !!t.archived;
}

export type PipeStatus = { key: string; dept: string; icon: string; action: string; status: 'done' | 'active' | 'pending' };

export function getPipeStatus(t: Task): PipeStatus[] {
  const planStatus = t.plan_status || '';
  const nodes = t.nodes || [];
  const s = t.status || t.state; // moziplus status or legacy edict state

  let activeIdx = PIPE_STATE_IDX[s] ?? 4;

  // Refine based on moziplus sub-state
  if (s === 'planning') {
    if (planStatus === 'challenging') activeIdx = 2;       // 审核
    else if (planStatus === 'approved') activeIdx = 3;      // 派发
    else if (planStatus === 'rejected') activeIdx = 1;      // 回到拆解
    else activeIdx = 1;                                      // 拆解
  } else if (s === 'executing') {
    const hasReviewing = nodes.some((n: TaskNode) => n.status === 'reviewing');
    activeIdx = hasReviewing ? 5 : 4;                       // 验收 vs 执行
  } else if (s === 'failed' || s === 'cancelled') {
    // 根据实际失败阶段定位进度条
    if (planStatus === 'pending' || planStatus === 'rejected' || !planStatus) {
      activeIdx = 1; // 拆解阶段失败/取消
    } else if (planStatus === 'challenging') {
      activeIdx = 2; // 审核阶段失败/取消
    } else if (planStatus === 'approved') {
      activeIdx = 4; // 执行阶段失败/取消
    } else {
      activeIdx = 4; // 默认显示在执行
    }
  } else if (s === 'escalated') {
    activeIdx = 4;
  } else if (s === 'cancelling' || s === 'pausing') {
    // BUG-6: 停在执行阶段
    activeIdx = 4;
  }

  return PIPE.map((stage, i) => ({
    ...stage,
    status: (i < activeIdx ? 'done' : i === activeIdx ? 'active' : 'pending') as 'done' | 'active' | 'pending',
  }));
}

// ── Tabs ──

export type TabKey =
  | 'tasks' | 'court' | 'monitor' | 'agents'
  | 'models' | 'skills' | 'sessions' | 'archives' | 'templates'
  | 'usage' | 'settings' | 'officials' | 'morning';

export const TAB_DEFS: { key: TabKey; label: string; icon: string }[] = [
  { key: 'tasks',     label: '任务看板', icon: '📜' },
  { key: 'court',     label: '军议大厅', icon: '🏛️' },
  { key: 'monitor',   label: '编排调度', icon: '🔌' },
  { key: 'agents',    label: '将军总览', icon: '🤺' },
  { key: 'models',    label: '模型配置', icon: '🤖' },
  { key: 'skills',    label: '技能配置', icon: '🎯' },
  { key: 'sessions',  label: '传令巡哨', icon: '🔭' },
  { key: 'usage',     label: '花费总览', icon: '💰' },
  { key: 'archives',  label: '奏折阁',   icon: '📜' },
  { key: 'templates', label: '任务模板', icon: '📋' },
  { key: 'settings',  label: '系统设置', icon: '⚙️' },
];

// ── DEPTS for monitor ──

export const DEPTS = [
  { id: 'pangtong',    label: '庞统',   emoji: '🐦', role: '副军师',   rank: '凤雏' },
  { id: 'simayi',      label: '司马懿', emoji: '🦅', role: '质量总监', rank: '仲达' },
  { id: 'zhugeliang',  label: '诸葛亮', emoji: '🪶', role: '总军师',   rank: '孔明' },
  { id: 'zhangfei',    label: '张飞',   emoji: '⚔️', role: '编码先锋', rank: '翼德' },
  { id: 'guanyu',      label: '关羽',   emoji: '🗡️', role: '风控守将', rank: '云长' },
  { id: 'zhaoyun',     label: '赵云',   emoji: '🏹', role: '数据总管', rank: '子龙' },
  { id: 'jiangwei',    label: '姜维',   emoji: '🛡️', role: '平台总督', rank: '伯约' },
];

// ── Templates ──

export interface TemplateParam {
  key: string;
  label: string;
  type: 'text' | 'textarea' | 'select';
  default?: string;
  required?: boolean;
  options?: string[];
}

export interface Template {
  id: string;
  cat: string;
  icon: string;
  name: string;
  desc: string;
  depts: string[];
  est: string;
  cost: string;
  params: TemplateParam[];
  command: string;
}

export const TEMPLATES: Template[] = [
  {
    id: 'tpl-blank', cat: '快速开始', icon: '📜', name: '空白军令',
    desc: '自由输入需求描述，无预设参数',
    depts: ['庞统'], est: '自定义', cost: '自定义',
    params: [
      { key: 'requirement', label: '需求描述', type: 'textarea', required: true },
    ],
    command: '{requirement}',
  },
  {
    id: 'tpl-quant-strategy', cat: '量化策略', icon: '📈', name: '量化策略开发',
    desc: '从需求分析到回测验证的完整策略开发流程',
    depts: ['庞统', '张飞', '关羽'], est: '~60分钟', cost: '¥3',
    params: [
      { key: 'strategy_name', label: '策略名称', type: 'text', required: true },
      { key: 'universe', label: '股票池', type: 'select', options: ['沪深300', '中证500', '全A'], default: '沪深300' },
      { key: 'period', label: '回测区间', type: 'text', default: '2024-01-01 ~ 2025-12-31' },
    ],
    command: '开发量化策略「{strategy_name}」，股票池：{universe}，回测区间：{period}',
  },
  {
    id: 'tpl-data-download', cat: '数据采集', icon: '📊', name: '行情数据下载',
    desc: '批量下载A股行情数据（日线/分钟线）到NAS',
    depts: ['赵云'], est: '~30分钟', cost: '¥1',
    params: [
      { key: 'data_type', label: '数据类型', type: 'select', options: ['日线', '1分钟线', '5分钟线', 'Tick'], default: '日线' },
      { key: 'symbols', label: '股票代码', type: 'text', default: '沪深300成分股' },
      { key: 'date_range', label: '日期范围', type: 'text', required: true },
    ],
    command: '下载{data_type}数据，股票：{symbols}，日期：{date_range}',
  },
  {
    id: 'tpl-backtest', cat: '量化策略', icon: '🔬', name: '策略回测',
    desc: '对指定策略进行标准化回测，输出绩效报告',
    depts: ['姜维', '庞统'], est: '~45分钟', cost: '¥2',
    params: [
      { key: 'strategy', label: '策略文件路径', type: 'text', required: true },
      { key: 'benchmark', label: '基准', type: 'select', options: ['沪深300', '中证500', '上证50'], default: '沪深300' },
    ],
    command: '回测策略 {strategy}，基准：{benchmark}',
  },
  {
    id: 'tpl-risk-review', cat: '风控审查', icon: '🛡️', name: '风控审查',
    desc: '审查策略的风控逻辑，评估止损/仓位/滑点设置',
    depts: ['关羽', '司马懿'], est: '~20分钟', cost: '¥1.5',
    params: [
      { key: 'target', label: '审查目标', type: 'text', required: true },
      { key: 'scope', label: '审查范围', type: 'select', options: ['止损规则', '仓位管理', '滑点控制', '全部'], default: '全部' },
    ],
    command: '对 {target} 进行风控审查，范围：{scope}',
  },
  {
    id: 'tpl-code-impl', cat: '编码开发', icon: '💻', name: '编码实现',
    desc: '根据设计文档编码实现功能，强调最小实现、可运行优先',
    depts: ['张飞'], est: '~40分钟', cost: '¥2',
    params: [
      { key: 'design_doc', label: '设计文档路径', type: 'text', required: true },
      { key: 'module', label: '模块名称', type: 'text', required: true },
    ],
    command: '根据 {design_doc} 实现模块 {module}',
  },
  {
    id: 'tpl-deploy', cat: '编码开发', icon: '🚀', name: '环境部署',
    desc: '部署运行环境，安装依赖，配置服务',
    depts: ['姜维'], est: '~30分钟', cost: '¥1.5',
    params: [
      { key: 'project', label: '项目名称', type: 'text', required: true },
      { key: 'env', label: '部署环境', type: 'select', options: ['Docker', 'NAS', '本地开发'], default: 'Docker' },
    ],
    command: '部署 {project} 到 {env}',
  },
  {
    id: 'tpl-data-verify', cat: '数据采集', icon: '✅', name: '数据验证',
    desc: '验证数据完整性、正确性、质量检查',
    depts: ['赵云'], est: '~15分钟', cost: '¥0.5',
    params: [
      { key: 'data_path', label: '数据路径', type: 'text', required: true },
      { key: 'check', label: '检查项', type: 'select', options: ['完整性', '正确性', '异常值', '全部'], default: '全部' },
    ],
    command: '验证数据 {data_path}，检查：{check}',
  },
  {
    id: 'tpl-requirement', cat: '需求分析', icon: '📝', name: '需求分析',
    desc: '分析用户需求，撰写需求规格文档',
    depts: ['庞统'], est: '~20分钟', cost: '¥1',
    params: [
      { key: 'req', label: '需求描述', type: 'textarea', required: true },
      { key: 'domain', label: '领域', type: 'select', options: ['量化策略', '数据平台', '交易系统', '基础设施'], default: '量化策略' },
    ],
    command: '分析需求：{req}，领域：{domain}',
  },
  {
    id: 'tpl-code-review', cat: '风控审查', icon: '🔍', name: '代码审查',
    desc: '审查代码质量、逻辑正确性、异常处理',
    depts: ['司马懿', '关羽'], est: '~25分钟', cost: '¥1.5',
    params: [
      { key: 'repo', label: '仓库/文件路径', type: 'text', required: true },
      { key: 'scope', label: '审查范围', type: 'select', options: ['全量', '增量', '指定文件'], default: '增量' },
    ],
    command: '审查 {repo}，范围：{scope}',
  },
];

export const TPL_CATS = [
  { name: '全部', icon: '📋' },
  { name: '量化策略', icon: '📈' },
  { name: '数据采集', icon: '📊' },
  { name: '风控审查', icon: '🛡️' },
  { name: '编码开发', icon: '💻' },
  { name: '需求分析', icon: '📝' },
];

// ── Main Store ──

interface AppStore {
  // Data
  liveStatus: LiveStatus | null;
  agentConfig: AgentConfig | null;
  changeLog: ChangeLogEntry[];
  officialsData: OfficialsData | null;
  agentsStatusData: AgentsStatusData | null;
  morningBrief: MorningBrief | null;
  subConfig: SubConfig | null;

  // v2.6: 多项目
  projects: Record<string, any>;
  selectedProjectId: string | null;

  // v2.6: 原生 V2Task
  v2tasks: V2Task[];
  v2taskDetail: V2Task | null;
  v2tasksLoading: boolean;

  // UI State
  activeTab: TabKey;
  edictFilter: 'active' | 'archived' | 'all';
  statusFilter: string;
  searchQuery: string;
  sessFilter: string;
  tplCatFilter: string;
  selectedOfficial: string | null;
  modalTaskId: string | null;
  countdown: number;

  // Toast
  toasts: { id: number; msg: string; type: 'ok' | 'err' }[];

  // Actions
  setActiveTab: (tab: TabKey) => void;
  setEdictFilter: (f: 'active' | 'archived' | 'all') => void;
  setStatusFilter: (f: string) => void;
  setSearchQuery: (q: string) => void;
  setSessFilter: (f: string) => void;
  setTplCatFilter: (f: string) => void;
  setSelectedOfficial: (id: string | null) => void;
  setModalTaskId: (id: string | null) => void;
  setCountdown: (n: number) => void;
  setSelectedProjectId: (pid: string | null) => void;
  toast: (msg: string, type?: 'ok' | 'err') => void;

  // v2.6 V2Task actions
  loadV2Tasks: () => Promise<void>;
  loadV2TaskDetail: (taskId: string) => Promise<void>;

  // Data fetching
  loadLive: () => Promise<void>;
  loadProjects: () => Promise<void>;
  loadAgentConfig: () => Promise<void>;
  loadOfficials: () => Promise<void>;
  loadAgentsStatus: () => Promise<void>;
  loadMorning: () => Promise<void>;
  loadSubConfig: () => Promise<void>;
  loadAll: () => Promise<void>;
}

let _toastId = 0;

export const useStore = create<AppStore>((set, get) => ({
  liveStatus: null,
  agentConfig: null,
  changeLog: [],
  officialsData: null,
  agentsStatusData: null,
  morningBrief: null,
  subConfig: null,

  // v2.6: 多项目
  projects: {},
  selectedProjectId: null,

  // v2.6: 原生 V2Task
  v2tasks: [],
  v2taskDetail: null,
  v2tasksLoading: false,

  activeTab: 'tasks',
  edictFilter: 'active',
  statusFilter: 'all',
  searchQuery: '',
  sessFilter: 'all',
  tplCatFilter: '全部',
  selectedOfficial: null,
  modalTaskId: null,
  countdown: 5,

  toasts: [],

  setActiveTab: (tab) => {
    set({ activeTab: tab });
    const s = get();
    if (['models', 'skills', 'sessions'].includes(tab) && !s.agentConfig) s.loadAgentConfig();
    if (tab === 'officials' && !s.officialsData) s.loadOfficials();
    if (tab === 'monitor') s.loadAgentsStatus();
    if (tab === 'morning' && !s.morningBrief) s.loadMorning();
  },
  setEdictFilter: (f) => set({ edictFilter: f }),
  setStatusFilter: (f) => set({ statusFilter: f }),
  setSearchQuery: (q) => set({ searchQuery: q }),
  setSessFilter: (f) => set({ sessFilter: f }),
  setTplCatFilter: (f) => set({ tplCatFilter: f }),
  setSelectedOfficial: (id) => set({ selectedOfficial: id }),
  setModalTaskId: (id) => set({ modalTaskId: id }),
  setCountdown: (n) => set({ countdown: n }),
  setSelectedProjectId: (pid) => {
    set({ selectedProjectId: pid });
    setApiProjectId(pid);
    // 切换项目后重新加载
    get().loadLive();
    get().loadV2Tasks();
  },

  toast: (msg, type = 'ok') => {
    const id = ++_toastId;
    set((s) => ({ toasts: [...s.toasts, { id, msg, type }] }));
    setTimeout(() => {
      set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) }));
    }, 3000);
  },

  // v2.6: 加载项目任务列表（含聚合统计）
  loadV2Tasks: async () => {
    const pid = get().selectedProjectId;
    if (!pid) { set({ v2tasks: [] }); return; }
    set({ v2tasksLoading: true });
    try {
      const res = await fetch(`/api/projects/${pid}/tasks`);
      if (!res.ok) { set({ v2tasks: [], v2tasksLoading: false }); return; }
      const data = await res.json();
      const tasks = data.tasks || [];
      // 批量获取每个任务的聚合字段
      // TODO: 后端应提供 list?expand=summary 接口，避免 N+1
      const enriched = await Promise.all(tasks.map(async (t: any) => {
        try {
          const r = await fetch(`/api/projects/${pid}/tasks/${t.id}`);
          if (r.ok) {
            const detail = await r.json();
            return { ...t, ...detail };
          }
        } catch { /* skip */ }
        return t;
      }));
      set({ v2tasks: enriched });
    } catch { /* silently fail */ }
    finally { set({ v2tasksLoading: false }); }
  },

  // v2.6: 加载任务详情（expand=all）
  loadV2TaskDetail: async (taskId: string) => {
    const pid = get().selectedProjectId;
    if (!pid) return;
    try {
      const res = await fetch(`/api/projects/${pid}/tasks/${taskId}?expand=all`);
      if (res.ok) {
        const task = await res.json();
        set({ v2taskDetail: task });
      }
    } catch { /* silently fail */ }
  },

  loadLive: async () => {
    try {
      const data = await api.liveStatus();
      set({ liveStatus: data });
      // 同步项目列表
      const projects = (data.syncStatus as any)?.projects?.projects || {};
      set({ projects });
      // 自动选择第一个项目
      const s = get();
      if (!s.selectedProjectId && Object.keys(projects).length > 0) {
        const firstPid = Object.keys(projects)[0];
        set({ selectedProjectId: firstPid });
        setApiProjectId(firstPid);
      }
      // Also preload officials for monitor tab
      if (!s.officialsData) {
        api.officialsStats().then((d) => set({ officialsData: d })).catch(() => {});
      }
    } catch {
      // silently fail
    }
  },

  loadProjects: async () => {
    try {
      const data = await api.projects();
      set({ projects: data.projects });
      const s = get();
      // 如果当前 selectedProjectId 不在项目列表里，重新选择
      if (!s.selectedProjectId || !(s.selectedProjectId in data.projects)) {
        if (Object.keys(data.projects).length > 0) {
          const firstPid = Object.keys(data.projects)[0];
          set({ selectedProjectId: firstPid });
          setApiProjectId(firstPid);
        }
      }
    } catch {
      // silently fail
    }
  },

  loadAgentConfig: async () => {
    try {
      const cfg = await api.agentConfig();
      const log = await api.modelChangeLog();
      set({ agentConfig: cfg, changeLog: log });
    } catch {
      // silently fail
    }
  },

  loadOfficials: async () => {
    try {
      const data = await api.officialsStats();
      set({ officialsData: data });
    } catch {
      // silently fail
    }
  },

  loadAgentsStatus: async () => {
    try {
      const data = await api.agentsStatus();
      set({ agentsStatusData: data });
    } catch {
      set({ agentsStatusData: null });
    }
  },

  loadMorning: async () => {
    try {
      const [brief, config] = await Promise.all([api.morningBrief(), api.morningConfig()]);
      set({ morningBrief: brief, subConfig: config });
    } catch {
      // silently fail
    }
  },

  loadSubConfig: async () => {
    try {
      const config = await api.morningConfig();
      set({ subConfig: config });
    } catch {
      // silently fail
    }
  },

  loadAll: async () => {
    const s = get();
    await s.loadLive();
    await s.loadProjects();  // 确保 selectedProjectId 被设置
    await s.loadV2Tasks();
    const tab = s.activeTab;
    if (['models', 'skills'].includes(tab)) await s.loadAgentConfig();
  },
}));

// ── Countdown & Polling ──

let _cdTimer: ReturnType<typeof setInterval> | null = null;

export function startPolling() {
  if (_cdTimer) return;
  useStore.getState().loadAll();
  _cdTimer = setInterval(() => {
    const s = useStore.getState();
    const cd = s.countdown - 1;
    if (cd <= 0) {
      s.setCountdown(5);
      s.loadAll();
    } else {
      s.setCountdown(cd);
    }
  }, 1000);
}

export function stopPolling() {
  if (_cdTimer) {
    clearInterval(_cdTimer);
    _cdTimer = null;
  }
}

// ── Utility ──

export function esc(s: string | undefined | null): string {
  if (!s) return '';
  return String(s)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

export function timeAgo(iso: string | undefined): string {
  if (!iso) return '';
  try {
    const d = new Date(iso.includes('T') ? iso : iso.replace(' ', 'T') + 'Z');
    if (isNaN(d.getTime())) return '';
    const diff = Date.now() - d.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) + '天前';
  } catch {
    return '';
  }
}
