<template>
  <view class="flex flex-col bg-white h-screen overflow-hidden">
    <!-- ✅ 顶部固定导航 -->
    <view class="flex-shrink-0">
      <TopNavBar :title="title" background="transparent" />
    </view>

    <!-- ✅ 滚动区域 -->
    <scroll-view class="flex-full overflow-hidden chat-scroll" scroll-y :scroll-into-view="scrollIntoViewId"
      scroll-with-animation @scroll="onScroll" @touchstart="onTouchStart" @touchend="onTouchEnd"
      @touchcancel="onTouchEnd">
      <view class="flex flex-col pt-[12px] px-[16px] pb-[24px]  gap-[10px]">
        <template v-if="hasStructuredLongTextData">
          <view v-if="headerSections.title || headerSections.tag" class="long-answer-header">
            <view v-if="headerSections.title" class="long-answer-title">
              {{ headerSections.title.contentValue }}
            </view>
            <view v-if="headerSections.tag" class="long-answer-tag" :style="longAnswerTagStyle">
              {{ headerSections.tag.contentValue }}
            </view>
          </view>

          <template v-for="section in contentSections" :key="section.contentKey">
            <LongAnswerSectionSkeleton v-if="shouldRenderSectionSkeleton(section)" />

            <ParsedValueView v-else-if="shouldUseParsedValueView(section)" :field-key="section.contentKey"
              :value="section.parsedValue !== null ? section.parsedValue : section.contentValue" />

            <ChatMarkdown v-else :text="section.contentValue" />
          </template>
        </template>

        <ChatMarkdown v-else-if="answerText" :text="answerText" />

        <!-- ✅ 底部锚点（必须存在） -->
        <view id="bottom-anchor"></view>
      </view>
    </scroll-view>
  </view>
</template>

<script setup>
import TopNavBar from "@/components/TopNavBar/index.vue";
import ChatMarkdown from "../ChatMarkdown/index.vue";
import LongAnswerSectionSkeleton from "./LongAnswerSectionSkeleton.vue";
import ParsedValueView from "./ParsedValueView.vue";
import { defineProps, ref, nextTick, computed } from "vue";
import { onLoad, onUnload } from "@dcloudio/uni-app";
import StreamManager from "@/utils/StreamManager.js";
import {
  LONG_TEXT_KEYS,
  getLongTextSections,
  getLongTextValue,
} from "@/utils/longTextCard";
import { buildTagToneStyle, pickRandomTagToneColor } from "@/utils/tagTone";

const props = defineProps({
  answerText: {
    type: String,
    default: "",
  },
});

const answerText = ref(props.answerText || "");
const title = ref("");
const longTextData = ref(null);
const streamFinished = ref(false);
const longAnswerTagColor = ref(pickRandomTagToneColor());
const longAnswerTagStyle = computed(() => buildTagToneStyle(longAnswerTagColor.value));

let unsubscribe = null;

const HIDDEN_DETAIL_SECTION_KEYS = [];
const hasStructuredLongTextData = computed(() => {
  const values = longTextData.value?.values;
  return !!(values && Object.keys(values).length > 0);
});

const shouldUseParsedValueView = (section) => {
  return (
    section.fromLongTextData &&
    section.contentKey !== LONG_TEXT_KEYS.tag &&
    section.contentKey !== LONG_TEXT_KEYS.title &&
    !HIDDEN_DETAIL_SECTION_KEYS.includes(section.contentKey)
  );
};

const renderSections = computed(() => {
  if (!hasStructuredLongTextData.value) return [];

  return getLongTextSections(longTextData.value)
    .filter((section) => section.contentValue)
    .map((section) => ({
      ...section,
      fromLongTextData: true,
    }));
});

const headerSections = computed(() => {
  const sections = renderSections.value;
  return {
    title: sections.find((section) => section.contentKey === LONG_TEXT_KEYS.title),
    tag: sections.find((section) => section.contentKey === LONG_TEXT_KEYS.tag),
  };
});

const contentSections = computed(() => {
  return renderSections.value.filter(
    (section) =>
      section.contentKey !== LONG_TEXT_KEYS.title &&
      section.contentKey !== LONG_TEXT_KEYS.tag &&
      !HIDDEN_DETAIL_SECTION_KEYS.includes(section.contentKey)
  );
});

const getSectionIndex = (section) => {
  return contentSections.value.findIndex((item) => item.contentKey === section?.contentKey);
};

const hasSectionAfter = (section) => {
  const sectionIndex = getSectionIndex(section);
  return sectionIndex >= 0 && sectionIndex < contentSections.value.length - 1;
};

const isNonStringSectionValue = (value) => {
  return value !== undefined && value !== null && typeof value !== "string";
};

const isPendingStructuredText = (value) => {
  const text = typeof value === "string" ? value.trim() : "";
  return text.startsWith("{") || text.startsWith("[");
};

const isStructuredSection = (section) => {
  return (
    section?.fromLongTextData &&
    (
      (section.parsedValue !== null && isNonStringSectionValue(section.parsedValue)) ||
      isPendingStructuredText(section.contentValue)
    )
  );
};

const isSectionReady = (section) => {
  if (!isStructuredSection(section)) return true;
  return (
    streamFinished.value ||
    (section.parsedValue !== null && isNonStringSectionValue(section.parsedValue)) ||
    hasSectionAfter(section)
  );
};

const shouldRenderSectionSkeleton = (section) => {
  return isStructuredSection(section) && !isSectionReady(section);
};

/** ✅ scroll-into-view 控制 */
const scrollIntoViewId = ref("");

/** 滚动控制状态 */
const isNearBottom = ref(true);
const scrollViewHeight = ref(0);
const SCROLL_THRESHOLD = 150; // px

/** 用户交互状态，用户滚动/触摸时临时禁用自动滚动 */
const userInteracting = ref(false);
let interactionTimer = null;

/** 是否已完成（从 URL 参数判断），完成状态下不初始初自动滚到底部 */
let isFinishedOnInit = false;

/** ✅ 防抖 */
let scrollTimer = null;

const measureScrollViewHeight = () => {
  try {
    // 使用 uni.createSelectorQuery 获取 scroll-view 的准确高度
    uni.createSelectorQuery()
      .select(".chat-scroll")
      .boundingClientRect((rect) => {
        if (rect && rect.height) {
          scrollViewHeight.value = rect.height;
        }
      })
      .exec();
  } catch (e) { }
}

/** 生成展示用标题：去除前导 `#` 并截取前 6 字符（超过加省略号） */
const computeTitle = (text = "") => {
  const t = (text || "").replace(/^#+\s*/, "");
  return t.length > 8 ? t.substring(0, 8) + "..." : t;
}

const onScroll = (e) => {
  try {
    const { scrollTop = 0, scrollHeight = 0 } = e.detail || {};

    // 计算距离底部的距离（使用准确的 scroll-view 高度）
    const viewHeight = scrollViewHeight.value;
    const distanceToBottom = scrollHeight - scrollTop - viewHeight;

    // 判断是否在底部附近（允许 SCROLL_THRESHOLD 的误差范围）
    // 注意：只更新 isNearBottom，不在滚动时强制改变 userInteracting
    const atBottom = distanceToBottom <= SCROLL_THRESHOLD;
    isNearBottom.value = atBottom;
  } catch (e) { }
}

const onTouchStart = () => {
  // 触摸开始时，立即标记为用户交互状态
  userInteracting.value = true;
  clearTimeout(interactionTimer);
}

const onTouchEnd = () => {
  // 触摸结束后延迟一段时间再取消交互状态
  // 这样即使用户快速滚动，也不会被中途打断
  clearTimeout(interactionTimer);
  interactionTimer = setTimeout(() => {
    userInteracting.value = false;
  }, 600);
}

const scrollToBottom = () => {
  if (scrollTimer) return;
  if (isFinishedOnInit) return;

  scrollTimer = setTimeout(() => {
    // ❗关键：强制触发滚动（小程序必须这样）
    // 如果用户正在交互，则跳过本次自动滚动
    if (userInteracting.value) {
      scrollTimer = null;
      return;
    }

    scrollIntoViewId.value = "";

    nextTick(() => {
      // 再次 nextTick + 延迟，兼容 markdown 渲染延迟
      setTimeout(() => {
        scrollIntoViewId.value = "bottom-anchor";
        // 测量高度以便后续滚动判断准确
        measureScrollViewHeight();
      }, 50);
    });

    scrollTimer = null;
  }, 100);
}

onLoad(({ message = "", streamId = "", finished = "0", tagToneColor = "" }) => {
  // 记录初始完成状态
  isFinishedOnInit = finished === "1";
  streamFinished.value = isFinishedOnInit;
  longAnswerTagColor.value = tagToneColor ? decodeURIComponent(tagToneColor) : longAnswerTagColor.value;

  console.log("LongAnswer onLoad with params:", { message, streamId, finished, tagToneColor });

  // 初次测量 scroll-view 高度
  nextTick(() => {
    measureScrollViewHeight();
  });

  if (streamId) {
    // ✅ 流式数据
    unsubscribe = StreamManager.subscribe(
      streamId,
      (text = "", finished = false, payload = null) => {
        streamFinished.value = !!finished;
        answerText.value = text || "";
        longTextData.value = payload || null;
        title.value = computeTitle(
          getLongTextValue(longTextData.value, LONG_TEXT_KEYS.title) || answerText.value
        );

        nextTick(() => {
          // 每次接收数据都重新测量高度（content size 可能变化，比如加载图）
          measureScrollViewHeight();

          // 流式完成时强制滚动到底部
          if (finished) {
            scrollToBottom();
          }
          // 流式中的数据更新：只有在用户未交互且接近底部时才自动滚动
          else if (!userInteracting.value && isNearBottom.value) {
            scrollToBottom();
          }
        });
      }
    );
  } else {
    // ✅ 非流式
    answerText.value = decodeURIComponent(message || "");
    longTextData.value = null;
    streamFinished.value = true;
    title.value = computeTitle(answerText.value);

    nextTick(() => {
      // 只有在初始化为非完成状态时才自动滚到底部
      scrollToBottom();
    });
  }
});

onUnload(() => {
  try {
    unsubscribe && unsubscribe();
  } catch (e) { }
  // 清理定时器，避免内存泄漏
  try { clearTimeout(scrollTimer); } catch (e) { }
  try { clearTimeout(interactionTimer); } catch (e) { }
  scrollTimer = null;
  interactionTimer = null;
});
</script>

<style scoped lang="scss">
@import "./styles/index.scss";
</style>
