<script setup lang="ts">
import { useAuthSession } from '../../../composables/useAuthSession'

usePageTitle('我的文章')

type Visibility = 'private' | 'unlisted' | 'public'
type Row = { id: number; title: string; slug: string; visibility: Visibility; tags?: string[] }
type ViewMode = 'list' | 'card'
type TagMode = 'or' | 'and'
type Payload = {
  items: Row[]
  total: number
  page: number
  pageSize: number
  availableTags?: string[]
}

const posts = ref<Row[]>([])
const loading = ref(true)
const viewMode = ref<ViewMode>('card')
const { user } = useAuthSession()
const { fetchData } = useClientApi()
const route = useRoute()
const router = useRouter()
const page = ref(1)
const total = ref(0)
const pageSize = ref(20)
const availableTagsApi = ref<string[]>([])
const selectedTags = ref<string[]>([])
const tagMode = ref<TagMode>('or')

function parsePage(raw: unknown): number {
  const n =
    typeof raw === 'string'
      ? Number.parseInt(raw, 10)
      : typeof raw === 'number'
        ? raw
        : Number.NaN
  if (!Number.isFinite(n) || n < 1) {
    return 1
  }
  return Math.floor(n)
}

async function load() {
  loading.value = true
  try {
    const query = new URLSearchParams()
    if (page.value > 1) {
      query.set('page', String(page.value))
    }
    if (selectedTags.value.length) {
      query.set('tags', selectedTags.value.join(','))
    }
    query.set('tagMode', tagMode.value)
    const url = query.toString() ? `/api/me/posts?${query.toString()}` : '/api/me/posts'
    const data = await fetchData<Payload>(url)
    posts.value = data.items
    total.value = data.total
    pageSize.value = data.pageSize
    availableTagsApi.value = data.availableTags ?? []
  } finally {
    loading.value = false
  }
}

const availableTags = computed(() => {
  const byApi = availableTagsApi.value ?? []
  const byItems = posts.value.flatMap(item => item.tags ?? []).filter(Boolean)
  return [...new Set([...byApi, ...byItems])]
})

function onPageChange(nextPage: number) {
  page.value = nextPage
  const query = { ...route.query }
  if (nextPage > 1) {
    query.page = String(nextPage)
  } else {
    delete query.page
  }
  void router.replace({ query })
}

watch(
  () => [route.query.page, route.query.tags, route.query.tagMode] as const,
  () => {
    const next = parsePage(route.query.page)
    page.value = next
    selectedTags.value =
      typeof route.query.tags === 'string'
        ? route.query.tags.split(',').map(x => x.trim()).filter(Boolean)
        : []
    tagMode.value = route.query.tagMode === 'and' ? 'and' : 'or'
    void load()
  },
)

onMounted(() => {
  page.value = parsePage(route.query.page)
  selectedTags.value =
    typeof route.query.tags === 'string'
      ? route.query.tags.split(',').map(x => x.trim()).filter(Boolean)
      : []
  tagMode.value = route.query.tagMode === 'and' ? 'and' : 'or'
  void load()
})

const tagModeItems = [
  { label: '任一命中 (OR)', value: 'or' },
  { label: '全部命中 (AND)', value: 'and' },
]

function updateRouteFilters(nextPage = 1) {
  const query = { ...route.query } as Record<string, string>
  if (selectedTags.value.length) {
    query.tags = selectedTags.value.join(',')
  } else {
    delete query.tags
  }
  query.tagMode = tagMode.value
  if (nextPage > 1) {
    query.page = String(nextPage)
  } else {
    delete query.page
  }
  void router.replace({ query })
}

function onTagsChange(next: string[]) {
  selectedTags.value = next
  updateRouteFilters(1)
}

function clearFilters() {
  selectedTags.value = []
  tagMode.value = 'or'
  updateRouteFilters(1)
}

function postDetailHref(post: Row) {
  if (post.visibility !== 'public') {
    return `/me/posts/preview/${post.id}`
  }
  const ps = user.value?.publicSlug
  if (!ps || !post.slug) {
    return ''
  }
  return `/@${ps}/posts/${encodeURIComponent(post.slug)}`
}

function visibilityLabel(visibility: string) {
  if (visibility === 'public') {
    return '公开'
  }
  if (visibility === 'unlisted') {
    return '仅链接'
  }
  return '私密'
}
</script>

<template>
  <UContainer class="py-8 space-y-4 max-w-6xl">
    <div class="flex flex-wrap justify-between items-center gap-3">
      <h1 class="text-2xl font-semibold">
        文章
      </h1>
      <div class="flex items-center gap-2">
        <div class="flex items-center rounded-lg border border-default p-0.5 bg-elevated/40">
          <UButton
            size="sm"
            :variant="viewMode === 'list' ? 'soft' : 'ghost'"
            color="neutral"
            icon="i-lucide-list"
            :class="viewMode === 'list' ? 'shadow-sm' : 'text-muted'"
            @click="viewMode = 'list'"
          >
            列表
          </UButton>
          <UButton
            size="sm"
            :variant="viewMode === 'card' ? 'soft' : 'ghost'"
            color="neutral"
            icon="i-lucide-layout-grid"
            :class="viewMode === 'card' ? 'shadow-sm' : 'text-muted'"
            @click="viewMode = 'card'"
          >
            卡片
          </UButton>
        </div>
        <UButton to="/me/posts/new">
          新建
        </UButton>
      </div>
    </div>
    <UCard :ui="{ body: 'p-4 space-y-3' }">
      <div class="flex items-center justify-between gap-2">
        <div class="text-sm text-muted">
          标签筛选
        </div>
        <UButton size="xs" color="neutral" variant="ghost" @click="clearFilters">
          清空
        </UButton>
      </div>
      <PostTagsInput
        :model-value="selectedTags"
        :suggestions="availableTags"
        placeholder="输入标签回车筛选"
        @update:model-value="onTagsChange"
      />
      <USelect
        v-model="tagMode"
        :items="tagModeItems"
        class="w-full sm:w-56"
        @update:model-value="() => updateRouteFilters(1)"
      />
    </UCard>

    <div v-if="loading" class="text-muted">
      加载中…
    </div>
    <UEmpty
      v-else-if="!posts.length"
      :title="selectedTags.length ? '没有匹配结果' : '暂无文章'"
      :description="selectedTags.length ? '试试调整标签筛选。' : '创建第一篇 Markdown 文章'"
    />
    <ul v-else-if="viewMode === 'list'" class="space-y-2">
      <li
        v-for="p in posts"
        :key="p.id"
        class="flex flex-wrap justify-between items-center gap-3 border border-default rounded-lg p-3"
      >
        <div class="min-w-0 flex-1">
          <div class="font-medium truncate">
            {{ p.title }}
          </div>
          <div class="text-xs text-muted">
            /{{ p.slug }} · {{ visibilityLabel(p.visibility) }}
          </div>
          <PostTagsPostTagBadges v-if="p.tags?.length" :tags="p.tags" class="mt-1.5" />
        </div>
        <div class="flex flex-wrap gap-1 justify-end">
          <UButton
            v-if="postDetailHref(p)"
            :to="postDetailHref(p)"
            size="xs"
            variant="soft"
            color="neutral"
          >
            详情
          </UButton>
          <UButton :to="`/me/posts/${p.id}`" size="xs" variant="ghost">
            编辑
          </UButton>
        </div>
      </li>
    </ul>
    <div v-else class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
      <UCard
        v-for="p in posts"
        :key="p.id"
        :ui="{ body: 'p-4 space-y-3', footer: 'px-4 py-3 border-t border-default' }"
      >
        <div class="space-y-2">
          <div class="font-medium line-clamp-2 min-h-12">
            {{ p.title }}
          </div>
          <div class="text-xs text-muted break-all">
            /{{ p.slug }}
          </div>
          <div class="flex flex-wrap items-center gap-2">
            <UBadge size="sm" color="neutral" variant="soft">
              {{ visibilityLabel(p.visibility) }}
            </UBadge>
          </div>
          <PostTagsPostTagBadges v-if="p.tags?.length" :tags="p.tags" :max="4" class="pt-1" />
        </div>
        <template #footer>
          <div class="flex flex-wrap gap-2 justify-end">
            <UButton
              v-if="postDetailHref(p)"
              :to="postDetailHref(p)"
              size="xs"
              variant="soft"
              color="neutral"
            >
              详情
            </UButton>
            <UButton :to="`/me/posts/${p.id}`" size="xs" variant="ghost">
              编辑
            </UButton>
          </div>
        </template>
      </UCard>
    </div>
    <div v-if="!loading && total > pageSize" class="flex justify-end">
      <UPagination
        :page="page"
        :total="total"
        :items-per-page="pageSize"
        size="sm"
        @update:page="onPageChange"
      />
    </div>
  </UContainer>
</template>
