import { usePageLang } from '@vuepress/client'
import { useBlogPostData } from '@vuepress-plume/plugin-blog-data/client'
import { computed, ref } from 'vue'
import type { Ref } from 'vue'
import type { PlumeThemeBlogPostItem } from '../../shared/index.js'
import { useLocaleLink, useThemeLocaleData } from '../composables/index.js'
import { getRandomColor, toArray } from '../utils/index.js'

export function usePostListControl() {
  const locale = usePageLang()
  const themeData = useThemeLocaleData()

  const list = useBlogPostData() as unknown as Ref<PlumeThemeBlogPostItem[]>
  const blog = computed(() => themeData.value.blog || {})
  const pagination = computed(() => blog.value.pagination || {})

  const postList = computed(() => {
    const stickyList = list.value.filter(item =>
      typeof item.sticky === 'boolean' ? item.sticky : item.sticky >= 0,
    )
    const otherList = list.value.filter(
      item => item.sticky === undefined || item.sticky === false,
    )

    return [
      ...stickyList.sort((prev, next) => {
        if (next.sticky === true && prev.sticky === true)
          return 0
        return next.sticky > prev.sticky ? 1 : -1
      }),
      ...otherList,
    ].filter(item => item.lang === locale.value)
  })

  const page = ref(1)

  const totalPage = computed(() => {
    if (blog.value.pagination === false)
      return 0
    const perPage = blog.value.pagination?.perPage || 20
    return Math.ceil(postList.value.length / perPage)
  })
  const isLastPage = computed(() => page.value >= totalPage.value)
  const isFirstPage = computed(() => page.value <= 1)
  const isPaginationEnabled = computed(() => blog.value.pagination !== false && totalPage.value > 1)

  const finalList = computed(() => {
    if (blog.value.pagination === false)
      return postList.value

    const perPage = blog.value.pagination?.perPage || 20
    if (postList.value.length <= perPage)
      return postList.value

    return postList.value.slice(
      (page.value - 1) * perPage,
      page.value * perPage,
    )
  })

  const changePage = (offset: number) => {
    page.value += offset
    window.scrollTo({ top: 0, left: 0, behavior: 'instant' })
  }

  return {
    pagination,
    postList: finalList,
    page,
    totalPage,
    isLastPage,
    isFirstPage,
    isPaginationEnabled,
    changePage,
  }
}

const extractLocales: Record<string, { tags: string, archives: string }> = {
  'zh-CN': { tags: '标签', archives: '归档' },
  'en': { tags: 'Tags', archives: 'Archives' },
  'zh-TW': { tags: '標籤', archives: '歸檔' },
}

export function useBlogExtract() {
  const theme = useThemeLocaleData()
  const locale = usePageLang()

  const hasBlogExtract = computed(() => theme.value.blog?.archives !== false || theme.value.blog?.tags !== false)
  const tagsLink = useLocaleLink('blog/tags/')
  const archiveLink = useLocaleLink('blog/archives/')

  const tags = computed(() => ({
    link: tagsLink.value,
    text: extractLocales[locale.value]?.tags || extractLocales.en.tags,
  }))

  const archives = computed(() => ({
    link: archiveLink.value,
    text: extractLocales[locale.value]?.archives || extractLocales.en.archives,
  }))

  return {
    hasBlogExtract,
    tags,
    archives,
  }
}

export type ShortPostItem = Pick<PlumeThemeBlogPostItem, 'title' | 'path' | 'createTime'>

export function useTags() {
  const locale = usePageLang()
  const list = useBlogPostData() as unknown as Ref<PlumeThemeBlogPostItem[]>
  const filteredList = computed(() =>
    list.value.filter(item => item.lang === locale.value),
  )

  const tags = computed(() => {
    const tagMap: Record<string, number> = {}
    filteredList.value.forEach((item) => {
      if (item.tags) {
        toArray(item.tags).forEach((tag) => {
          if (tagMap[tag])
            tagMap[tag] += 1
          else
            tagMap[tag] = 1
        })
      }
    })
    return Object.keys(tagMap).map(tag => ({
      name: tag,
      count: tagMap[tag] > 99 ? '99+' : tagMap[tag],
      color: getRandomColor(),
    }))
  })

  const postList = ref<ShortPostItem[]>([])
  const currentTag = ref<string>()

  const handleTagClick = (tag: string) => {
    currentTag.value = tag
    postList.value = filteredList.value.filter((item) => {
      if (item.tags)
        return toArray(item.tags).includes(tag)

      return false
    }).map(item => ({
      title: item.title,
      path: item.path,
      createTime: item.createTime.split(' ')[0].replace(/\//g, '-'),
    }))
  }

  return {
    tags,
    currentTag,
    postList,
    handleTagClick,
  }
}

export function useArchives() {
  const locale = usePageLang()
  const list = useBlogPostData() as unknown as Ref<PlumeThemeBlogPostItem[]>
  const filteredList = computed(() =>
    list.value.filter(item => item.lang === locale.value),
  )
  const archives = computed(() => {
    const archives: { label: string, list: ShortPostItem[] }[] = []

    filteredList.value.forEach((item) => {
      const createTime = item.createTime.split(' ')[0]
      const year = createTime.split('/')[0]
      let current = archives.find(archive => archive.label === year)
      if (!current) {
        current = { label: year, list: [] }
        archives.push(current)
      }
      current.list.push({
        title: item.title,
        path: item.path,
        createTime: createTime.slice(year.length + 1).replace(/\//g, '-'),
      })
    })

    return archives
  })

  return {
    archives,
  }
}
