<script setup lang="ts">
import { createComment, createReply, listCommentReplies, listComments } from '@/api/halo-base/comment'
import { completeUrl } from '@/utils/url'
import { avatar } from '@/utils/imageHelper'
import { timeFrom } from '@/utils/base/timeFrom'
import type { CommentV1alpha1PublicApiListCommentRepliesRequest, CommentV1alpha1PublicApiListComments1Request, CommentWithReplyVo, ReplyVo } from '@halo-dev/api-client'
import type { IHaloListResponseBase } from '@/api/types/halo'

interface IProps {
  postName: string
  commentSubjectVersion: string
  commentCount?: number
}

const props = withDefaults(defineProps<IProps>(), {
  commentCount: 0,
})

const emits = defineEmits<{
  (e: 'close'): void
  (e: 'commented'): void
}>()

// --- 评论列表 ---
const commentList = ref<CommentWithReplyVo[]>([])
const commentPage = ref(1)
const commentHasNext = ref(false)
const commentLoading = ref(false)

// --- 回复目标 ---
const replyTarget = ref<{
  commentName: string
  replyName?: string
  displayName: string
} | null>(null)

// --- 输入内容 ---
const inputText = ref('')
const submitLoading = ref(false)

// --- 展开回复的评论 ---
const expandedReplies = ref<Set<string>>(new Set())
const replyLoadingMap = ref<Record<string, boolean>>({})
const replyHasNextMap = ref<Record<string, boolean>>({})
const replyPageMap = ref<Record<string, number>>({})

// --- 获取评论列表 ---
async function fetchComments(page = 1, append = false) {
  commentLoading.value = true
  try {
    const res = await listComments({
      group: 'content.halo.run',
      name: props.postName,
      kind: 'Post',
      version: props.commentSubjectVersion,
      page,
      size: 20,
      sort: ['metadata.creationTimestamp,desc'],
    } as CommentV1alpha1PublicApiListComments1Request)
    const data = res as unknown as IHaloListResponseBase<CommentWithReplyVo>
    if (append) {
      commentList.value = [...commentList.value, ...(data.items ?? [])]
    }
    else {
      commentList.value = data.items ?? []
    }
    commentHasNext.value = data.hasNext
    commentPage.value = page
  }
  catch (err) {
    console.error('获取评论失败:', err)
  }
  finally {
    commentLoading.value = false
  }
}

// --- 加载更多评论 ---
function handleLoadMoreComments() {
  if (commentLoading.value || !commentHasNext.value)
    return
  fetchComments(commentPage.value + 1, true)
}

// --- 获取回复列表 ---
async function fetchReplies(commentName: string, page = 1, append = false) {
  replyLoadingMap.value[commentName] = true
  try {
    const res = await listCommentReplies({
      name: commentName,
      page,
      size: 10,
    } as CommentV1alpha1PublicApiListCommentRepliesRequest)
    const data = res as unknown as IHaloListResponseBase<ReplyVo>
    const comment = commentList.value.find(c => c.metadata.name === commentName)
    if (comment) {
      if (append) {
        comment.replies = {
          ...comment.replies,
          items: [...(comment.replies?.items ?? []), ...(data.items ?? [])],
          hasNext: data.hasNext,
        } as any
      }
      else {
        comment.replies = {
          ...data,
          items: data.items ?? [],
        } as any
      }
    }
    replyHasNextMap.value[commentName] = data.hasNext
    replyPageMap.value[commentName] = page
  }
  catch (err) {
    console.error('获取回复失败:', err)
    uni.showToast({ title: '获取回复失败', icon: 'none' })
  }
  finally {
    replyLoadingMap.value[commentName] = false
  }
}

// --- 切换展开回复 ---
function handleToggleReplies(comment: CommentWithReplyVo) {
  const name = comment.metadata.name
  if (expandedReplies.value.has(name)) {
    expandedReplies.value.delete(name)
  }
  else {
    expandedReplies.value.add(name)
    if (!comment.replies?.items?.length) {
      fetchReplies(name)
    }
  }
}

// --- 加载更多回复 ---
function handleLoadMoreReplies(commentName: string) {
  if (replyLoadingMap.value[commentName] || !replyHasNextMap.value[commentName])
    return
  fetchReplies(commentName, (replyPageMap.value[commentName] ?? 1) + 1, true)
}

// --- 设置回复目标 ---
function handleReply(commentName: string, replyName: string | undefined, displayName: string) {
  replyTarget.value = { commentName, replyName, displayName }
}

// --- 取消回复 ---
function handleCancelReply() {
  replyTarget.value = null
}

// --- 提交评论/回复 ---
async function handleSubmit() {
  const text = inputText.value.trim()
  if (!text || submitLoading.value)
    return

  submitLoading.value = true
  try {
    if (replyTarget.value) {
      await createReply({
        name: replyTarget.value.commentName,
        replyRequest: {
          content: text,
          raw: text,
          quoteReply: replyTarget.value.replyName || undefined,
          allowNotification: true,
        },
      } as any)
    }
    else {
      await createComment({
        commentRequest: {
          content: text,
          raw: text,
          subjectRef: {
            group: 'content.halo.run',
            kind: 'Post',
            name: props.postName,
            version: props.commentSubjectVersion,
          },
          allowNotification: true,
        },
      } as any)
    }

    inputText.value = ''
    replyTarget.value = null
    uni.showToast({ title: '评论成功', icon: 'none' })
    await fetchComments(1)
    emits('commented')
  }
  catch (err) {
    console.error('评论失败:', err)
    uni.showToast({ title: '评论失败', icon: 'none' })
  }
  finally {
    submitLoading.value = false
  }
}

// --- 关闭面板 ---
function handleClose() {
  emits('close')
}

defineExpose({
  refresh: () => fetchComments(),
})

onMounted(() => {
  fetchComments()
})
</script>

<template>
  <view class="uh-backdrop-blur fixed inset-0 z-110 flex items-end bg-black/20" @click="handleClose">
    <wd-transition :show="true" :duration="300" name="slide-up" :lazy-render="false">
      <!-- 面板主体 -->
      <view
        class="box-border w-screen flex flex-col rounded-t-3xl bg-white"
        @click.stop
      >
        <!-- 拖拽指示条 -->
        <view class="w-full center py-2" @click.stop="handleClose">
          <view class="h-1 w-10 rounded-full bg-gray-300" />
        </view>

        <!-- 头部 -->
        <view class="box-border flex items-center justify-between border-b border-gray-100 px-4 pb-3">
          <text class="text-base text-gray-900 font-bold">
            说点什么 <text v-if="commentCount > 0" class="text-sm text-gray-600 font-normal">（{{ commentCount }}）</text>
          </text>
          <view class="h-8 w-8 center rounded-full bg-gray-50" @click="handleClose">
            <wd-icon name="close" color="#6B7280" :size="18" />
          </view>
        </view>

        <!-- 评论列表 -->
        <scroll-view
          class="h-[60vh] overflow-hidden"
          scroll-y
          @scrolltolower="handleLoadMoreComments"
        >
          <view class="box-border h-full px-4 pt-3">
            <!-- 加载中 -->
            <view v-if="commentLoading && commentList.length === 0" class="box-border h-full center">
              <wd-loading />
            </view>

            <!-- 空状态 -->
            <view v-else-if="!commentLoading && commentList.length === 0" class="box-border h-full center flex-col gap-y-2">
              <wd-icon name="chat" color="#D1D5DB" :size="40" />
              <text class="text-sm text-gray-400">快来抢沙发吧~</text>
            </view>

            <!-- 评论列表 -->
            <view v-else class="box-border h-full w-full flex flex-col">
              <view
                v-for="comment in commentList"
                :key="comment.metadata.name"
                class="border-b border-gray-50 py-3"
              >
                <view class="flex gap-x-3">
                  <!-- 头像 -->
                  <image
                    class="uh-shadow-md box-border h-9 w-9 shrink-0 border-2 border-white rounded-xl border-solid bg-gray-100"
                    :src="avatar(comment.owner.avatar)"
                    mode="aspectFill"
                  />

                  <!-- 内容区 -->
                  <view class="flex flex-1 flex-col gap-y-2 overflow-hidden">
                    <view class="flex items-center justify-between">
                      <text class="text-xs text-gray-500 font-medium">{{ comment.owner.displayName || '匿名用户' }}</text>
                      <text class="text-[11px] text-gray-400">{{ timeFrom(comment.spec.creationTime || comment.metadata.creationTimestamp) }}</text>
                    </view>

                    <text class="text-sm text-gray-900 leading-5">
                      <rich-text :nodes="comment.spec.raw" />
                    </text>

                    <!-- 操作栏 -->
                    <view class="flex items-center gap-x-4">
                      <view
                        class="flex items-center gap-x-1"
                        @click="handleReply(comment.metadata.name, undefined, comment.owner.displayName || '匿名用户')"
                      >
                        <wd-icon name="message" color="#9CA3AF" :size="14" />
                        <text class="text-[11px] text-gray-400">回复</text>
                      </view>
                      <view
                        v-if="(comment.status?.replyCount ?? 0) > 0"
                        class="flex items-center gap-x-1"
                        @click="handleToggleReplies(comment)"
                      >
                        <wd-icon
                          :name="expandedReplies.has(comment.metadata.name) ? 'up' : 'down'"
                          color="#9CA3AF"
                          :size="14"
                        />
                        <text class="text-[11px] text-gray-400">
                          {{ expandedReplies.has(comment.metadata.name) ? '收起' : `${comment.status?.replyCount}条回复` }}
                        </text>
                      </view>
                    </view>

                    <!-- 回复列表 -->
                    <view v-if="expandedReplies.has(comment.metadata.name)" class="mt-2 flex flex-col gap-y-2 rounded-xl bg-gray-50 p-3">
                      <view
                        v-for="reply in (comment.replies?.items ?? [])"
                        :key="reply.metadata.name"
                        class="flex gap-x-2.5"
                      >
                        <image
                          class="h-7 w-7 shrink-0 border-2 border-white rounded-lg border-solid bg-gray-200"
                          :src="avatar(reply.owner.avatar)"
                          mode="aspectFill"
                        />
                        <view class="flex flex-1 flex-col gap-y-1.5 overflow-hidden">
                          <view class="flex items-center justify-between">
                            <text class="text-[11px] text-gray-500 font-medium">{{ reply.owner.displayName || '匿名用户' }}</text>
                            <text class="text-[10px] text-gray-400">{{ timeFrom(reply.spec.creationTime || reply.metadata.creationTimestamp) }}</text>
                          </view>

                          <view v-if="reply.spec.quoteReply" class="rounded-lg bg-gray-100 px-2.5 py-1.5">
                            <text class="text-[11px] text-gray-400">回复 {{ reply.spec.quoteReply }}：</text>
                          </view>

                          <text class="text-xs text-gray-700 leading-4.5">
                            <rich-text :nodes="reply.spec.raw" />
                          </text>

                          <view
                            class="flex items-center gap-x-1"
                            @click="handleReply(comment.metadata.name, reply.metadata.name, reply.owner.displayName || '匿名用户')"
                          >
                            <wd-icon name="message" color="#9CA3AF" :size="12" />
                            <text class="text-[10px] text-gray-400">回复</text>
                          </view>
                        </view>
                      </view>

                      <!-- 加载更多回复 -->
                      <view
                        v-if="replyHasNextMap[comment.metadata.name]"
                        class="center py-1"
                        @click="handleLoadMoreReplies(comment.metadata.name)"
                      >
                        <text class="text-xs text-gray-400">
                          {{ replyLoadingMap[comment.metadata.name] ? '加载中...' : '查看更多回复' }}
                        </text>
                      </view>

                      <view v-if="replyLoadingMap[comment.metadata.name] && !(comment.replies?.items?.length)" class="center py-2">
                        <wd-loading :size="20" color="#1a1a1a" > 加载中 </wd-loading>
                      </view>
                    </view>
                  </view>
                </view>
              </view>

              <!-- 加载更多 -->
              <view v-if="commentHasNext" class="center py-3" @click="handleLoadMoreComments">
                <text class="text-xs text-gray-400">{{ commentLoading ? '加载中...' : '加载更多评论' }}</text>
              </view>

              <view class="h-4 w-full" />
            </view>
          </view>
        </scroll-view>

        <!-- 底部输入区 -->
        <view class="box-border border-t border-gray-100 px-4 pt-2">
          <!-- 回复提示 -->
          <view v-if="replyTarget" class="mb-2 flex items-center justify-between rounded-lg bg-gray-50 px-3 py-1.5">
            <text class="text-xs text-gray-500">回复 {{ replyTarget.displayName }}</text>
            <view @click="handleCancelReply">
              <wd-icon name="close" color="#9CA3AF" :size="14" />
            </view>
          </view>

          <view class="flex items-center gap-x-3 pb-2">
            <input
              v-model="inputText"
              class="flex-1 rounded-xl bg-gray-50 px-4 py-2.5 text-sm active:bg-gray-100 focus:bg-gray-100"
              :placeholder="replyTarget ? `回复 ${replyTarget.displayName}...` : '写评论...'"
              confirm-type="send"
              :adjust-position="true"
              @confirm="handleSubmit"
            >
            <view
              class="h-9 w-9 center shrink-0 rounded-xl transition-colors"
              :class="inputText.trim() ? 'bg-gray-900' : 'bg-gray-200'"
              @click="handleSubmit"
            >
              <wd-icon name="arrow-up" :color="inputText.trim() ? '#FFFFFF' : '#9CA3AF'" :size="18" />
            </view>
          </view>
        </view>
      </view>
    </wd-transition>
  </view>
</template>
