import { useCallback, useEffect, useRef, useState } from 'react';
import Button from '../components/Button';
import Modal from '../components/Modal';
import Tabs from '../components/Tabs';
import ChatInput from '../components/ChatInput';
import Icon from '../components/Icon';
import ChatMessage, {
  DEFAULT_CHAT_FORM_CONFIRM,
  DEFAULT_CHAT_RESULT,
  DEFAULT_CHAT_RESULT_ARTIFACTS,
  DEFAULT_CHAT_TASK_GROUPS,
  DEFAULT_CHAT_THINKING,
  useStreamingTaskGroups,
} from '../components/ChatMessage';
import catcatSvg from '../components/file-type-assets/catcat.svg';
import CopilotArtifactDetailPanel from './shared/CopilotArtifactDetailPanel';
import { resolveArtifactDetailDemoContent } from './shared/artifact-detail-content';
import ChatArtifactSplitLayout, { CHAT_ARTIFACT_SPLIT_COLUMN_GAP } from './shared/ChatArtifactSplitLayout';
import StrategyListPage from './StrategyListPage';
import BatchAttributionPage from './BatchAttributionPage';
import RuntimeDataPage from './RuntimeDataPage';

/**
 * CopilotPagePattern — B端 Copilot + 内容区 双栏模板
 *
 * 基于 Figma 设计稿 243-9115（无 Copilot）/ 243-9162（有 Copilot）还原。
 *
 * 布局：
 *   顶导栏（shrink-0）：左侧返回+标题+AI触发按钮 | 居中胶囊Tab | 右侧操作组
 *   内容区（flex-1）：
 *     [AI按钮展开] Copilot 侧栏 + 右侧详情 `ChatArtifactSplitLayout` 可拖拽分栏
 *     主内容白卡（flex-1，内部有二级Tab+操作栏）
 *
 * 交互：点击顶导栏 Copilot 触发按钮 ↔ 切换侧栏展开/收起
 * 右侧详情：CopilotArtifactDetailPanel + 顶栏 Tab 对应业务面板（服务策略 / 批测&归因 / 运行数据）
 *
 * @prop {string} [platformName='抖音社区'] — 顶导栏页面标题（真实业务场景名）
 * @prop {string} [assistantName='AI Copilot'] — 侧栏欢迎态与 AI 消息 header 的助手名称
 */

const PAGE_TAB_PANELS = [
  {
    label: '服务策略',
    iconName: 'share-07-stroked',
    headerActionLabel: '分享',
    Panel: StrategyListPage,
  },
  {
    label: '批测&归因',
    iconName: 'file-07-stroked',
    headerActionLabel: '导出报告',
    Panel: BatchAttributionPage,
  },
  {
    label: '运行数据',
    iconName: 'pie-chart-01-stroked',
    headerActionLabel: '分享',
    Panel: RuntimeDataPage,
  },
];

/* ── 顶导栏中间的一级页面 Tab ── */
const PAGE_TABS = PAGE_TAB_PANELS.map(({ label, iconName }) => ({
  label,
  icon: <Icon name={iconName} />,
}));

/* ── Copilot 快捷建议 ── */
const COPILOT_SUGGESTIONS = [
  '分析智能会话与人工会话差异',
  '分析总结智能会话的问题和机会点',
  '分析一个 case',
  '基于批测报告分析优化方向和问题',
];

const STREAM_INTERVAL = 600;
const AUTO_FLOW_TIMINGS = {
  thinkingDone: 900,
  confirmShow: 1400,
};

const DEFAULT_COPILOT_PLATFORM_NAME = '抖音社区';
const DEFAULT_COPILOT_ASSISTANT_NAME = 'AI Copilot';
/** 顶导栏与内容区左右页面边距（与 CHAT_CONVERSATION_PAGE_PADDING 对齐） */
const COPILOT_PAGE_GUTTER_X = 16;
/** 底部输入区：水平 inset 由外层内容区承担，与消息流同宽 */
const COPILOT_CHAT_INPUT_FOOTER = 'relative z-10 w-full shrink-0 pt-2 pb-2';
const TOP_BAR_TABS_SIDE_MIN = 12;
const TOP_BAR_SECTION_GAP = 16;

function normalizeDisplayName(value, fallback) {
  if (typeof value === 'string' && value.trim()) return value.trim();
  return fallback;
}

function buildAiHeader(assistantName) {
  return {
    name: assistantName,
    avatarSrc: catcatSvg,
  };
}

const DEFAULT_CONVERSATION_CONTEXT = {
  account: '抖音社区',
  environment: '服务策略 / 线上策略 V8',
  mock: '近 7 天私信会话样本 186 条',
  conclusion: '上一轮已沉淀私信场景的服务策略问题清单，可继续追问优化方向。',
  artifacts: DEFAULT_CHAT_RESULT_ARTIFACTS.map((item) => item.title),
};

const TASK_KEYWORDS = ['整理', '分析', '生成', '梳理', '输出', '汇总', '优化'];
const STOP_KEYWORDS = ['停止', '取消'];
const GENERIC_REPLIES = [
  '收到，我会结合当前策略上下文继续处理。',
  '明白了，我先按这个方向帮你梳理。',
  '可以，我会基于当前私信场景继续补充分析。',
  '没问题，我先整理成可执行的建议给你。',
];

const FOLLOW_UP_REPLIES = {
  查看风险样本: {
    resultText:
      '已筛出 12 条高风险私信样本，主要集中在「用户情绪升级但意图识别偏弱」和「跨轮追问时上下文衔接不足」两类问题。建议优先补强情绪识别权重、补齐意图转人工闸门，并针对高投诉场景增加策略兜底。',
    resultArtifacts: [
      { id: 'risk-samples', type: 'table', title: '高风险私信样本明细', meta: '表格 · 12 条' },
      { id: 'risk-summary', type: 'document', title: '问题样本归因摘要', meta: '文档 · 2 页' },
    ],
    followUps: ['生成优化建议', '补充验证方案', '导出给运营复盘'],
  },
  生成优化建议: {
    resultText:
      '已生成一版服务策略优化建议：针对私信挽回、情绪安抚、转人工兜底和促成成交 4 条链路补充了策略节点，建议先在高风险词命中场景灰度 10% 验证一次答复命中率和人工接管率，再逐步放量。',
    resultArtifacts: [
      { id: 'strategy-revamp', type: 'strategy', title: '服务策略优化建议', meta: '策略 · 4 条主链路' },
      { id: 'validation-plan', type: 'document', title: '灰度验证计划', meta: '文档 · 3 项指标' },
    ],
    followUps: ['生成 AB 实验方案', '补充灰度指标', '同步到飞书文档'],
  },
  补充验证方案: {
    resultText:
      '我补充了一版验证方案：建议按照新客转化、老客挽回、风险升级 3 类会话拆分样本，分别观察策略命中率、追问完成率和转人工率，并补一组高情绪用户样本做极端场景回放。',
    resultArtifacts: [
      { id: 'validation-sheet', type: 'table', title: '验证样本拆分矩阵', meta: '表格 · 3 类场景' },
      { id: 'replay-plan', type: 'batch-report', title: '极端场景回放计划', meta: '回放 · 28 条样本' },
    ],
    followUps: ['生成批测任务', '查看高情绪样本', '补充策略兜底'],
  },
};

function nowHHmm() {
  const d = new Date();
  return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
}

function routeReply(text) {
  if (FOLLOW_UP_REPLIES[text]) {
    return { type: 'follow-up-result', ...FOLLOW_UP_REPLIES[text] };
  }
  if (STOP_KEYWORDS.some((keyword) => text.includes(keyword))) {
    return { type: 'short', text: '已停止当前任务，需要时再叫我。' };
  }
  if (TASK_KEYWORDS.some((keyword) => text.includes(keyword))) {
    return { type: 'task' };
  }
  return { type: 'short', text: GENERIC_REPLIES[Math.floor(Math.random() * GENERIC_REPLIES.length)] };
}

function buildThinkingContent(text, context) {
  const artifacts = context.artifacts?.length ? context.artifacts.join('、') : '暂无历史产物';
  return [
    `用户本轮输入：${text}`,
    `系统自动带入当前业务场景：${context.account}`,
    `系统自动带入当前环境：${context.environment}`,
    `系统自动带入样本范围：${context.mock}`,
    `系统自动带入上一轮结论：${context.conclusion || '暂无历史结论'}`,
    `系统自动带入上一轮产物：${artifacts}`,
    '先完成上下文理解与执行口径确认，再进入自动执行流。',
  ].join('\n');
}

function buildClarificationConfirms(context) {
  return DEFAULT_CHAT_FORM_CONFIRM.map((confirm) => ({
    ...confirm,
    id: 'copilot-clarify-confirm',
    title: '人工澄清确认',
    primaryActionLabel: '确认并继续',
    secondaryActionLabel: '',
    formItems: [
      {
        id: 'scene',
        label: '分析目标',
        type: 'select',
        placeholder: '请选择分析目标',
        defaultValue: 'strategy-analysis',
        options: [
          { value: 'strategy-analysis', label: '服务策略分析' },
          { value: 'conversation-review', label: '私信会话复盘' },
          { value: 'ab-plan', label: 'AB 实验方案' },
        ],
        fullWidth: true,
      },
      {
        id: 'channel',
        label: '上下文来源',
        type: 'select',
        placeholder: '请选择上下文来源',
        defaultValue: 'current-context',
        options: [
          {
            value: 'current-context',
            label: `使用当前页面上下文、${context.environment} 与 ${context.mock}`,
          },
          { value: 'refresh-mock', label: '刷新样本后继续分析' },
          { value: 'manual-review', label: '先人工复核关键信息' },
        ],
        fullWidth: true,
      },
      {
        id: 'remark',
        label: '补充说明',
        type: 'input',
        placeholder: '请输入补充说明（可选）',
        fullWidth: true,
      },
    ],
  }));
}

function buildAutoFlowPayload(text, reply, context) {
  if (reply.type === 'follow-up-result') {
    return {
      resultText: `${reply.resultText}\n\n本轮追问已自动继承当前业务场景、页面环境、样本范围和上一轮结论，无需重新补充上下文。`,
      resultArtifacts: reply.resultArtifacts,
      followUps: reply.followUps,
    };
  }

  if (reply.type === 'task') {
    return {
      resultText:
        `${DEFAULT_CHAT_RESULT}\n\n我已结合当前页面的「${context.account}」上下文继续执行，并会优先围绕服务策略、流程节点和批测风险给出建议。`,
      resultArtifacts: DEFAULT_CHAT_RESULT_ARTIFACTS,
      followUps: ['查看风险样本', '生成优化建议', '补充验证方案'],
    };
  }

  return {
    resultText:
      `${reply.text} 已结合当前页面上下文继续处理「${text}」：当前场景为 ${context.account}，环境为 ${context.environment}，样本范围为 ${context.mock}。如果你需要更深入的结论，可以继续选择下方追问。`,
    resultArtifacts: DEFAULT_CHAT_RESULT_ARTIFACTS.slice(0, 2),
    followUps: ['继续细化结论', '补充一轮验证', '生成可交付文档'],
  };
}

function getFlowTotalMs() {
  const totalSteps = DEFAULT_CHAT_TASK_GROUPS.reduce(
    (sum, group) => sum + (group.steps?.length ?? 0),
    0,
  );
  return (totalSteps + 1) * STREAM_INTERVAL;
}

function hasActionablePrimaryButton(label) {
  return typeof label === 'string' && label.trim().length > 0;
}

function confirmsRequireHumanGate(confirms) {
  return Array.isArray(confirms) && confirms.some((confirm) => hasActionablePrimaryButton(confirm?.primaryActionLabel));
}

function messageToChatProps(msg, isLatest, handlers = {}) {
  const {
    onFollowUpSelect,
    onConfirmPrimary,
    onConfirmSecondary,
    onConfirmOptionChange,
    onConfirmFormChange,
    onArtifactSelect,
    selectedArtifactId,
    assistantName,
  } = handlers;
  const aiHeader = buildAiHeader(
    normalizeDisplayName(assistantName, DEFAULT_COPILOT_ASSISTANT_NAME),
  );
  const baseActions = {
    showCopy: true,
    showQuote: true,
    showLike: true,
    showDislike: true,
    historyMode: !isLatest,
  };
  const baseProps = { className: msg.className || '' };

  const wrapFollowUps = (raw) => {
    if (!raw) return null;
    const items = Array.isArray(raw) ? raw : raw.items;
    if (!Array.isArray(items) || items.length === 0) return null;
    return {
      items,
      onSelect: (item) => {
        const label = typeof item === 'string' ? item : item?.label;
        if (label && onFollowUpSelect) onFollowUpSelect(label);
      },
    };
  };

  if (msg.kind === 'user') {
    return {
      ...baseProps,
      role: 'user',
      timestamp: msg.timestamp,
      userContent: msg.userContent,
      actions: baseActions,
    };
  }

  if (msg.kind === 'ai-text') {
    return {
      ...baseProps,
      role: 'ai',
      header: aiHeader,
      title: '',
      steps: null,
      resultText: msg.resultText,
      timestamp: msg.timestamp,
      actions: baseActions,
    };
  }

  if (msg.kind === 'ai-thinking') {
    return {
      ...baseProps,
      role: 'ai',
      header: aiHeader,
      title: '',
      steps: null,
      thinking: msg.thinking,
      resultText: msg.resultText,
      timestamp: msg.timestamp,
      actions: msg.thinking?.state === 'thinking' ? null : baseActions,
    };
  }

  if (msg.kind === 'ai-confirm') {
    return {
      ...baseProps,
      role: 'ai',
      header: aiHeader,
      title: '',
      steps: null,
      leadText: msg.leadText,
      confirms: Array.isArray(msg.confirms)
        ? msg.confirms.map((confirm) => ({
          ...confirm,
          onOptionChange: (value, option) => onConfirmOptionChange && onConfirmOptionChange(
            msg.id,
            confirm.id,
            value,
            option,
          ),
          onFormChange: (formValues, meta) => onConfirmFormChange && onConfirmFormChange(
            msg.id,
            confirm.id,
            formValues,
            meta,
          ),
          onPrimaryAction: (payload) => onConfirmPrimary && onConfirmPrimary(msg.id, confirm.id, {
            ...payload,
            primaryActionLabel: confirm.primaryActionLabel,
          }),
          onSecondaryAction: () => onConfirmSecondary && onConfirmSecondary(msg.id, confirm.id),
        }))
        : msg.confirms,
      timestamp: msg.timestamp,
      actions: baseActions,
    };
  }

  return {
    ...baseProps,
    role: 'ai',
    header: aiHeader,
    title: '',
    steps: null,
    taskGroups: msg.taskGroups,
    resultText: msg.resultText,
    resultArtifacts: msg.resultArtifacts,
    onArtifactSelect,
    selectedArtifactId,
    followUps: wrapFollowUps(msg.followUps),
    taskBadge: msg.taskBadge,
    timestamp: msg.timestamp,
    actions: msg.stream === true ? null : baseActions,
  };
}

function StreamingChatMessage({ taskGroups, ...rest }) {
  const streamed = useStreamingTaskGroups(taskGroups, { intervalMs: STREAM_INTERVAL });
  return <ChatMessage {...rest} taskGroups={streamed} />;
}

export default function CopilotPagePattern({
  platformName = DEFAULT_COPILOT_PLATFORM_NAME,
  assistantName = DEFAULT_COPILOT_ASSISTANT_NAME,
} = {}) {
  const [copilotOpen, setCopilotOpen] = useState(true);
  const [activeTabIndex, setActiveTabIndex] = useState(0);
  const resolvedPlatformName = normalizeDisplayName(platformName, DEFAULT_COPILOT_PLATFORM_NAME);
  const resolvedAssistantName = normalizeDisplayName(assistantName, DEFAULT_COPILOT_ASSISTANT_NAME);

  return (
    <div
      className="tfds-page-copilot-workbench flex h-full min-h-0 min-w-0 w-full flex-col overflow-hidden"
      style={{
        background: 'var(--color-blueGrey-200, #F2F4F7)',
        borderRadius: 'inherit',
        border: '1px solid var(--color-border-default, #E4E7EC)',
        minHeight: '100%',
      }}
    >
      {/* ── 顶导栏 ── */}
      <TopBar
        copilotOpen={copilotOpen}
        onToggleCopilot={() => setCopilotOpen(v => !v)}
        activeTabIndex={activeTabIndex}
        onTabChange={setActiveTabIndex}
        platformName={resolvedPlatformName}
      />

      {/* ── 内容区：左缘与顶栏标题对齐；对话区与右侧详情间距 24px ── */}
      <div
        className="flex flex-1 min-h-0 min-w-0 overflow-hidden pb-4"
        style={{
          paddingLeft: COPILOT_PAGE_GUTTER_X,
          paddingRight: COPILOT_PAGE_GUTTER_X,
        }}
      >
        {copilotOpen ? (
          <ChatArtifactSplitLayout
            className="min-h-0 flex-1"
            columnGap={CHAT_ARTIFACT_SPLIT_COLUMN_GAP}
            conversation={(
              <CopilotPanel
                onClose={() => setCopilotOpen(false)}
                assistantName={resolvedAssistantName}
              />
            )}
            artifactPanel={(
              <ContentCard activeTabIndex={activeTabIndex} />
            )}
          />
        ) : (
          <ContentCard activeTabIndex={activeTabIndex} className="min-h-0 flex-1" />
        )}
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────
   顶导栏
   左：标题 + Copilot 触发按钮
   中：一级页面 Tab（仅 Tabs 左右留白均 < 12px 时换行）
   右：更多 + 次操作 + 主操作
──────────────────────────────────────────── */
function TopBar({ copilotOpen, onToggleCopilot, activeTabIndex, onTabChange, platformName }) {
  const barRef = useRef(null);
  const leadRef = useRef(null);
  const tabsMeasureRef = useRef(null);
  const actionsRef = useRef(null);
  const [tabsWrapped, setTabsWrapped] = useState(false);

  useEffect(() => {
    const bar = barRef.current;
    if (!bar) return undefined;

    const measure = () => {
      const barWidth = bar.getBoundingClientRect().width;
      const leadWidth = leadRef.current?.getBoundingClientRect().width ?? 0;
      const tabsWidth = tabsMeasureRef.current?.getBoundingClientRect().width ?? 0;
      const actionsWidth = actionsRef.current?.getBoundingClientRect().width ?? 0;
      const middleWidth = barWidth - leadWidth - actionsWidth - TOP_BAR_SECTION_GAP * 2;
      const sideSpace = (middleWidth - tabsWidth) / 2;
      const shouldWrap = tabsWidth <= 0
        || middleWidth < tabsWidth
        || sideSpace < TOP_BAR_TABS_SIDE_MIN;
      setTabsWrapped(shouldWrap);
    };

    measure();
    const observer = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(measure) : null;
    observer?.observe(bar);
    if (leadRef.current) observer?.observe(leadRef.current);
    if (tabsMeasureRef.current) observer?.observe(tabsMeasureRef.current);
    if (actionsRef.current) observer?.observe(actionsRef.current);
    window.addEventListener('resize', measure);

    return () => {
      observer?.disconnect();
      window.removeEventListener('resize', measure);
    };
  }, [copilotOpen, platformName]);

  return (
    <div
      className="shrink-0 py-4"
      style={{ paddingLeft: COPILOT_PAGE_GUTTER_X, paddingRight: COPILOT_PAGE_GUTTER_X }}
    >
      <div ref={barRef} className="relative min-h-[36px] min-w-0">
        {tabsWrapped ? (
          <div className="flex min-w-0 flex-col gap-3">
            <div className="flex min-w-0 items-center justify-between gap-4">
              <div ref={leadRef} className="flex min-w-0 items-center gap-3">
                <TopBarLead
                  copilotOpen={copilotOpen}
                  onToggleCopilot={onToggleCopilot}
                  platformName={platformName}
                />
              </div>
              <div ref={actionsRef} className="flex shrink-0 items-center gap-4">
                <TopBarActions />
              </div>
            </div>
            <div className="flex w-full min-w-0 justify-start">
              <div ref={tabsMeasureRef}>
                <TopBarTabs activeIndex={activeTabIndex} onChange={onTabChange} />
              </div>
            </div>
          </div>
        ) : (
          <div className="flex min-h-[36px] min-w-0 items-center gap-4">
            <div ref={leadRef} className="flex min-w-0 shrink-0 items-center gap-3">
              <TopBarLead
                copilotOpen={copilotOpen}
                onToggleCopilot={onToggleCopilot}
                platformName={platformName}
              />
            </div>
            <div className="flex min-w-0 flex-1 justify-center">
              <div ref={tabsMeasureRef} className="shrink-0">
                <TopBarTabs activeIndex={activeTabIndex} onChange={onTabChange} />
              </div>
            </div>
            <div ref={actionsRef} className="flex shrink-0 items-center gap-4">
              <TopBarActions />
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function TopBarLead({ copilotOpen, onToggleCopilot, platformName }) {
  return (
    <>
      <span
        className="min-w-0 truncate font-semibold [font-weight:var(--font-semibold)] text-base leading-[22px] whitespace-nowrap"
        style={{ color: 'var(--foreground, #0F1C35)' }}
      >
        {platformName}
      </span>

      {!copilotOpen && (
        <Button
          variant="outline-black"
          size="md"
          radius="rounded"
          onClick={onToggleCopilot}
          icon={(
            <img
              src={catcatSvg}
              alt=""
              aria-hidden="true"
              style={{ width: '16px', height: '16px', display: 'block' }}
            />
          )}
          className="shrink-0 !border-transparent hover:!border-transparent focus-visible:outline-[var(--color-brand-200)]"
          style={{
            border: '1px solid transparent',
            background: 'var(--gradient-ai-fill-1) padding-box, var(--gradient-ai-fill-2) border-box',
            boxShadow: '0 0 0 1px rgba(255,255,255,0.6) inset',
          }}
        >
          Copilot
        </Button>
      )}
    </>
  );
}

function TopBarTabs({ activeIndex, onChange }) {
  return (
    <Tabs
      variant="pill"
      size="md"
      items={PAGE_TABS}
      activeIndex={activeIndex}
      onChange={onChange}
    />
  );
}

function TopBarActions() {
  return (
    <>
      <div className="flex items-center gap-2">
        <Button variant="ghost-black" iconOnly icon={<Icon name="dots-horizontal-stroked" />} tooltip="更多" aria-label="更多" />
        <Button variant="outline-black">次操作</Button>
        <Button variant="primary" icon={<Icon name="plus-stroked" />}>主操作</Button>
      </div>
    </>
  );
}

/* ────────────────────────────────────────────
   Copilot 侧边栏
   上：标题栏（新会话 + 图标按钮组）
   中：AI 欢迎态（头像 + 标题 + 欢迎语 + 快捷建议 chips）
   下：ChatInput
──────────────────────────────────────────── */
function CopilotArtifactModal({ artifact, onClose }) {
  if (!artifact) return null;

  return (
    <div
      className="fixed inset-0 z-[100] flex items-center justify-center bg-black/40 p-4"
      role="presentation"
      onMouseDown={(event) => {
        if (event.target === event.currentTarget) onClose?.();
      }}
    >
      <Modal
        layout="center"
        size="lg"
        title={artifact.title || '产物详情'}
        subtitle={artifact.meta || null}
        showFooterHint={false}
        draggable={false}
        onClose={onClose}
        bodyClassName="min-h-[min(480px,60vh)]"
      >
        {resolveArtifactDetailDemoContent(artifact)}
      </Modal>
    </div>
  );
}

function CopilotPanel({ onClose, assistantName = DEFAULT_COPILOT_ASSISTANT_NAME }) {
  const [phase, setPhase] = useState('welcome');
  const [messages, setMessages] = useState([]);
  const [inputView, setInputView] = useState('default');
  const [artifactModalArtifact, setArtifactModalArtifact] = useState(null);
  const replyTimerRef = useRef(null);
  const busyTimerRef = useRef(null);
  const flowTimersRef = useRef([]);
  const pendingFlowResumeRef = useRef(null);
  const scrollRef = useRef(null);
  const latestAnchorRef = useRef(null);
  const idSeedRef = useRef(100);
  const conversationContextRef = useRef({ ...DEFAULT_CONVERSATION_CONTEXT });
  const nextId = useCallback((prefix = 'm') => `${prefix}${++idSeedRef.current}`, []);

  const clearFlowTimers = useCallback(() => {
    flowTimersRef.current.forEach((timerId) => clearTimeout(timerId));
    flowTimersRef.current = [];
  }, []);

  const scheduleFlowTimer = useCallback((callback, delay) => {
    const timerId = setTimeout(() => {
      flowTimersRef.current = flowTimersRef.current.filter((id) => id !== timerId);
      callback();
    }, delay);
    flowTimersRef.current.push(timerId);
  }, []);

  const clearPendingFlowResume = useCallback(() => {
    pendingFlowResumeRef.current = null;
  }, []);

  const pauseForHumanGate = useCallback((resume) => {
    pendingFlowResumeRef.current = resume;
  }, []);

  const resumePendingFlow = useCallback(() => {
    const resume = pendingFlowResumeRef.current;
    pendingFlowResumeRef.current = null;
    if (typeof resume === 'function') resume();
  }, []);

  const scrollToLatest = useCallback((behavior = 'smooth') => {
    if (latestAnchorRef.current?.scrollIntoView) {
      latestAnchorRef.current.scrollIntoView({ block: 'end', behavior });
      return;
    }
    const el = scrollRef.current;
    if (el) el.scrollTo({ top: el.scrollHeight, behavior });
  }, []);

  useEffect(() => () => {
    if (replyTimerRef.current) clearTimeout(replyTimerRef.current);
    if (busyTimerRef.current) clearTimeout(busyTimerRef.current);
    clearFlowTimers();
  }, [clearFlowTimers]);

  useEffect(() => {
    if (phase !== 'chat' || messages.length === 0) return undefined;
    const el = scrollRef.current;
    if (!el) return undefined;
    const inner = el.firstElementChild;
    if (!inner) return undefined;
    const ro = new ResizeObserver(() => {
      scrollToLatest();
    });
    ro.observe(inner);
    return () => ro.disconnect();
  }, [phase, messages.length, scrollToLatest]);

  const handleNewSession = useCallback(() => {
    if (replyTimerRef.current) clearTimeout(replyTimerRef.current);
    if (busyTimerRef.current) clearTimeout(busyTimerRef.current);
    clearFlowTimers();
    clearPendingFlowResume();
    conversationContextRef.current = { ...DEFAULT_CONVERSATION_CONTEXT };
    setMessages([]);
    setPhase('welcome');
    setInputView('default');
    setArtifactModalArtifact(null);
  }, [clearFlowTimers, clearPendingFlowResume]);

  const handleArtifactSelect = useCallback((artifact) => {
    if (!artifact?.id) return;
    setArtifactModalArtifact(artifact);
  }, []);

  const handleArtifactModalClose = useCallback(() => {
    setArtifactModalArtifact(null);
  }, []);

  const handleConfirmPrimary = useCallback(
    (messageId, confirmId, payload = {}) => {
      const isActionable = hasActionablePrimaryButton(payload.primaryActionLabel);
      const selectedLabel = payload.option?.label ?? '';
      setMessages((prev) =>
        prev.map((message) =>
          message.id === messageId
            ? {
              ...message,
              confirms: Array.isArray(message.confirms)
                ? message.confirms.map((confirm) => (
                  confirm.id === confirmId
                    ? {
                      ...confirm,
                      defaultConfirmed: true,
                      selectedValue: payload.value ?? confirm.selectedValue,
                      defaultSelectedValue: payload.value ?? confirm.defaultSelectedValue,
                      selectedLabel: selectedLabel || confirm.selectedLabel,
                      formValues: payload.formValues ?? confirm.formValues,
                    }
                    : confirm
                ))
                : message.confirms,
              leadText: isActionable ? '已确认澄清信息，继续执行后续流程。' : message.leadText,
              timestamp: nowHHmm(),
            }
            : message,
        ),
      );
      if (isActionable) resumePendingFlow();
    },
    [resumePendingFlow],
  );

  const handleConfirmOptionChange = useCallback((messageId, confirmId, value, option) => {
    setMessages((prev) =>
      prev.map((message) =>
        message.id === messageId
          ? {
            ...message,
            confirms: Array.isArray(message.confirms)
              ? message.confirms.map((confirm) => (
                confirm.id === confirmId
                  ? {
                    ...confirm,
                    selectedValue: value,
                    defaultSelectedValue: value,
                    selectedLabel: option?.label ?? confirm.selectedLabel,
                  }
                  : confirm
              ))
              : message.confirms,
          }
          : message,
      ),
    );
  }, []);

  const handleConfirmFormChange = useCallback((messageId, confirmId, formValues, meta = {}) => {
    setMessages((prev) =>
      prev.map((message) =>
        message.id === messageId
          ? {
            ...message,
            confirms: Array.isArray(message.confirms)
              ? message.confirms.map((confirm) => (
                confirm.id === confirmId
                  ? {
                    ...confirm,
                    formValues,
                    lastChangedFieldId: meta.fieldId,
                  }
                  : confirm
              ))
              : message.confirms,
          }
          : message,
      ),
    );
  }, []);

  const handleConfirmSecondary = useCallback(
    (messageId, confirmId) => {
      setMessages((prev) =>
        prev.map((message) =>
          message.id === messageId
            ? {
              ...message,
              confirms: Array.isArray(message.confirms)
                ? message.confirms.map((confirm) => (
                  confirm.id === confirmId ? { ...confirm, defaultConfirmed: true } : confirm
                ))
                : message.confirms,
              leadText: '已取消当前确认，流程暂停。',
              timestamp: nowHHmm(),
            }
            : message,
        ),
      );
      clearPendingFlowResume();
      setInputView('default');
    },
    [clearPendingFlowResume],
  );

  const startAutoOrchestratedFlow = useCallback(
    (text, reply, ctx = {}) => {
      const contextSnapshot = { ...conversationContextRef.current };
      const thinkingMsgId = nextId('think');
      const confirmMsgId = nextId('confirm');
      const flowMsgId = nextId('flow');
      const payload = buildAutoFlowPayload(text, reply, contextSnapshot);
      const clarificationConfirms = buildClarificationConfirms(contextSnapshot);

      const finishExecutionFlow = () => {
        setMessages((prev) =>
          prev.map((message) =>
            message.id === flowMsgId
              ? {
                ...message,
                stream: false,
                taskGroups: DEFAULT_CHAT_TASK_GROUPS.map((group) => ({
                  ...group,
                  status: 'completed',
                })),
                resultText: payload.resultText,
                resultArtifacts: payload.resultArtifacts,
                followUps: payload.followUps,
                timestamp: nowHHmm(),
              }
              : message,
          ),
        );
        conversationContextRef.current = {
          ...contextSnapshot,
          conclusion: payload.resultText,
          artifacts: payload.resultArtifacts.map((artifact) => artifact.title),
          lastUserIntent: text,
        };
        setInputView('default');
      };

      const startExecutionFlow = () => {
        setInputView('busy');
        setMessages((prev) => [
          ...prev,
          {
            id: flowMsgId,
            kind: 'ai-flow',
            timestamp: nowHHmm(),
            taskGroups: DEFAULT_CHAT_TASK_GROUPS,
            stream: true,
          },
        ]);
        scheduleFlowTimer(finishExecutionFlow, getFlowTotalMs());
      };

      const continueAfterConfirm = () => {
        setMessages((prev) =>
          prev.map((message) =>
            message.id === confirmMsgId
              ? {
                ...message,
                confirms: Array.isArray(message.confirms)
                  ? message.confirms.map((confirm) => ({
                    ...confirm,
                    defaultConfirmed: true,
                  }))
                  : message.confirms,
                leadText: '已确认澄清信息，开始自动执行。',
                timestamp: nowHHmm(),
              }
              : message,
          ),
        );
        scheduleFlowTimer(startExecutionFlow, 320);
      };

      setMessages((prev) => [
        ...prev,
        {
          id: thinkingMsgId,
          kind: 'ai-thinking',
          timestamp: nowHHmm(),
          thinking: {
            ...DEFAULT_CHAT_THINKING,
            state: 'thinking',
            inProgressLabel: '深度思考中 ...',
            defaultExpanded: false,
          },
        },
      ]);

      scheduleFlowTimer(() => {
        setMessages((prev) =>
          prev.map((message) =>
            message.id === thinkingMsgId
              ? {
                ...message,
                thinking: {
                  ...DEFAULT_CHAT_THINKING,
                  state: 'completed',
                  durationLabel: '深度思考（用时 3.20 秒）',
                  content: buildThinkingContent(text, contextSnapshot),
                  defaultExpanded: false,
                },
                resultText: '已完成上下文理解，接下来需要先确认本轮执行口径。',
                timestamp: nowHHmm(),
              }
              : message,
          ),
        );
      }, AUTO_FLOW_TIMINGS.thinkingDone);

      scheduleFlowTimer(() => {
        setMessages((prev) => [
          ...prev,
          {
            id: confirmMsgId,
            kind: 'ai-confirm',
            timestamp: nowHHmm(),
            leadText: '请确认以下人工澄清信息；确认后我会继续自动执行策略分析和结果整理。',
            confirms: clarificationConfirms,
          },
        ]);

        if (confirmsRequireHumanGate(clarificationConfirms)) {
          pauseForHumanGate(continueAfterConfirm);
          return;
        }

        scheduleFlowTimer(continueAfterConfirm, 320);
      }, AUTO_FLOW_TIMINGS.confirmShow);
    },
    [nextId, pauseForHumanGate, scheduleFlowTimer],
  );

  const handleSend = useCallback(
    (text, ctx = {}) => {
      const trimmed = (text || '').trim();
      if (!trimmed) return;

      if (phase === 'welcome') setPhase('chat');

      const userContent = Array.isArray(ctx.segments) && ctx.segments.length > 0
        ? ctx.segments
        : [{ type: 'text', value: trimmed }];

      setMessages((prev) => [
        ...prev,
        {
          id: nextId('u'),
          kind: 'user',
          timestamp: nowHHmm(),
          userContent,
        },
      ]);
      setInputView('replying');

      const reply = routeReply(trimmed);
      if (replyTimerRef.current) clearTimeout(replyTimerRef.current);
      if (busyTimerRef.current) clearTimeout(busyTimerRef.current);
      clearFlowTimers();
      clearPendingFlowResume();

      if (reply.type === 'short') {
        replyTimerRef.current = setTimeout(() => {
          setMessages((prev) => [
            ...prev,
            {
              id: nextId('a'),
              kind: 'ai-text',
              timestamp: nowHHmm(),
              resultText: reply.text,
            },
          ]);
          setInputView('default');
          scrollToLatest();
        }, 600);
        return;
      }

      startAutoOrchestratedFlow(trimmed, reply, ctx);
      scrollToLatest();
    },
    [phase, nextId, clearFlowTimers, clearPendingFlowResume, scrollToLatest, startAutoOrchestratedFlow],
  );

  const handleFollowUpSend = useCallback(
    (text) => {
      handleSend(text, { source: 'follow-up' });
    },
    [handleSend],
  );

  const handleStop = useCallback(() => {
    if (replyTimerRef.current) {
      clearTimeout(replyTimerRef.current);
      replyTimerRef.current = null;
    }
    if (busyTimerRef.current) {
      clearTimeout(busyTimerRef.current);
      busyTimerRef.current = null;
    }
    clearFlowTimers();
    clearPendingFlowResume();
    setInputView('default');
    setMessages((prev) => [
      ...prev,
      {
        id: nextId('a'),
        kind: 'ai-text',
        timestamp: nowHHmm(),
        resultText: '已停止当前任务，需要时再叫我。',
      },
    ]);
  }, [nextId, clearFlowTimers, clearPendingFlowResume]);

  const lastIdx = messages.length - 1;

  return (
    <div className="flex h-full min-h-0 min-w-0 w-full flex-col overflow-hidden">
      <CopilotArtifactModal
        artifact={artifactModalArtifact}
        onClose={handleArtifactModalClose}
      />

      {/* 标题栏 */}
      <div className="flex items-center shrink-0" style={{ height: '48px', paddingRight: '4px' }}>
        <div className="flex items-center flex-1 min-w-0 gap-1" />
        <div className="flex items-center gap-0.5 shrink-0">
          <Button variant="ghost-black" iconOnly icon={<Icon name="message-plus-square-stroked" />} tooltip="新建会话" aria-label="新建会话" onClick={handleNewSession} />
          <Button variant="ghost-black" iconOnly icon={<Icon name="clock-stroked" />} tooltip="历史记录" aria-label="历史记录" />
          <Button variant="ghost-black" iconOnly icon={<Icon name="layout-left-stroked" />} tooltip="收起面板" aria-label="收起面板" onClick={onClose} />
        </div>
      </div>

      {phase === 'welcome' ? (
        <CopilotWelcomePhase
          assistantName={assistantName}
          onSend={handleSend}
          inputView={inputView}
          onStop={handleStop}
        />
      ) : (
        <CopilotChatPhase
          scrollRef={scrollRef}
          latestAnchorRef={latestAnchorRef}
          messages={messages}
          lastIdx={lastIdx}
          inputView={inputView}
          onSend={handleSend}
          onStop={handleStop}
          handlers={{
            assistantName,
            onFollowUpSelect: handleFollowUpSend,
            onConfirmPrimary: handleConfirmPrimary,
            onConfirmSecondary: handleConfirmSecondary,
            onConfirmOptionChange: handleConfirmOptionChange,
            onConfirmFormChange: handleConfirmFormChange,
            onArtifactSelect: handleArtifactSelect,
            selectedArtifactId: artifactModalArtifact?.id ?? null,
          }}
        />
      )}
    </div>
  );
}

function CopilotWelcomePhase({ assistantName = DEFAULT_COPILOT_ASSISTANT_NAME, onSend, onStop, inputView }) {
  return (
    <div className="flex min-h-0 flex-1 flex-col">
      <div className="flex flex-1 min-h-0 flex-col items-center justify-center gap-6 overflow-y-auto">
        <div className="flex flex-col items-center gap-3">
          <div style={{ position: 'relative', width: '66px', height: '66px', flexShrink: 0 }}>
            <div
              style={{
                position: 'absolute',
                inset: '0',
                borderRadius: '50%',
                padding: '0.5px',
                background: 'linear-gradient(135deg, rgba(63,226,213,0.6) 0%, rgba(64,147,224,0.6) 35%, rgba(122,97,250,0.6) 65%, rgba(214,130,235,0.6) 100%)',
              }}
            >
              <div
                style={{
                  width: '100%',
                  height: '100%',
                  borderRadius: '50%',
                  background: [
                    'linear-gradient(42deg, #FFF 11.61%, rgba(255,255,255,0.00) 37.84%)',
                    'linear-gradient(74deg, rgba(63,226,213,0.15) 12.18%, rgba(64,147,224,0.15) 39.9%, rgba(122,97,250,0.15) 63.86%, rgba(214,130,235,0.15) 86.38%)',
                    '#FFF',
                  ].join(', '),
                  boxShadow: '0px 8px 15px rgba(180,218,244,0.50)',
                }}
              />
            </div>
            <img
              src={catcatSvg}
              alt=""
              aria-hidden="true"
              style={{
                position: 'absolute',
                width: '32px',
                height: '32px',
                top: '50%',
                left: '50%',
                transform: 'translate(-50%, -50%)',
                zIndex: 1,
              }}
            />
          </div>
          <span
            className="whitespace-nowrap [font-weight:var(--font-semibold)]"
            style={{ fontSize: '18px', lineHeight: '24px', letterSpacing: '-0.03em', color: 'var(--foreground, #0F1C35)' }}
          >
            {assistantName}
          </span>
        </div>

        <p
          className="m-0 text-center text-sm leading-5"
          style={{ color: 'var(--foreground-muted, rgba(15,28,53,0.6))', width: '100%' }}
        >
          您好，我可以帮您分析会话、制定策略并输出可交付结论。
        </p>

        <div className="flex w-full flex-col gap-2">
          {COPILOT_SUGGESTIONS.map((text) => (
            <button
              key={text}
              type="button"
              className="flex w-full cursor-pointer items-center justify-between border-0 text-left"
              style={{
                padding: '10px 12px',
                borderRadius: '8px',
                background: 'rgba(255,255,255,0.6)',
                boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.9)',
                fontSize: '12px',
                lineHeight: '16px',
                color: 'var(--foreground, #0F1C35)',
                fontFamily: 'inherit',
                transition: 'background var(--motion-ui-fast)',
              }}
              onMouseEnter={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.85)'; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.6)'; }}
              onClick={() => onSend(text, { source: 'suggestion' })}
            >
              <span>{text}</span>
              <Icon name="arrow-narrow-right-stroked" size={12} />
            </button>
          ))}
        </div>
      </div>

      <div className={COPILOT_CHAT_INPUT_FOOTER}>
        <ChatInput
          variant={inputView}
          autoReplyOnSend={false}
          placeholder="需要我为你做什么"
          onSend={onSend}
          onStop={onStop}
        />
      </div>
    </div>
  );
}

function CopilotChatPhase({
  scrollRef,
  latestAnchorRef,
  messages,
  lastIdx,
  handlers,
  onSend,
  onStop,
  inputView,
}) {
  const [atTop, setAtTop] = useState(true);

  useEffect(() => {
    const el = scrollRef.current;
    if (!el) return undefined;
    const update = () => setAtTop(el.scrollTop <= 4);
    update();
    el.addEventListener('scroll', update, { passive: true });
    return () => el.removeEventListener('scroll', update);
  }, [scrollRef, messages.length]);

  const FADE_MASK = atTop
    ? 'linear-gradient(to bottom, #000 0, #000 calc(100% - 32px), transparent 100%)'
    : 'linear-gradient(to bottom, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%)';

  return (
    <div className="flex min-h-0 w-full min-w-0 flex-1 flex-col">
      <div
        ref={scrollRef}
        className="relative z-0 w-full min-h-0 flex-1 overflow-x-hidden overflow-y-auto"
        style={{
          padding: '8px 0',
          maskImage: FADE_MASK,
          WebkitMaskImage: FADE_MASK,
        }}
      >
        <div className="mx-auto flex w-full flex-col gap-2" style={{ maxWidth: '100%', padding: '0 0 72px' }}>
          {messages.map((message, idx) => {
            const isLatest = idx === lastIdx;
            const props = messageToChatProps(message, isLatest, handlers);
            if (message.kind === 'ai-flow' && message.stream === true) {
              return <StreamingChatMessage key={message.id} {...props} taskGroups={message.taskGroups} />;
            }
            return <ChatMessage key={message.id} {...props} />;
          })}
          <div ref={latestAnchorRef} aria-hidden="true" style={{ height: '1px' }} />
        </div>
      </div>

      <div className={COPILOT_CHAT_INPUT_FOOTER}>
        <ChatInput
          variant={inputView}
          autoReplyOnSend={false}
          placeholder="继续追问，或输入分析/生成/整理"
          onSend={onSend}
          onStop={onStop}
        />
      </div>
    </div>
  );
}

function ContentCard({ activeTabIndex = 0, className = '' }) {
  const activePanel = PAGE_TAB_PANELS[activeTabIndex] || PAGE_TAB_PANELS[0];
  const { label, iconName, headerActionLabel, Panel } = activePanel;

  return (
    <CopilotArtifactDetailPanel
      className={['h-full min-h-0 min-w-0', className].filter(Boolean).join(' ')}
      headerTitle={label}
      headerIconName={iconName}
      headerActionLabel={headerActionLabel}
      bodySlotPadding={false}
    >
      <Panel embedded shellless initialLoading={false} />
    </CopilotArtifactDetailPanel>
  );
}
