<script setup lang="ts">
import { unwrapApiBody, type ApiResponse } from '~/utils/http/factory'
import { useAuthSession } from '~/composables/useAuthSession'

type CommentNode = {
  id: number
  parentId: number | null
  kind: string
  guestDisplayName: string | null
  author: { nickname: string | null; username: string | null } | null
  body: string | null
  deleted: boolean
  createdAt: string
  children: CommentNode[]
  viewerCanDelete: boolean
}

type CommentsPayload = {
  postId: number
  viewerCanModeratePost: boolean
  comments: CommentNode[]
}

const props = defineProps<{
  mode: 'public-post' | 'unlisted'
  publicSlug: string
  postSlug?: string
  shareToken?: string
}>()

const { loggedIn, refresh: refreshAuthSession } = useAuthSession()
const { fetchData } = useClientApi()
const toast = useToast()

onMounted(() => {
  void refreshAuthSession()
})

const commentsBase = computed(() => {
  if (props.mode === 'public-post') {
    const slug = props.postSlug
    if (!slug) {
      return ''
    }
    return `/api/public/profile/${encodeURIComponent(props.publicSlug)}/posts/${encodeURIComponent(slug)}`
  }
  const token = props.shareToken
  if (!token) {
    return ''
  }
  return `/api/public/unlisted/${encodeURIComponent(props.publicSlug)}/${encodeURIComponent(token)}`
})

const { data, pending, error, refresh: refreshComments } = await useAsyncData(
  () => `comments-${props.mode}-${props.publicSlug}-${props.postSlug ?? ''}-${props.shareToken ?? ''}`,
  async () => {
    const base = commentsBase.value
    if (!base) {
      return null
    }
    const fetcher = import.meta.server ? useRequestFetch() : $fetch
    const res = await fetcher<ApiResponse<CommentsPayload>>(`${base}/comments`)
    return unwrapApiBody(res)
  },
  { watch: [commentsBase] },
)

const flatComments = computed(() => flattenTree(data.value?.comments ?? []))

function flattenTree(nodes: CommentNode[], depth = 0): Array<{ node: CommentNode; depth: number }> {
  const acc: Array<{ node: CommentNode; depth: number }> = []
  for (const n of nodes) {
    acc.push({ node: n, depth })
    if (n.children.length > 0) {
      acc.push(...flattenTree(n.children, depth + 1))
    }
  }
  return acc
}

const replyToId = ref<number | null>(null)
const draftBody = ref('')
const guestName = ref('')
const submitting = ref(false)

function authorLine(node: CommentNode): string {
  if (node.deleted) {
    return ''
  }
  if (node.kind === 'guest' && node.guestDisplayName) {
    return node.guestDisplayName
  }
  if (node.author) {
    return node.author.nickname || node.author.username || '用户'
  }
  return '访客'
}

async function deleteComment(node: CommentNode) {
  const postId = data.value?.postId
  if (postId == null) {
    return
  }
  try {
    await fetchData(`/api/me/posts/${postId}/comments/${node.id}`, { method: 'DELETE' })
    await refreshComments()
    toast.add({ title: '评论已删除', color: 'success' })
  }
  catch {
    /* fetchData 已 toast */
  }
}

async function submitComment() {
  const base = commentsBase.value
  if (!base) {
    return
  }

  const body = draftBody.value.trim()
  if (!body) {
    toast.add({ title: '请填写内容', color: 'error' })
    return
  }

  if (!loggedIn.value) {
    const name = guestName.value.trim()
    if (!name) {
      toast.add({ title: '请填写昵称', color: 'error' })
      return
    }
  }

  submitting.value = true
  try {
    const payload = {
      parentId: replyToId.value,
      body: draftBody.value,
      ...(loggedIn.value ? {} : { guestDisplayName: guestName.value.trim() }),
    }

    await fetchData<{ id: number }>(`${base}/comments`, {
      method: 'POST',
      body: payload,
    })

    draftBody.value = ''
    guestName.value = ''
    replyToId.value = null
    await refreshComments()
    toast.add({ title: '评论已发送', color: 'success' })
  }
  catch {
    /* fetchData 已 toast */
  }
  finally {
    submitting.value = false
  }
}
</script>

<template>
  <section class="space-y-4 border-t border-default pt-8">
    <h2 class="text-lg font-semibold">
      评论
    </h2>
    <p v-if="pending" class="text-muted">
      加载评论…
    </p>
    <p v-else-if="error" class="text-muted">
      评论加载失败
    </p>
    <div v-else class="space-y-3">
      <div
        v-for="{ node, depth } in flatComments"
        :key="node.id"
        :class="['space-y-2 py-1', depth > 0 && 'border-l border-default']"
        :style="depth > 0 ? { marginLeft: `${depth * 0.75}rem`, paddingLeft: '0.75rem' } : undefined"
      >
        <template v-if="node.deleted">
          <p class="text-sm text-muted">
            此评论已删除
          </p>
        </template>
        <template v-else>
          <div class="flex flex-wrap items-center gap-2 text-sm">
            <span class="font-medium">{{ authorLine(node) }}</span>
            <span class="text-xs tabular-nums text-muted">{{ new Date(node.createdAt).toLocaleString('zh-CN') }}</span>
            <UButton
              size="xs"
              variant="ghost"
              color="neutral"
              label="回复"
              @click="replyToId = node.id"
            />
            <UButton
              v-if="node.viewerCanDelete"
              size="xs"
              color="error"
              variant="soft"
              label="删除"
              @click="deleteComment(node)"
            />
          </div>
          <div class="prose dark:prose-invert whitespace-pre-wrap text-sm">
            {{ node.body }}
          </div>
        </template>
      </div>
      <p v-if="!flatComments.length" class="text-sm text-muted">
        暂无评论，来抢沙发吧。
      </p>
    </div>

    <div class="space-y-3 border-t border-default pt-6">
      <p v-if="replyToId != null" class="flex flex-wrap items-center gap-2 text-sm text-muted">
        <span>正在回复评论 #{{ replyToId }}</span>
        <UButton size="xs" variant="link" color="neutral" label="取消" @click="replyToId = null" />
      </p>
      <template v-if="loggedIn">
        <UTextarea v-model="draftBody" placeholder="写下你的评论…" :rows="4" class="w-full" />
        <UButton :loading="submitting" label="发表" @click="submitComment" />
      </template>
      <template v-else>
        <UInput v-model="guestName" placeholder="你的昵称" class="w-full max-w-md" />
        <UTextarea v-model="draftBody" placeholder="写下你的评论…" :rows="4" class="w-full" />
        <UButton :loading="submitting" label="发表" @click="submitComment" />
      </template>
    </div>
  </section>
</template>
