<script setup>
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { ref, computed, watch, onMounted } from "vue";
import { YhIcon } from "../../icon";
import { loadMarkdown } from "../../markdown-it";
import { sanitizeMarkup } from "../../sanitize";
import { aiThoughtChainProps, aiThoughtChainEmits } from "./ai-thought-chain";
import { useComponentTheme } from "@yh-ui/theme";
defineOptions({
  name: "YhAiThoughtChain"
});
const props = defineProps(aiThoughtChainProps);
const emit = defineEmits(aiThoughtChainEmits);
const ns = useNamespace("ai-thought-chain");
const { t } = useLocale();
const { themeStyle } = useComponentTheme("ai-thought-chain", props.themeOverrides);
const isExpanded = ref(false);
const md = ref(null);
const isMdLoading = ref(false);
const loadMarkdownIt = async () => {
  if (md.value || isMdLoading.value) return;
  isMdLoading.value = true;
  try {
    const MarkdownItClass = await loadMarkdown();
    md.value = new MarkdownItClass({
      html: false,
      linkify: true,
      typographer: true
    });
  } catch (err) {
    console.error("[YhAiThoughtChain] \u65E0\u6CD5\u52A0\u8F7D markdown-it\u3002", err);
  } finally {
    isMdLoading.value = false;
  }
};
onMounted(() => {
  if (props.markdown) {
    loadMarkdownIt();
  }
});
watch(
  () => props.markdown,
  (val) => {
    if (val) loadMarkdownIt();
  }
);
const itemExpandedStates = ref([]);
const internalItems = ref([]);
const draggedIndex = ref(null);
const dragOverIndex = ref(null);
const itemsToUse = computed(() => {
  if (props.editable || props.draggable) {
    return internalItems.value.length > 0 ? internalItems.value : props.items;
  }
  return props.items;
});
watch(
  () => props.items,
  (newItems) => {
    if (Array.isArray(newItems)) {
      internalItems.value = [...newItems];
    } else {
      internalItems.value = [];
    }
  },
  { immediate: true, deep: true }
);
const ensureInternalItems = () => {
  if (!internalItems.value.length && props.items && props.items.length) {
    internalItems.value = [...props.items];
  }
};
const currentProgress = computed(() => {
  if (!itemsToUse.value || itemsToUse.value.length === 0) return 0;
  const completedCount = itemsToUse.value.filter(
    (item) => item.status === "success" || item.status === "complete"
  ).length;
  return Math.round(completedCount / itemsToUse.value.length * 100);
});
const currentStatus = computed(() => {
  if (props.status !== "none") return props.status;
  if (props.thinking === true) return "thinking";
  if (props.thinking === false) return "complete";
  return "none";
});
const displayTitle = computed(() => {
  if (props.title) return props.title;
  return currentStatus.value === "thinking" || currentStatus.value === "loading" ? t("ai.thoughtChain.thinking") : t("ai.thoughtChain.thoughtProcess");
});
const renderMarkdown = (content) => {
  if (!props.markdown || !content) return content;
  if (!md.value) return sanitizeMarkup(content);
  return sanitizeMarkup(md.value.render(content));
};
const getStatusIcon = (status = "none") => {
  switch (status) {
    case "thinking":
    case "loading":
      return "loading";
    case "success":
    case "complete":
      return "check-circle";
    case "error":
      return "circle-close";
    default:
      return "check-circle";
  }
};
watch(
  () => currentStatus.value,
  (newStatus) => {
    if (props.autoCollapse && (newStatus === "complete" || newStatus === "success")) {
      isExpanded.value = false;
    }
  }
);
watch(
  () => itemsToUse.value,
  (newItems) => {
    if (newItems && newItems.length > 0) {
      itemExpandedStates.value = newItems.map((item, index) => {
        if (item.expanded !== void 0) return item.expanded;
        return index === newItems.length - 1;
      });
    }
  },
  { immediate: true, deep: true }
);
const toggleExpand = () => {
  isExpanded.value = !isExpanded.value;
};
const toggleItemExpand = (index) => {
  itemExpandedStates.value[index] = !itemExpandedStates.value[index];
};
const handleItemClick = (item, index) => {
  if (item.clickable !== false) {
    emit("node-click", item, index);
  }
};
const handleDeleteNode = (item, index) => {
  emit("node-delete", item, index);
  if (!props.editable) return;
  ensureInternalItems();
  const newItems = [...internalItems.value];
  newItems.splice(index, 1);
  internalItems.value = newItems;
  emit("update:items", newItems);
  emit("reorder", newItems);
};
const handleAddNode = (index) => {
  emit("node-add", index);
  if (!props.editable) return;
  ensureInternalItems();
  const newItems = [...internalItems.value];
  newItems.splice(index + 1, 0, {
    title: t("ai.thoughtChain.defaultTitle"),
    status: "none"
  });
  internalItems.value = newItems;
  emit("update:items", newItems);
  emit("reorder", newItems);
};
const handleDragStart = (e, index) => {
  if (!props.draggable) return;
  draggedIndex.value = index;
  if (e.dataTransfer) {
    e.dataTransfer.effectAllowed = "move";
  }
};
const handleDragOver = (e, index) => {
  if (!props.draggable || draggedIndex.value === null) return;
  e.preventDefault();
  dragOverIndex.value = index;
};
const handleDragLeave = () => {
  dragOverIndex.value = null;
};
const handleDrop = (e, targetIndex) => {
  if (!props.draggable || draggedIndex.value === null) return;
  e.preventDefault();
  if (draggedIndex.value !== null) {
    ensureInternalItems();
    const newItems = [...internalItems.value];
    const [removed] = newItems.splice(draggedIndex.value, 1);
    newItems.splice(targetIndex, 0, removed);
    internalItems.value = newItems;
    emit("update:items", newItems);
    emit("reorder", newItems);
  }
  draggedIndex.value = null;
  dragOverIndex.value = null;
};
const handleDragEnd = () => {
  draggedIndex.value = null;
  dragOverIndex.value = null;
};
</script>

<template>
  <div
    :class="[ns.b(), ns.is('expanded', isExpanded), ns.is('thinking', currentStatus === 'thinking' || currentStatus === 'loading'), ns.is('timeline', itemsToUse && itemsToUse.length > 0), ns.is('draggable', draggable), className, classNames?.root || '']"
    :style="[themeStyle, style, styles?.root || {}]"
  >
    <!-- 进度条 -->
    <div
      v-if="showProgress && itemsToUse && itemsToUse.length > 0"
      :class="[ns.e('progress-bar'), classNames?.progressBar || '']"
      :style="styles?.progressBar || {}"
    >
      <div :class="ns.e('progress-fill')" :style="{
  width: currentProgress + '%'
}"></div>
    </div>

    <!-- 多节点时间轴模式 -->
    <template v-if="itemsToUse && itemsToUse.length > 0">
      <div
        v-for="(item, index) in itemsToUse"
        :key="item.id || index"
        :class="[ns.e('item'), ns.is('last', index === itemsToUse.length - 1), ns.is('active', item.status === 'thinking' || item.status === 'loading'), ns.is('drag-over', dragOverIndex === index), ns.is('dragging', draggedIndex === index), classNames?.item || '']"
        :style="styles?.item || {}"
        :draggable="draggable"
        @dragstart="handleDragStart($event, index)"
        @dragover="handleDragOver($event, index)"
        @dragleave="handleDragLeave"
        @drop="handleDrop($event, index)"
        @dragend="handleDragEnd"
      >
        <div
          :class="[ns.e('item-dot-wrapper'), classNames?.itemDotWrapper || '']"
          :style="styles?.itemDotWrapper || {}"
        >
          <div
            :class="[ns.e('item-dot'), ns.m(dotSize), ns.m(item.status || 'none'), classNames?.itemDot || '']"
            :style="styles?.itemDot || {}"
          >
            <YhIcon
              :name="item.icon || getStatusIcon(item.status)"
              :class="{
  'is-loading': item.status === 'thinking' || item.status === 'loading'
}"
            />
          </div>
          <div
            v-if="index < itemsToUse.length - 1"
            :class="[ns.e('item-line'), {
  'is-gradient': lineGradient
}, classNames?.itemLine || '']"
            :style="styles?.itemLine || {}"
          ></div>
        </div>

        <div
          :class="[ns.e('item-main'), classNames?.itemMain || '']"
          :style="styles?.itemMain || {}"
        >
          <div
            :class="[ns.e('item-header'), classNames?.itemHeader || '']"
            :style="styles?.itemHeader || {}"
            @click="toggleItemExpand(index)"
          >
            <!-- 拖拽手柄 -->
            <YhIcon v-if="draggable" name="rank" :class="ns.e('drag-handle')" />

            <span
              :class="[ns.e('item-title'), classNames?.itemTitle || '']"
              :style="styles?.itemTitle || {}"
              >{{ item.title }}</span
            >

            <!-- 节点进度 -->
            <span v-if="item.progress !== void 0" :class="ns.e('item-progress')">
              {{ item.progress }}%
            </span>

            <!-- 操作按钮 -->
            <div :class="ns.e('item-actions')" v-if="editable" @click.stop>
              <YhIcon
                name="delete"
                :class="ns.e('action-icon')"
                @click="handleDeleteNode(item, index)"
              />
              <YhIcon name="plus" :class="ns.e('action-icon')" @click="handleAddNode(index)" />
            </div>

            <YhIcon
              v-if="item.content || item.description"
              name="arrow-down"
              :class="[ns.e('item-arrow'), {
  'is-expanded': itemExpandedStates[index]
}]"
            />
          </div>

          <!-- 内容区域 -->
          <Transition name="yh-ai-thought-collapse">
            <div
              v-if="itemExpandedStates[index] && (item.content || item.description)"
              :class="[ns.e('item-content'), classNames?.itemContent || '']"
              :style="styles?.itemContent || {}"
              @click="handleItemClick(item, index)"
            >
              <!-- 支持 Markdown：内容来自 renderMarkdown，仅用于受控的思维链节点 -->
              <!-- eslint-disable vue/no-v-html -->
              <div
                v-if="markdown"
                :class="ns.e('item-text')"
                v-html="renderMarkdown(item.content || item.description || '')"
              ></div>
              <!-- eslint-enable vue/no-v-html -->
              <!-- 纯文本 -->
              <div v-else :class="ns.e('item-text')">{{ item.content || item.description }}</div>
            </div>
          </Transition>
        </div>
      </div>

      <!-- 添加节点按钮 -->
      <div v-if="editable" :class="ns.e('add-node')" @click="handleAddNode(itemsToUse.length)">
        <YhIcon name="plus" />
        <span>{{ t("ai.thoughtChain.addNode") }}</span>
      </div>
    </template>

    <!-- 单节点/传统模式 -->
    <template v-else>
      <div
        :class="[ns.e('header'), classNames?.header || '']"
        :style="styles?.header || {}"
        @click="toggleExpand"
      >
        <div :class="ns.e('icon')">
          <YhIcon
            :name="getStatusIcon(currentStatus)"
            :class="[ns.e('status-icon'), {
  'is-loading': currentStatus === 'thinking' || currentStatus === 'loading'
}]"
          />
        </div>
        <div :class="[ns.e('title'), classNames?.title || '']" :style="styles?.title || {}">
          {{ displayTitle }}
        </div>
        <YhIcon name="arrow-down" :class="[ns.e('arrow'), {
  'is-expanded': isExpanded
}]" />
      </div>

      <Transition name="yh-ai-thought-collapse">
        <div
          v-if="isExpanded"
          :class="[ns.e('content'), classNames?.content || '']"
          :style="styles?.content || {}"
        >
          <slot>
            <div :class="ns.e('text')">{{ content }}</div>
          </slot>
        </div>
      </Transition>
    </template>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-ai-thought-chain {
  margin: 12px 0;
  border-left: 3px solid var(--yh-color-info-light-5);
  padding-left: 12px;
  max-width: 100%;
  transition: all 0.3s ease;
  container-type: inline-size;
  container-name: ai-thought-chain;
}
.yh-ai-thought-chain__progress-bar {
  height: 4px;
  background: var(--yh-border-color-lighter);
  border-radius: 2px;
  margin-bottom: 16px;
  overflow: hidden;
}

.yh-ai-thought-chain__progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--yh-color-primary), var(--yh-color-success));
  border-radius: 2px;
  transition: width 0.3s ease;
}

.yh-ai-thought-chain.is-thinking {
  border-left-color: var(--yh-color-primary);
}
.yh-ai-thought-chain.is-thinking .yh-ai-thought-chain__title {
  color: var(--yh-color-primary);
  background: linear-gradient(90deg, var(--yh-color-primary) 0%, var(--yh-color-primary-light-3) 35%, var(--yh-color-primary) 70%);
  background-size: 200% 100%;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: yh-ai-thought-title-wave 1.6s ease-in-out infinite;
}

.yh-ai-thought-chain.is-draggable .yh-ai-thought-chain__item {
  cursor: move;
}
.yh-ai-thought-chain.is-draggable .yh-ai-thought-chain__item.is-dragging {
  opacity: 0.5;
}
.yh-ai-thought-chain.is-draggable .yh-ai-thought-chain__item.is-drag-over {
  background: var(--yh-color-primary-light-9);
}

.yh-ai-thought-chain.is-draggable .yh-ai-thought-chain__drag-handle {
  margin-right: 8px;
  cursor: grab;
  color: var(--yh-text-color-placeholder);
  font-size: 12px;
}
.yh-ai-thought-chain.is-draggable .yh-ai-thought-chain__drag-handle:active {
  cursor: grabbing;
}

.yh-ai-thought-chain__item-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 12px;
  opacity: 0;
  transition: opacity 0.2s;
}

.yh-ai-thought-chain__item-header:hover .yh-ai-thought-chain__item-actions {
  opacity: 1;
}

.yh-ai-thought-chain__action-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  font-size: 16px;
  color: var(--yh-text-color-secondary);
  cursor: pointer;
  border-radius: 6px;
  transition: all 0.15s ease-out;
}
.yh-ai-thought-chain__action-icon:hover {
  color: var(--yh-color-primary);
  background: var(--yh-fill-color-light);
  transform: scale(1.05);
}

.yh-ai-thought-chain__item-progress {
  margin-left: 8px;
  font-size: 12px;
  color: var(--yh-color-primary);
  font-weight: 500;
}

.yh-ai-thought-chain__add-node {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin-left: 32px;
  color: var(--yh-text-color-secondary);
  font-size: 13px;
  cursor: pointer;
  border-radius: 6px;
  transition: all 0.2s;
}
.yh-ai-thought-chain__add-node:hover {
  color: var(--yh-color-primary);
  background: var(--yh-fill-color-light);
}

.yh-ai-thought-chain__header {
  display: flex;
  align-items: center;
  cursor: pointer;
  font-size: 13px;
  color: var(--yh-text-color-secondary);
  user-select: none;
  transition: color 0.2s;
}
.yh-ai-thought-chain__header:hover {
  color: var(--yh-color-primary);
}

.yh-ai-thought-chain__icon {
  margin-right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.yh-ai-thought-chain__status-icon {
  font-size: 14px;
  color: var(--yh-color-success);
}
.yh-ai-thought-chain__status-icon.is-loading {
  color: var(--yh-color-primary);
  animation: yh-spin 1s linear infinite;
}

.yh-ai-thought-chain__title {
  font-weight: 500;
  flex: 1;
}

.yh-ai-thought-chain__arrow {
  transition: transform 0.3s;
  margin-left: 8px;
}
.yh-ai-thought-chain__arrow.is-expanded {
  transform: rotate(180deg);
}

.yh-ai-thought-chain__content {
  margin-top: 8px;
  padding: 12px;
  background-color: var(--yh-fill-color-light);
  border-radius: 8px;
  font-size: 13px;
  color: var(--yh-text-color-regular);
  line-height: 1.6;
  animation: yh-fade-in 0.3s ease;
}

.yh-ai-thought-chain__text {
  white-space: pre-wrap;
  word-break: break-all;
}

.yh-ai-thought-chain.is-timeline {
  border-left: none;
  padding-left: 0;
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item {
  display: flex;
  gap: 12px;
  position: relative;
  padding-bottom: 20px;
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item.is-last {
  padding-bottom: 0;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 20px;
  flex-shrink: 0;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  z-index: 1;
  background: var(--yh-bg-color);
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--thinking {
  color: var(--yh-color-primary);
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--thinking .yh-icon.is-loading {
  animation: yh-spin 1s linear infinite;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--loading {
  color: var(--yh-color-primary);
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--loading .yh-icon.is-loading {
  animation: yh-spin 1s linear infinite;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--success {
  color: var(--yh-color-success);
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--complete {
  color: var(--yh-color-success);
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--error {
  color: var(--yh-color-danger);
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--none {
  color: var(--yh-color-info-light-3);
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--small {
  width: 14px;
  height: 14px;
  font-size: 12px;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--default {
  width: 20px;
  height: 20px;
  font-size: 14px;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-dot--large {
  width: 26px;
  height: 26px;
  font-size: 18px;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-line {
  position: absolute;
  top: 20px;
  bottom: 0;
  left: 9px;
  width: 2px;
  background: var(--yh-border-color-lighter);
  z-index: 0;
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-line.is-gradient {
  background: linear-gradient(to bottom, var(--yh-color-primary), var(--yh-border-color-lighter));
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-main {
  flex: 1;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-header {
  display: flex;
  align-items: center;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  color: var(--yh-text-color-primary);
  height: 20px;
  transition: color 0.2s;
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-header:hover {
  color: var(--yh-color-primary);
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-title {
  transition: color 0.2s ease;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item.is-active .yh-ai-thought-chain__item-title {
  color: var(--yh-color-primary);
  background: linear-gradient(90deg, var(--yh-color-primary) 0%, var(--yh-color-primary-light-3) 35%, var(--yh-color-primary) 70%);
  background-size: 200% 100%;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: yh-ai-thought-title-wave 1.6s ease-in-out infinite;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-arrow {
  margin-left: 6px;
  font-size: 12px;
  color: var(--yh-text-color-secondary);
  transition: transform 0.3s;
}
.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-arrow.is-expanded {
  transform: rotate(180deg);
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-content {
  margin-top: 8px;
  padding: 10px;
  background: var(--yh-fill-color-light);
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.5;
  animation: yh-fade-in 0.3s ease;
}

.yh-ai-thought-chain.is-timeline .yh-ai-thought-chain__item .yh-ai-thought-chain__item-text {
  white-space: pre-wrap;
}

@container ai-thought-chain (max-width: 560px) {
  .yh-ai-thought-chain__add-node {
    margin-left: 0;
  }
  .yh-ai-thought-chain__item-header {
    flex-wrap: wrap;
    height: auto;
    row-gap: 6px;
  }
  .yh-ai-thought-chain__item-actions {
    opacity: 1;
    margin-left: 0;
  }
  .yh-ai-thought-chain__item-progress {
    margin-left: 0;
  }
}
@container ai-thought-chain (max-width: 420px) {
  .yh-ai-thought-chain__content {
    padding: 10px;
  }
  .yh-ai-thought-chain__item-content {
    padding: 8px;
  }
}

@keyframes yh-spin {
  100% {
    transform: rotate(360deg);
  }
}
@keyframes yh-fade-in {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes yh-ai-thought-title-wave {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .yh-ai-thought-chain.is-thinking .yh-ai-thought-chain__title,
  .yh-ai-thought-chain__item.is-active .yh-ai-thought-chain__item-title {
    animation: none;
  }
}
.yh-ai-thought-collapse-enter-active,
.yh-ai-thought-collapse-leave-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  max-height: 500px;
  overflow: hidden;
}

.yh-ai-thought-collapse-enter-from,
.yh-ai-thought-collapse-leave-to {
  max-height: 0;
  opacity: 0;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  margin-top: 0 !important;
  transform: translateY(-10px);
}
</style>
