<script lang="ts">
// 迭代结果类型
</script>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';

import {
  CheckCircle2,
  ChevronDown,
  ChevronUp,
  Clock,
  Loader2,
  Maximize,
  XCircle,
  Zap,
} from '@vben/icons';
import { $t } from '@vben/locales';

import { ZqDialog } from '#/components/zq-dialog';

export interface IterationResult {
  iteration?: number;
  status: 'failed' | 'success';
  elapsed_time?: number;
  tokens_used?: number;
  error_message?: string;
  output?: any;
  inputs?: any;
}

export interface NodeExecutionResult {
  status: 'failed' | 'pending' | 'running' | 'success';
  streaming_content?: string;
  output?: any;
  elapsed_time?: number;
  tokens_used?: number;
  error_message?: string;
  inputs?: {
    previous_output?: any;
    variables?: Record<string, any>;
  };
  loop_iteration?: number;
  iterations?: IterationResult[];
}

const props = defineProps<{
  nodeType?: string;
  result: NodeExecutionResult;
}>();

defineOptions({ inheritAttrs: false });

const expanded = ref(false);
const detailVisible = ref(false);

const hasIterations = computed(
  () => props.result.iterations && props.result.iterations.length > 0,
);
const selectedIteration = ref(0);

watch(
  () => props.result.iterations?.length,
  (newLen) => {
    if (newLen && newLen > 0) {
      selectedIteration.value = newLen - 1;
    }
  },
);

const displayResult = computed(() => {
  if (hasIterations.value && props.result.iterations) {
    const iter = props.result.iterations[selectedIteration.value];
    if (iter) {
      return {
        status: iter.status,
        output: iter.output,
        elapsed_time: iter.elapsed_time,
        tokens_used: iter.tokens_used,
        error_message: iter.error_message,
        inputs: iter.inputs,
        streaming_content: undefined,
      };
    }
  }
  return props.result;
});

const formattedOutput = computed(() => {
  if (displayResult.value.output === undefined || displayResult.value.output === null) {
    return '{}';
  }
  if (typeof displayResult.value.output === 'string') {
    return displayResult.value.output;
  }
  return JSON.stringify(displayResult.value.output, null, 2);
});

const outputPreview = computed(() => {
  const output = formattedOutput.value;
  if (!output) return $t('ai-platform.workflow.editor.nodeResultCard.noOutput');
  if (output.length <= 100) return output;
  return `${output.slice(0, 100)}...`;
});

const hasDetails = computed(() => {
  return formattedOutput.value.length > 100 || !!displayResult.value.inputs;
});

const canOpenDetail = computed(() => {
  return (
    (displayResult.value.status === 'success' ||
      displayResult.value.status === 'failed') &&
    (displayResult.value.output !== undefined ||
      !!displayResult.value.inputs ||
      !!displayResult.value.error_message)
  );
});

const statusConfig = computed(() => {
  const status = displayResult.value.status;
  switch (status) {
    case 'failed': {
      return {
        icon: XCircle,
        text: $t('ai-platform.workflow.editor.nodeResultCard.failed'),
        bgClass: 'bg-red-50 dark:bg-red-950',
        borderClass: 'border-red-300 dark:border-red-700',
        textClass: 'text-red-600 dark:text-red-400',
        iconClass: 'text-red-500 dark:text-red-400',
      };
    }
    case 'pending': {
      return {
        icon: Clock,
        text: $t('ai-platform.workflow.editor.nodeResultCard.pending'),
        bgClass: 'bg-muted',
        borderClass: 'border-border',
        textClass: 'text-muted-foreground',
        iconClass: 'text-muted-foreground',
      };
    }
    case 'running': {
      return {
        icon: Loader2,
        text: $t('ai-platform.workflow.editor.nodeResultCard.running'),
        bgClass: 'bg-blue-50 dark:bg-blue-950',
        borderClass: 'border-blue-300 dark:border-blue-700',
        textClass: 'text-blue-600 dark:text-blue-400',
        iconClass: 'text-blue-500 dark:text-blue-400 animate-spin',
      };
    }
    case 'success': {
      return {
        icon: CheckCircle2,
        text: $t('ai-platform.workflow.editor.nodeResultCard.success'),
        bgClass: 'bg-green-50 dark:bg-green-950',
        borderClass: 'border-green-300 dark:border-green-700',
        textClass: 'text-green-600 dark:text-green-400',
        iconClass: 'text-green-500 dark:text-green-400',
      };
    }
    default: {
      return {
        icon: Clock,
        text: $t('ai-platform.workflow.editor.nodeResultCard.unknown'),
        bgClass: 'bg-muted',
        borderClass: 'border-border',
        textClass: 'text-muted-foreground',
        iconClass: 'text-muted-foreground',
      };
    }
  }
});

function toggleExpand() {
  if (hasDetails.value) {
    expanded.value = !expanded.value;
  }
}

function openDetailDialog() {
  detailVisible.value = true;
}

const formattedInputs = computed(() => {
  if (!displayResult.value.inputs) {
    return JSON.stringify({ variables: {}, previous_output: null }, null, 2);
  }
  return JSON.stringify(displayResult.value.inputs, null, 2);
});
</script>

<template>
  <div class="nodrag nopan w-[280px] max-w-[280px]" v-bind="$attrs">
    <ZqDialog
      v-model="detailVisible"
      width="90%"
      :show-footer="false"
      :draggable="false"
      :content-height="'calc(100vh - 200px)'"
    >
      <template #title>
        <div class="flex flex-wrap items-center gap-2">
          <component
            :is="statusConfig.icon"
            class="size-4"
            :class="statusConfig.iconClass"
          />
          <span class="text-sm font-medium" :class="statusConfig.textClass">
            {{ statusConfig.text }}
          </span>
          <span
            v-if="displayResult.elapsed_time !== undefined"
            class="text-muted-foreground text-sm"
          >
            {{ $t('ai-platform.workflow.editor.nodeResultCard.elapsed') }}
            {{ displayResult.elapsed_time }}ms
          </span>
          <span
            v-if="displayResult.tokens_used"
            class="text-muted-foreground text-sm"
          >
            Tokens: {{ displayResult.tokens_used }}
          </span>
          <div v-if="hasIterations" class="flex items-center gap-1.5">
            <span class="text-muted-foreground text-xs">
              {{ $t('ai-platform.workflow.editor.nodeResultCard.iteration') }}
            </span>
            <div class="flex gap-1">
              <button
                v-for="(iter, idx) in result.iterations"
                :key="idx"
                type="button"
                class="flex size-6 items-center justify-center rounded text-xs font-medium transition-colors"
                :class="[
                  selectedIteration === idx
                    ? 'bg-primary text-primary-foreground'
                    : 'bg-muted hover:bg-accent text-muted-foreground',
                  iter.status === 'failed' ? 'ring-1 ring-red-500' : '',
                ]"
                @click.stop="selectedIteration = idx"
              >
                {{ idx + 1 }}
              </button>
            </div>
          </div>
        </div>
      </template>

      <div class="grid h-full min-h-[520px] grid-cols-2 gap-4">
        <div class="flex min-h-0 flex-col overflow-hidden">
          <div class="text-foreground mb-2 text-sm font-medium">
            {{ $t('ai-platform.workflow.editor.nodeResultCard.input') }}
          </div>
          <div class="result-json-view min-h-0 flex-1 overflow-auto rounded border">
            <pre>{{ formattedInputs }}</pre>
          </div>
        </div>

        <div class="flex min-h-0 flex-col overflow-hidden">
          <div class="text-foreground mb-2 text-sm font-medium">
            {{ $t('ai-platform.workflow.editor.nodeResultCard.output') }}
          </div>
          <div class="result-json-view min-h-0 flex-1 overflow-auto rounded border">
            <pre>{{ formattedOutput }}</pre>
          </div>
        </div>
      </div>

      <div
        v-if="displayResult.status === 'failed' && displayResult.error_message"
        class="mt-4"
      >
        <div class="mb-2 text-sm font-medium text-red-600 dark:text-red-400">
          {{ $t('ai-platform.workflow.editor.nodeResultCard.errorInfo') }}
        </div>
        <div class="overflow-auto rounded border border-red-200 bg-red-50 p-4 dark:border-red-800 dark:bg-red-950">
          <pre class="whitespace-pre-wrap break-all font-mono text-sm text-red-600 dark:text-red-400">{{
            displayResult.error_message
          }}</pre>
        </div>
      </div>
    </ZqDialog>

    <div
      class="nodrag nopan w-full overflow-hidden rounded-lg border transition-all duration-200"
      :class="[statusConfig.bgClass, statusConfig.borderClass]"
      @mousedown.stop
      @pointerdown.stop
    >
      <div
        v-if="hasIterations"
        class="flex items-center gap-1 border-b px-3 py-1.5"
        :class="statusConfig.borderClass"
      >
        <span class="text-muted-foreground mr-1 text-[10px]">
          {{ $t('ai-platform.workflow.editor.nodeResultCard.iteration') }}
        </span>
        <div class="flex flex-wrap gap-1">
          <button
            v-for="(iter, idx) in result.iterations"
            :key="idx"
            type="button"
            class="nodrag nopan flex size-5 items-center justify-center rounded text-[10px] font-medium transition-colors"
            :class="[
              selectedIteration === idx
                ? 'bg-primary text-primary-foreground'
                : 'bg-muted hover:bg-accent text-muted-foreground',
              iter.status === 'failed' ? 'ring-1 ring-red-500' : '',
            ]"
            @click.stop="selectedIteration = idx"
            @pointerdown.stop
          >
            {{ idx + 1 }}
          </button>
        </div>
      </div>

      <div class="flex items-center justify-between px-3 py-2">
        <div
          class="flex min-w-0 flex-1 items-center gap-2"
          :class="{ 'cursor-pointer hover:opacity-80': hasDetails }"
          @click.stop="toggleExpand"
        >
          <component
            :is="statusConfig.icon"
            class="size-4 shrink-0"
            :class="statusConfig.iconClass"
          />
          <span class="truncate text-xs font-medium" :class="statusConfig.textClass">
            {{ statusConfig.text }}
          </span>
        </div>

        <div class="nodrag nopan flex shrink-0 items-center gap-1.5">
          <div
            v-if="displayResult.elapsed_time !== undefined"
            class="text-muted-foreground flex items-center gap-1 text-xs"
          >
            <Clock class="size-3" />
            <span>{{ displayResult.elapsed_time }}ms</span>
          </div>

          <div
            v-if="displayResult.tokens_used"
            class="text-muted-foreground flex items-center gap-1 text-xs"
          >
            <Zap class="size-3" />
            <span>{{ displayResult.tokens_used }}</span>
          </div>

          <button
            v-if="canOpenDetail"
            type="button"
            class="nodrag nopan hover:bg-accent flex size-6 shrink-0 items-center justify-center rounded"
            :title="$t('ai-platform.workflow.editor.nodeResultCard.fullscreen')"
            @click.stop="openDetailDialog"
            @pointerdown.stop
            @mousedown.stop
          >
            <Maximize class="text-muted-foreground size-3.5" />
          </button>

          <button
            v-if="hasDetails"
            type="button"
            class="nodrag nopan flex size-6 shrink-0 items-center justify-center rounded"
            @click.stop="toggleExpand"
            @pointerdown.stop
          >
            <component
              :is="expanded ? ChevronUp : ChevronDown"
              class="text-muted-foreground size-4"
            />
          </button>
        </div>
      </div>

      <div
        v-if="
          !expanded &&
          displayResult.status !== 'pending' &&
          displayResult.status !== 'running'
        "
        class="border-t px-3 py-2"
        :class="statusConfig.borderClass"
      >
        <div
          v-if="displayResult.status === 'failed'"
          class="text-xs text-red-600 dark:text-red-400"
        >
          {{
            displayResult.error_message ||
            $t('ai-platform.workflow.editor.nodeResultCard.execFailed')
          }}
        </div>
        <div v-else class="text-muted-foreground overflow-hidden text-xs">
          <pre class="whitespace-pre-wrap break-all font-sans">{{
            outputPreview
          }}</pre>
        </div>
      </div>

      <div
        v-if="
          displayResult.status === 'running' && displayResult.streaming_content
        "
        class="border-t px-3 py-2"
        :class="statusConfig.borderClass"
      >
        <div class="text-muted-foreground overflow-hidden text-xs">
          <pre class="whitespace-pre-wrap break-all font-sans">{{
            displayResult.streaming_content
          }}</pre>
          <span
            class="inline-block h-4 w-1 animate-pulse bg-blue-500 dark:bg-blue-400"
          ></span>
        </div>
      </div>

      <div
        v-if="expanded"
        class="space-y-3 border-t px-3 py-2"
        :class="statusConfig.borderClass"
      >
        <div v-if="displayResult.inputs">
          <div class="text-muted-foreground mb-1 text-xs font-medium">
            {{ $t('ai-platform.workflow.editor.nodeResultCard.input') }}
          </div>
          <div class="bg-card/50 max-h-32 overflow-auto rounded p-2 text-xs">
            <pre class="text-muted-foreground whitespace-pre-wrap break-all font-mono">{{
              JSON.stringify(displayResult.inputs, null, 2)
            }}</pre>
          </div>
        </div>

        <div v-if="displayResult.output !== undefined">
          <div class="text-muted-foreground mb-1 text-xs font-medium">
            {{ $t('ai-platform.workflow.editor.nodeResultCard.output') }}
          </div>
          <div class="bg-card/50 max-h-48 overflow-auto rounded p-2 text-xs">
            <pre class="text-muted-foreground whitespace-pre-wrap break-all font-mono">{{
              formattedOutput
            }}</pre>
          </div>
        </div>

        <div
          v-if="displayResult.status === 'failed' && displayResult.error_message"
        >
          <div class="mb-1 text-xs font-medium text-red-500 dark:text-red-400">
            {{ $t('ai-platform.workflow.editor.nodeResultCard.errorInfo') }}
          </div>
          <div
            class="rounded bg-red-100/50 p-2 text-xs text-red-600 dark:bg-red-900/50 dark:text-red-400"
          >
            {{ displayResult.error_message }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.result-json-view {
  background: hsl(var(--muted) / 35%);
  padding: 12px;
}

.result-json-view pre {
  min-height: 100%;
  margin: 0;
  color: hsl(var(--muted-foreground));
  font-family:
    ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
    'Courier New', monospace;
  font-size: 12px;
  line-height: 1.6;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
</style>
