<script setup lang="ts">
import type { WorkflowStreamEvent } from '#/api/ai-platform/ai-platform';

import { computed, onUnmounted, ref, watch } from 'vue';

import { CheckCircle2, Clock, Loader2, Play, X, XCircle } from '@vben/icons';
import { $t } from '@vben/locales';

import {
  ElButton,
  ElCollapse,
  ElCollapseItem,
  ElForm,
  ElFormItem,
  ElInput,
  ElMessage,
  ElScrollbar,
  ElTag,
} from 'element-plus';

import { runWorkflowStreamApi } from '#/api/ai-platform/ai-platform';

const props = defineProps<{
  nodes: any[];
  workflowId: string;
}>();

const emit = defineEmits([
  'close',
  'run-start',
  'run-complete',
  'clear-status',
  'node-start',
  'node-complete',
  'node-message',
  'waiting-for-input',
  'loop-iteration',
]);

const running = ref(false);
const result = ref<any>(null);
const inputs = ref<Record<string, any>>({});
const runId = ref<string>('');
let cancelStream: (() => void) | null = null;

// 实时节点状态追踪
interface NodeExecutionState {
  node_id: string;
  node_type: string;
  node_label: string;
  status: 'failed' | 'pending' | 'running' | 'success';
  start_time?: number;
  elapsed_time?: number;
  tokens_used?: number;
  error_message?: string;
  inputs?: {
    previous_output?: any;
    variables?: Record<string, any>;
  };
  outputs?: {
    output?: any;
    output_variables?: Record<string, any>;
  };
  // LLM 流式输出
  streaming_content?: string;
  // 并行执行
  parallel_branches?: string[];
  parallel_results?: Record<string, any>;
}
const nodeStates = ref<Map<string, NodeExecutionState>>(new Map());
const currentNodeId = ref<string>('');
let timerInterval: null | ReturnType<typeof setInterval> = null;

// 查找 Start 节点并提取变量
const startNode = computed(() => props.nodes.find((n) => n.type === 'start'));
const variables = computed(() => startNode.value?.data?.variables || []);

// 获取节点状态列表（按执行顺序）
const nodeStateList = computed(() => {
  return [...nodeStates.value.values()];
});

// 计算总体统计
const totalStats = computed(() => {
  const states = nodeStateList.value;
  const completed = states.filter(
    (s) => s.status === 'success' || s.status === 'failed',
  );
  const totalTime = completed.reduce(
    (sum, s) => sum + (s.elapsed_time || 0),
    0,
  );
  const totalTokens = completed.reduce(
    (sum, s) => sum + (s.tokens_used || 0),
    0,
  );
  return {
    total: states.length,
    completed: completed.length,
    success: states.filter((s) => s.status === 'success').length,
    failed: states.filter((s) => s.status === 'failed').length,
    running: states.filter((s) => s.status === 'running').length,
    totalTime,
    totalTokens,
  };
});

// 启动计时器更新当前运行节点的耗时
const startTimer = () => {
  stopTimer();
  timerInterval = setInterval(() => {
    if (currentNodeId.value) {
      const state = nodeStates.value.get(currentNodeId.value);
      if (state && state.status === 'running' && state.start_time) {
        state.elapsed_time = Date.now() - state.start_time;
      }
    }
  }, 100);
};

const stopTimer = () => {
  if (timerInterval) {
    clearInterval(timerInterval);
    timerInterval = null;
  }
};

// 初始化输入（使用默认值）
watch(
  variables,
  (vars) => {
    const newInputs: Record<string, any> = {};
    vars.forEach((v: any) => {
      // 保留已有值，否则使用默认值
      newInputs[v.variable] = inputs.value[v.variable] || v.default_value || '';
    });
    inputs.value = newInputs;
  },
  { immediate: true },
);

// 组件卸载时取消流和计时器
onUnmounted(() => {
  cancelStream?.();
  stopTimer();
});

// 格式化耗时显示
const formatTime = (ms: number | undefined) => {
  if (ms === undefined) return '-';
  if (ms < 1000) return `${ms}ms`;
  return `${(ms / 1000).toFixed(1)}s`;
};

const handleRun = () => {
  if (!props.workflowId) return;
  running.value = true;
  result.value = null;
  nodeStates.value.clear();
  currentNodeId.value = '';
  emit('run-start');
  startTimer();

  // 编辑器调试模式，使用草稿版本
  // 系统变量（application_id 等）由 API 层自动注入
  cancelStream = runWorkflowStreamApi(
    props.workflowId,
    inputs.value,
    (event: WorkflowStreamEvent) => {
      // 处理不同类型的事件
      switch (event.type) {
        case 'complete': {
          stopTimer();
          result.value = {
            status: 'completed',
            outputs: event.outputs,
            elapsed_time: event.elapsed_time,
            total_tokens: event.total_tokens,
            execution_log: nodeStateList.value,
          };
          running.value = false;
          emit('run-complete', result.value);
          break;
        }

        case 'error': {
          stopTimer();
          // 将当前运行中的节点标记为失败（优先使用事件中的 node_id）
          const failedNodeId = event.node_id || currentNodeId.value;
          if (failedNodeId) {
            const state = nodeStates.value.get(failedNodeId);
            if (state && state.status === 'running') {
              state.status = 'failed';
              state.error_message =
                event.message ||
                $t('ai-platform.workflow.editor.runPanel.execFailed');
              state.elapsed_time = state.start_time
                ? Date.now() - state.start_time
                : 0;
              emit('node-complete', {
                node_id: failedNodeId,
                node_type: state.node_type,
                status: 'failed',
                error_message:
                  event.message ||
                  $t('ai-platform.workflow.editor.runPanel.execFailed'),
              });
            }
            currentNodeId.value = '';
          }
          result.value = {
            status: 'failed',
            error_message: event.message,
            execution_log: nodeStateList.value,
          };
          running.value = false;
          emit('run-complete', result.value);
          break;
        }

        case 'llm_chunk': {
          // LLM 流式输出
          const state = nodeStates.value.get(event.node_id || '');
          if (state) {
            state.streaming_content = event.accumulated_content || '';
          }
          break;
        }

        case 'loop_complete': {
          // 循环执行完成
          const loopEvent = event as any;
          const outputVar = loopEvent.output_variable || 'loop_results';
          const outputs: Record<string, any> = {
            total_iterations: loopEvent.total_iterations,
            results_count: loopEvent.results_count,
          };
          // 将 loop_results 添加到输出中
          if (loopEvent.loop_results) {
            outputs[outputVar] = loopEvent.loop_results;
          }

          emit('node-complete', {
            node_id: loopEvent.node_id,
            node_type: 'loop',
            status: 'success',
            elapsed_time: 0,
            tokens_used: 0,
            outputs,
          });
          break;
        }

        case 'loop_iteration_complete': {
          // 循环迭代完成
          emit('loop-iteration', {
            type: 'complete',
            node_id: event.node_id,
            iteration: event.iteration,
            total: event.total,
            output: event.output,
          });
          break;
        }

        case 'loop_iteration_error': {
          // 循环迭代错误
          emit('loop-iteration', {
            type: 'error',
            node_id: event.node_id,
            iteration: event.iteration,
            error: event.error,
          });
          break;
        }

        case 'loop_iteration_start': {
          // 循环迭代开始
          emit('loop-iteration', {
            type: 'start',
            node_id: event.node_id,
            iteration: event.iteration,
            total: event.total,
            item: event.item,
          });
          break;
        }

        case 'node_complete': {
          // 更新节点完成状态（包含输出数据）
          const state = nodeStates.value.get(event.node_id || '');
          if (state) {
            state.status = event.status === 'success' ? 'success' : 'failed';
            state.elapsed_time = event.elapsed_time;
            state.tokens_used = event.tokens_used;
            state.error_message = event.error_message;
            state.outputs = event.outputs;
          }
          currentNodeId.value = '';
          emit('node-complete', {
            node_id: event.node_id,
            node_type: event.node_type,
            status: event.status,
            elapsed_time: event.elapsed_time,
            tokens_used: event.tokens_used,
            error_message: event.error_message,
            warnings: event.warnings,
          });
          break;
        }

        case 'node_event': {
          // 节点事件（如消息节点发送消息）
          const nodeEvent = event.event;
          if (nodeEvent?.type === 'message') {
            // 显示消息
            emit('node-message', {
              node_id: event.node_id,
              content: nodeEvent.content,
              message_type: nodeEvent.message_type,
            });
          }
          break;
        }

        case 'node_start': {
          // 记录节点开始状态（包含输入数据）
          currentNodeId.value = event.node_id || '';
          nodeStates.value.set(event.node_id || '', {
            node_id: event.node_id || '',
            node_type: event.node_type || '',
            node_label: event.node_label || event.node_id || '',
            status: 'running',
            start_time: Date.now(),
            elapsed_time: 0,
            inputs: event.inputs,
          });
          emit('node-start', {
            node_id: event.node_id,
            node_type: event.node_type,
          });
          break;
        }

        case 'parallel_complete': {
          // 并行执行完成
          const state = nodeStates.value.get(event.node_id || '');
          if (state) {
            state.status = 'success';
            state.elapsed_time = Date.now() - (state.start_time || Date.now());
            state.parallel_results = event.branch_results;
          }
          break;
        }

        case 'parallel_start': {
          // 并行执行开始
          const branches = event.branches || [];
          nodeStates.value.set(event.node_id || '', {
            node_id: event.node_id || '',
            node_type: 'parallel',
            node_label: $t('ai-platform.workflow.editor.runPanel.parallelExec'),
            status: 'running',
            start_time: Date.now(),
            elapsed_time: 0,
            parallel_branches: branches,
          });
          break;
        }

        case 'start': {
          // 工作流开始执行
          runId.value = event.run_id || '';
          break;
        }

        case 'waiting_input': {
          // 等待用户输入（对话流节点）
          stopTimer();
          const state = nodeStates.value.get(event.node_id || '');
          if (state) {
            state.status = 'waiting' as any;
            state.elapsed_time = state.start_time
              ? Date.now() - state.start_time
              : 0;
          }
          // 发送等待事件给父组件处理
          emit('waiting-for-input', {
            node_id: event.node_id,
            node_type: event.node_type,
            run_id: runId.value,
            waiting_config: event.waiting_config,
            loop_iteration: event.loop_iteration,
          });
          running.value = false;
          break;
        }
      }
    },
    (error) => {
      console.error('Stream error:', error);
      stopTimer();
      // 将当前运行中的节点标记为失败
      if (currentNodeId.value) {
        const state = nodeStates.value.get(currentNodeId.value);
        if (state && state.status === 'running') {
          state.status = 'failed';
          state.error_message =
            error.message ||
            $t('ai-platform.workflow.editor.runPanel.execFailed');
          emit('node-complete', {
            node_id: currentNodeId.value,
            node_type: state.node_type,
            status: 'failed',
            error_message:
              error.message ||
              $t('ai-platform.workflow.editor.runPanel.execFailed'),
          });
        }
        currentNodeId.value = '';
      }
      ElMessage.error(
        error.message ||
          $t('ai-platform.workflow.editor.runPanel.workflowExecFailed'),
      );
      result.value = {
        status: 'failed',
        error_message: error.message,
        execution_log: nodeStateList.value,
      };
      running.value = false;
    },
    () => {
      // Stream completed
      cancelStream = null;
    },
    true, // useDraft: 编辑器调试使用草稿版本
  );
};

const handleStop = () => {
  cancelStream?.();
  cancelStream = null;
  stopTimer();
  running.value = false;
  // 将当前运行中的节点标记为已停止
  if (currentNodeId.value) {
    const state = nodeStates.value.get(currentNodeId.value);
    if (state && state.status === 'running') {
      state.status = 'failed';
      state.error_message = $t(
        'ai-platform.workflow.editor.runPanel.userStopped',
      );
    }
  }
};
</script>

<template>
  <div
    class="border-border bg-card z-30 flex h-full w-96 flex-col border-l shadow-xl"
  >
    <div
      class="border-border bg-muted/50 flex items-center justify-between border-b px-4 py-3"
    >
      <div class="text-foreground flex items-center gap-2 font-medium">
        <Play class="text-primary size-4" />
        {{ $t('ai-platform.workflow.editor.runPanel.runPreview') }}
      </div>
      <ElButton link :icon="X" @click="$emit('close')" />
    </div>

    <ElScrollbar class="flex-1">
      <div class="space-y-6 p-4">
        <!-- 输入区域 -->
        <div>
          <div
            class="text-muted-foreground mb-3 text-xs font-semibold uppercase tracking-wider"
          >
            {{ $t('ai-platform.workflow.editor.runPanel.inputVariables') }}
          </div>

          <div
            v-if="variables.length === 0"
            class="border-border bg-muted text-muted-foreground rounded border border-dashed p-3 text-center text-sm"
          >
            {{ $t('ai-platform.workflow.editor.runPanel.noVariablesHint') }}
          </div>

          <ElForm v-else label-position="top" size="default">
            <ElFormItem
              v-for="v in variables"
              :key="v.variable"
              :label="v.label || v.variable"
              :required="v.required"
            >
              <ElInput
                v-model="inputs[v.variable]"
                :placeholder="
                  $t('ai-platform.workflow.editor.runPanel.inputPlaceholder', {
                    type: v.type,
                  })
                "
                :type="v.type === 'number' ? 'number' : 'text'"
              />
            </ElFormItem>
          </ElForm>

          <div class="mt-2 flex gap-2">
            <ElButton
              v-if="!running"
              type="primary"
              class="flex-1"
              @click="handleRun"
            >
              {{ $t('ai-platform.workflow.editor.runPanel.startRun') }}
            </ElButton>
            <ElButton v-else type="danger" class="flex-1" @click="handleStop">
              {{ $t('ai-platform.workflow.editor.runPanel.stopRun') }}
            </ElButton>
            <ElButton v-if="result && !running" @click="emit('clear-status')">
              {{ $t('ai-platform.workflow.editor.runPanel.clearStatus') }}
            </ElButton>
          </div>
        </div>

        <!-- 实时执行状态 -->
        <div v-if="running || nodeStateList.length > 0" class="mt-4">
          <div class="mb-2 flex items-center justify-between">
            <div
              class="text-muted-foreground text-xs font-semibold uppercase tracking-wider"
            >
              {{ $t('ai-platform.workflow.editor.runPanel.execStatus') }}
            </div>
            <div
              v-if="running"
              class="flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400"
            >
              <Loader2 class="size-3 animate-spin" />
              {{ $t('ai-platform.workflow.editor.runPanel.running') }}
            </div>
          </div>

          <!-- 统计信息 -->
          <div class="mb-3 flex gap-2 text-xs">
            <ElTag size="small" type="info">
              {{ totalStats.completed }}/{{ totalStats.total }}
              {{ $t('ai-platform.workflow.editor.runPanel.nodes') }}
            </ElTag>
            <ElTag v-if="totalStats.totalTokens > 0" size="small">
              {{ totalStats.totalTokens }} tokens
            </ElTag>
            <ElTag v-if="totalStats.totalTime > 0" size="small">
              {{ formatTime(totalStats.totalTime) }}
            </ElTag>
          </div>

          <!-- 节点列表 -->
          <div class="space-y-2">
            <div
              v-for="state in nodeStateList"
              :key="state.node_id"
              class="rounded-lg border p-2 text-xs transition-all"
              :class="[
                state.status === 'running'
                  ? 'border-blue-300 bg-blue-50 dark:border-blue-700 dark:bg-blue-950'
                  : '',
                state.status === 'success'
                  ? 'border-green-200 bg-green-50 dark:border-green-700 dark:bg-green-950'
                  : '',
                state.status === 'failed'
                  ? 'border-red-200 bg-red-50 dark:border-red-700 dark:bg-red-950'
                  : '',
                state.status === 'pending' ? 'border-border bg-muted' : '',
              ]"
            >
              <div class="flex items-center justify-between">
                <div class="flex items-center gap-2">
                  <!-- 状态图标 -->
                  <Loader2
                    v-if="state.status === 'running'"
                    class="size-3.5 animate-spin text-blue-600 dark:text-blue-400"
                  />
                  <CheckCircle2
                    v-else-if="state.status === 'success'"
                    class="size-3.5 text-green-600 dark:text-green-400"
                  />
                  <XCircle
                    v-else-if="state.status === 'failed'"
                    class="size-3.5 text-red-600 dark:text-red-400"
                  />
                  <Clock v-else class="text-muted-foreground size-3.5" />

                  <!-- 节点名称 -->
                  <span
                    class="font-medium"
                    :class="[
                      state.status === 'running'
                        ? 'text-blue-700 dark:text-blue-300'
                        : '',
                      state.status === 'success'
                        ? 'text-green-700 dark:text-green-300'
                        : '',
                      state.status === 'failed'
                        ? 'text-red-700 dark:text-red-300'
                        : '',
                      state.status === 'pending' ? 'text-muted-foreground' : '',
                    ]"
                  >
                    {{ state.node_label }}
                  </span>
                  <span class="text-muted-foreground">({{ state.node_type }})</span>
                </div>

                <!-- 耗时 -->
                <span
                  class="font-mono"
                  :class="[
                    state.status === 'running'
                      ? 'text-blue-600 dark:text-blue-400'
                      : 'text-muted-foreground',
                  ]"
                >
                  {{ formatTime(state.elapsed_time) }}
                </span>
              </div>

              <!-- Token 和错误信息 -->
              <div
                v-if="state.tokens_used || state.error_message"
                class="mt-1 pl-5"
              >
                <span v-if="state.tokens_used" class="text-muted-foreground">
                  {{ state.tokens_used }} tokens
                </span>
                <span
                  v-if="state.error_message"
                  class="text-red-500 dark:text-red-400"
                >
                  {{ state.error_message }}
                </span>
              </div>

              <!-- LLM 流式输出内容 -->
              <div
                v-if="state.node_type === 'llm' && state.streaming_content"
                class="mt-2 rounded border border-blue-200 bg-blue-50/50 p-2 dark:border-blue-700 dark:bg-blue-900/50"
              >
                <div
                  class="mb-1 flex items-center gap-1 text-[10px] font-medium text-blue-600 dark:text-blue-400"
                >
                  <Loader2
                    v-if="state.status === 'running'"
                    class="size-3 animate-spin"
                  />
                  <span>{{
                    $t('ai-platform.workflow.editor.runPanel.llmOutput')
                  }}</span>
                </div>
                <div
                  class="text-foreground max-h-40 overflow-auto whitespace-pre-wrap break-all font-mono text-xs"
                >
                  {{ state.streaming_content }}
                  <span
                    v-if="state.status === 'running'"
                    class="ml-0.5 inline-block h-3 w-1 animate-pulse bg-blue-500 dark:bg-blue-400"
                  ></span>
                </div>
              </div>

              <!-- 并行执行状态 -->
              <div
                v-if="state.node_type === 'parallel'"
                class="mt-2 rounded border border-purple-200 bg-purple-50/50 p-2 dark:border-purple-700 dark:bg-purple-900/50"
              >
                <div
                  class="mb-1 flex items-center gap-1 text-[10px] font-medium text-purple-600 dark:text-purple-400"
                >
                  <Loader2
                    v-if="state.status === 'running'"
                    class="size-3 animate-spin"
                  />
                  <span>{{
                    $t(
                      'ai-platform.workflow.editor.runPanel.parallelBranches',
                      { count: state.parallel_branches?.length || 0 },
                    )
                  }}</span>
                </div>
                <div
                  v-if="state.parallel_branches"
                  class="mt-1 flex flex-wrap gap-1"
                >
                  <span
                    v-for="branch in state.parallel_branches"
                    :key="branch"
                    class="rounded bg-purple-100 px-1.5 py-0.5 text-[10px] text-purple-700 dark:bg-purple-800 dark:text-purple-300"
                  >
                    {{ branch }}
                  </span>
                </div>
                <div v-if="state.parallel_results" class="mt-2">
                  <div class="text-muted-foreground mb-1 text-[10px]">
                    {{
                      $t('ai-platform.workflow.editor.runPanel.branchResults')
                    }}
                  </div>
                  <pre
                    class="text-muted-foreground bg-card border-border max-h-32 overflow-auto whitespace-pre-wrap break-all rounded border p-2 font-mono text-[10px]"
                    >{{ JSON.stringify(state.parallel_results, null, 2) }}</pre>
                </div>
              </div>

              <!-- 输入输出详情（可折叠） -->
              <ElCollapse v-if="state.inputs || state.outputs" class="mt-2">
                <ElCollapseItem
                  v-if="state.inputs"
                  :title="$t('ai-platform.workflow.editor.runPanel.input')"
                  name="inputs"
                >
                  <pre
                    class="text-muted-foreground bg-muted max-h-32 overflow-auto whitespace-pre-wrap break-all rounded p-2 font-mono text-[10px]"
                    >{{ JSON.stringify(state.inputs, null, 2) }}</pre>
                </ElCollapseItem>
                <ElCollapseItem
                  v-if="state.outputs"
                  :title="$t('ai-platform.workflow.editor.runPanel.output')"
                  name="outputs"
                >
                  <pre
                    class="text-muted-foreground bg-muted max-h-32 overflow-auto whitespace-pre-wrap break-all rounded p-2 font-mono text-[10px]"
                    >{{ JSON.stringify(state.outputs, null, 2) }}</pre>
                </ElCollapseItem>
              </ElCollapse>
            </div>
          </div>
        </div>

        <!-- 结果区域 -->
        <div
          v-if="result"
          class="animate-in fade-in slide-in-from-bottom-4 mt-4 duration-300"
        >
          <div
            class="text-muted-foreground mb-2 text-xs font-semibold uppercase tracking-wider"
          >
            {{ $t('ai-platform.workflow.editor.runPanel.runResult') }}
          </div>

          <div class="border-border bg-muted overflow-hidden rounded-lg border">
            <div
              class="border-border bg-muted/50 text-muted-foreground flex justify-between border-b px-3 py-2 text-xs"
            >
              <span
                :class="
                  result.status === 'completed'
                    ? 'text-green-600 dark:text-green-400'
                    : 'text-red-600 dark:text-red-400'
                "
              >
                {{
                  result.status === 'completed'
                    ? $t('ai-platform.workflow.editor.runPanel.success')
                    : $t('ai-platform.workflow.editor.runPanel.failed')
                }}
              </span>
              <span v-if="result.elapsed_time">{{ result.elapsed_time }}ms</span>
            </div>
            <div v-if="result.outputs" class="p-3">
              <pre
                class="text-foreground max-h-64 overflow-auto whitespace-pre-wrap break-all font-mono text-xs"
                >{{ JSON.stringify(result.outputs, null, 2) }}</pre
              >
            </div>
            <div
              v-if="result.error_message"
              class="p-3 text-xs text-red-500 dark:text-red-400"
            >
              {{ result.error_message }}
            </div>
          </div>
        </div>
      </div>
    </ElScrollbar>
  </div>
</template>
