import { getCollection, render, type CollectionEntry } from 'astro:content'
import { readingTime, calculateWordCountFromHtml } from '@/lib/utils'
import type { Block, RichText } from './interfaces'
import { NotionApiError, fetchNotionApiJson } from './notion/api'
import {
  buildHeadingId,
  buildText,
  richTextToPlainText,
  toNotionImageUrl,
} from './blog-helpers'

const DEFAULT_AUTHOR_ID = 'libr'
type ContentCollection = 'blog' | 'authors' | 'projects'

async function getCollectionSafe<T extends ContentCollection>(
  name: T,
): Promise<CollectionEntry<T>[]> {
  try {
    return await getCollection(name)
  } catch {
    return []
  }
}

type NotionPost = {
  id: string
  slug?: string
  Content?: string
  excerpt?: string
  Tags?: string[]
  Published?: boolean
  'Published Date'?: string
  created_time?: string
  last_edited_time?: string
}

export type NotionBlockValue = {
  id: string
  type: string
  properties?: Record<string, any>
  content?: string[]
  format?: Record<string, any>
  synced_from?: Record<string, any>
  link_to_page_id?: string
  parent_table?: string
}

export type NotionBlock = {
  value: NotionBlockValue
}

export type NotionBlockMap = Record<string, NotionBlock>

export type RemotePostPayload = {
  post: CollectionEntry<'blog'>
  blockMap: NotionBlockMap
  rootId: string
}

type PostsPayload = {
  posts?: NotionPost[]
  length?: number
}

export interface LinkEntry {
  id: string
  picLink?: string
  published?: boolean
  Description?: string
  links: string
  name: string
  created_time?: string
  last_edited_time?: string
}

export async function getAllAuthors(): Promise<CollectionEntry<'authors'>[]> {
  return getCollectionSafe('authors')
}

export function normalizePost(post: NotionPost): CollectionEntry<'blog'> {
  const dateString =
    post['Published Date'] ?? post.created_time ?? new Date().toISOString()
  const date = new Date(dateString)
  const id = post.slug || post.id
  const banner = (post as any).banner || null
  const image = banner
  return {
    id,
    collection: 'blog',
    data: {
      title: post.Content || id || 'Untitled',
      description: (post as any).excerpt || '',
      date,
      tags: Array.isArray(post.Tags) ? post.Tags : [],
      draft: !(post.Published ?? true),
      authors: [DEFAULT_AUTHOR_ID],
      banner,
      image,
    },
    body: '',
  }
}

export async function fetchPostsPage(
  page = 1,
  size = 1000,
): Promise<{
  posts: CollectionEntry<'blog'>[]
  totalPages: number
}> {
  const payload = await fetchNotionApiJson<PostsPayload>(
    `/v2/posts?page=${page}&length=${size}`,
  )
  const posts = (payload.posts ?? []).filter((post) => post.Published ?? true)
  const normalized = posts
    .map(normalizePost)
    .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf())
    .filter((post) => !isSubpost(post.id)) as CollectionEntry<'blog'>[]

  return {
    posts: normalized,
    totalPages: payload.length ?? 0,
  }
}

export async function getAllPosts(
  page?: number,
  size?: number,
): Promise<CollectionEntry<'blog'>[]> {
  try {
    const { posts } = await fetchPostsPage(page ?? 1, size ?? 1000)
    return posts
  } catch (error) {
    console.error('getAllPosts remote fetch failed, using fallback:', error)
    return []
  }
}

export async function getAllPostsAndSubposts(): Promise<
  CollectionEntry<'blog'>[]
> {
  return getAllPosts()
}

export async function getAllTags(): Promise<Map<string, number>> {
  const posts = await getAllPosts()
  return posts.reduce((acc, post) => {
    post.data.tags?.forEach((tag) => {
      acc.set(tag, (acc.get(tag) || 0) + 1)
    })
    return acc
  }, new Map<string, number>())
}

export async function getAdjacentPosts(currentId: string): Promise<{
  newer: CollectionEntry<'blog'> | null
  older: CollectionEntry<'blog'> | null
  parent: CollectionEntry<'blog'> | null
}> {
  const allPosts = await getAllPosts()

  const parentPosts = allPosts.filter((post) => !isSubpost(post.id))
  const currentIndex = parentPosts.findIndex((post) => post.id === currentId)

  if (currentIndex === -1) {
    return { newer: null, older: null, parent: null }
  }

  return {
    newer: currentIndex > 0 ? parentPosts[currentIndex - 1] : null,
    older:
      currentIndex < parentPosts.length - 1
        ? parentPosts[currentIndex + 1]
        : null,
    parent: null,
  }
}

export async function getPostsByAuthor(
  authorId: string,
): Promise<CollectionEntry<'blog'>[]> {
  const posts = await getAllPosts()
  return posts.filter((post) => post.data.authors?.includes(authorId))
}

export async function getPostsByTag(
  tag: string,
): Promise<CollectionEntry<'blog'>[]> {
  const posts = await getAllPosts()
  return posts.filter((post) => post.data.tags?.includes(tag))
}

export async function getRecentPosts(
  count: number,
): Promise<CollectionEntry<'blog'>[]> {
  const posts = await getAllPosts()
  return posts.slice(0, count)
}

export async function getSortedTags(): Promise<
  { tag: string; count: number }[]
> {
  const tagCounts = await getAllTags()
  return [...tagCounts.entries()]
    .map(([tag, count]) => ({ tag, count }))
    .sort((a, b) => {
      const countDiff = b.count - a.count
      return countDiff !== 0 ? countDiff : a.tag.localeCompare(b.tag)
    })
}

export function getParentId(subpostId: string): string {
  return subpostId.split('/')[0]
}

export async function getSubpostsForParent(
  parentId: string,
): Promise<CollectionEntry<'blog'>[]> {
  const posts = await getCollectionSafe('blog')
  return posts
    .filter(
      (post) =>
        !post.data.draft &&
        isSubpost(post.id) &&
        getParentId(post.id) === parentId,
    )
    .sort((a, b) => {
      const dateDiff = a.data.date.valueOf() - b.data.date.valueOf()
      if (dateDiff !== 0) return dateDiff

      const orderA = a.data.order ?? 0
      const orderB = b.data.order ?? 0
      return orderA - orderB
    })
}

export function groupPostsByYear(
  posts: CollectionEntry<'blog'>[],
): Record<string, CollectionEntry<'blog'>[]> {
  return posts.reduce(
    (acc: Record<string, CollectionEntry<'blog'>[]>, post) => {
      const year = post.data.date.getFullYear().toString()
      ;(acc[year] ??= []).push(post)
      return acc
    },
    {},
  )
}

export async function hasSubposts(postId: string): Promise<boolean> {
  return false
}

export function isSubpost(postId: string): boolean {
  return false
}

export async function fetchRemotePost(
  slug: string,
): Promise<{ post: NotionPost } | null> {
  try {
    const data = await fetchNotionApiJson<Partial<{ post: NotionPost }>>(
      `/v2/posts/${encodeURI(slug)}?info=true`,
    )
    if (!data.post) return null
    return data
  } catch (error) {
    if (error instanceof NotionApiError && error.status === 404) {
      return null
    }
    console.error(`fetchRemotePost error for slug "${slug}":`, error)
    throw error
  }
}

export async function fetchRemotePostContent(
  slug: string,
): Promise<RemotePostPayload | null> {
  try {
    const data = await fetchNotionApiJson<
      Partial<{
        post: NotionPost
        blockMap: NotionBlockMap
      }>
    >(`/v2/posts/${encodeURI(slug)}`)
    if (!data.post || !data.blockMap) return null

    const rootId = data.post.id
    const post = normalizePost(data.post)

    return {
      post,
      blockMap: data.blockMap,
      rootId,
    }
  } catch (error) {
    if (error instanceof NotionApiError && error.status === 404) {
      return null
    }
    console.error(`fetchRemotePostContent error for slug "${slug}":`, error)
    throw error
  }
}

export async function getFriendLinks(): Promise<LinkEntry[]> {
  try {
    const data = await fetchNotionApiJson<LinkEntry[]>('/v2/links')
    if (!Array.isArray(data)) throw new Error('Invalid links data format')

    return data
  } catch (error) {
    console.error('getFriendLinks error:', error)
    return []
  }
}

export async function getParentPost(
  subpostId: string,
): Promise<CollectionEntry<'blog'> | null> {
  const parentId = getParentId(subpostId)
  const allPosts = await getAllPosts()
  return allPosts.find((post) => post.id === parentId) || null
}

export async function parseAuthors(authorIds: string[] = []) {
  if (!authorIds.length) return []

  const allAuthors = await getAllAuthors()
  const authorMap = new Map(allAuthors.map((author) => [author.id, author]))

  return authorIds.map((id) => {
    const author = authorMap.get(id)
    return {
      id,
      name: author?.data?.name || id,
      avatar: author?.data?.avatar || '/static/logo.png',
      isRegistered: !!author,
    }
  })
}

export async function getPostById(
  postId: string,
): Promise<CollectionEntry<'blog'> | null> {
  const allPosts = await getAllPostsAndSubposts()
  return allPosts.find((post) => post.id === postId) || null
}

export async function getSubpostCount(parentId: string): Promise<number> {
  const subposts = await getSubpostsForParent(parentId)
  return subposts.length
}

export async function getCombinedReadingTime(postId: string): Promise<string> {
  const post = await getPostById(postId)
  if (!post) return readingTime(0)

  let totalWords = calculateWordCountFromHtml(post.body)

  if (!isSubpost(postId)) {
    const subposts = await getSubpostsForParent(postId)
    for (const subpost of subposts) {
      totalWords += calculateWordCountFromHtml(subpost.body)
    }
  }

  return readingTime(totalWords)
}

export async function getPostReadingTime(postId: string): Promise<string> {
  const post = await getPostById(postId)
  if (!post) return readingTime(0)

  const wordCount = calculateWordCountFromHtml(post.body)
  return readingTime(wordCount)
}

export type TOCHeading = {
  slug: string
  text: string
  depth: number
  isSubpostTitle?: boolean
}

export type RenderedRemoteContent = {
  blocks: Block[]
  headingBlocks: Block[]
  headings: TOCHeading[]
  wordCount: number
}

function parseRichTexts(raw: any): RichText[] {
  if (!Array.isArray(raw)) return []

  return raw.map((segment: any) => {
    const [text, decorations] = segment

    const annotation: RichText['Annotation'] = {
      Bold: false,
      Italic: false,
      Strikethrough: false,
      Underline: false,
      Code: false,
      Color: 'default',
    }

    let href: string | undefined
    let mentionPageId: string | undefined
    let equationExpression: string | undefined

    if (Array.isArray(decorations)) {
      for (const deco of decorations) {
        const [type, value] = deco
        switch (type) {
          case 'b':
            annotation.Bold = true
            break
          case 'i':
            annotation.Italic = true
            break
          case 's':
            annotation.Strikethrough = true
            break
          case '_':
            annotation.Underline = true
            break
          case 'c':
            annotation.Code = true
            break
          case 'a':
            href =
              typeof value === 'string'
                ? value
                : typeof value?.[0] === 'string'
                  ? value[0]
                  : undefined
            break
          case 'p':
            mentionPageId =
              typeof value === 'object' && value?.id ? value.id : undefined
            break
          case 'e': {
            if (typeof value === 'string') {
              equationExpression = value
            } else if (Array.isArray(value) && typeof value[0] === 'string') {
              equationExpression = value[0]
            } else if (typeof text === 'string') {
              equationExpression = text
            }
            break
          }
          case 'h':
            if (typeof value === 'string') {
              annotation.Color = value
            }
            break
          default:
            break
        }
      }
    }

    if (equationExpression) {
      const richText: RichText = {
        Equation: { Expression: equationExpression },
        Annotation: { ...annotation },
        PlainText: equationExpression,
      }

      if (href) {
        richText.Href = href
      }

      if (mentionPageId) {
        richText.Mention = {
          Type: 'page',
          Page: { Id: mentionPageId },
        }
      }

      return richText
    }

    const richText = buildText(typeof text === 'string' ? text : '', href, {
      Color: annotation.Color,
      Bold: annotation.Bold,
      Italic: annotation.Italic,
      Strikethrough: annotation.Strikethrough,
      Underline: annotation.Underline,
      Code: annotation.Code,
    })

    if (mentionPageId) {
      richText.Mention = {
        Type: 'page',
        Page: { Id: mentionPageId },
      }
    }

    return richText
  })
}

function countWordsFromRichTexts(richTexts: RichText[] = []): number {
  const text = richTextToPlainText(richTexts)
  if (!text) return 0
  return text.split(/\s+/).filter(Boolean).length
}

function countWords(blocks: Block[]): number {
  let total = 0

  const addChildren = (children?: Block[]) => {
    if (children && children.length > 0) {
      total += countWords(children)
    }
  }

  for (const block of blocks) {
    switch (block.Type) {
      case 'paragraph':
        total += countWordsFromRichTexts(block.Paragraph?.RichTexts)
        addChildren(block.Paragraph?.Children)
        break
      case 'heading_1':
        total += countWordsFromRichTexts(block.Heading1?.RichTexts)
        addChildren(block.Heading1?.Children)
        break
      case 'heading_2':
        total += countWordsFromRichTexts(block.Heading2?.RichTexts)
        addChildren(block.Heading2?.Children)
        break
      case 'heading_3':
        total += countWordsFromRichTexts(block.Heading3?.RichTexts)
        addChildren(block.Heading3?.Children)
        break
      case 'bulleted_list':
      case 'numbered_list':
        block.ListItems?.forEach((item) => {
          if (item.Type === 'bulleted_list_item') {
            total += countWordsFromRichTexts(item.BulletedListItem?.RichTexts)
            addChildren(item.BulletedListItem?.Children)
          } else if (item.Type === 'numbered_list_item') {
            total += countWordsFromRichTexts(item.NumberedListItem?.RichTexts)
            addChildren(item.NumberedListItem?.Children)
          }
        })
        break
      case 'to_do':
        total += countWordsFromRichTexts(block.ToDo?.RichTexts)
        addChildren(block.ToDo?.Children)
        break
      case 'quote':
        total += countWordsFromRichTexts(block.Quote?.RichTexts)
        addChildren(block.Quote?.Children)
        break
      case 'callout':
        total += countWordsFromRichTexts(block.Callout?.RichTexts)
        addChildren(block.Callout?.Children)
        break
      case 'code':
        total += countWordsFromRichTexts(block.Code?.RichTexts)
        break
      case 'image':
        total += countWordsFromRichTexts(block.Image?.Caption)
        break
      case 'bookmark':
        total += countWordsFromRichTexts(block.Bookmark?.Caption)
        break
      case 'link_preview':
        break
      case 'embed':
        break
      case 'video':
        total += countWordsFromRichTexts(block.Video?.Caption)
        break
      case 'column_list':
        block.ColumnList?.Columns?.forEach((column) => {
          addChildren(column.Children)
        })
        break
      case 'synced_block':
        addChildren(block.SyncedBlock?.Children)
        break
      case 'toggle':
        total += countWordsFromRichTexts(block.Toggle?.RichTexts)
        addChildren(block.Toggle?.Children)
        break
      default:
        break
    }
  }

  return total
}

function buildBlocks(
  contentIds: string[],
  blockMap: NotionBlockMap,
  headingBlocks: Block[],
): Block[] {
  const blocks: Block[] = []
  let i = 0

  while (i < contentIds.length) {
    const currentId = contentIds[i]
    const current = blockMap[currentId]?.value
    if (!current) {
      i++
      continue
    }
    if (current.type === 'bulleted_list' || current.type === 'numbered_list') {
      const listItems: Block[] = []
      const targetType = current.type

      while (
        i < contentIds.length &&
        blockMap[contentIds[i]]?.value?.type === targetType
      ) {
        const item = blockMap[contentIds[i]]?.value
        const childIds = Array.isArray(item?.content) ? item.content : []
        const children = buildBlocks(childIds, blockMap, headingBlocks)

        if (targetType === 'bulleted_list') {
          listItems.push({
            Id: item?.id ?? contentIds[i],
            Type: 'bulleted_list_item',
            HasChildren: children.length > 0,
            BulletedListItem: {
              RichTexts: parseRichTexts(item?.properties?.title),
              Color:
                typeof item?.format?.block_color === 'string'
                  ? item?.format?.block_color
                  : 'default',
              Children: children.length > 0 ? children : undefined,
            },
          })
        } else {
          listItems.push({
            Id: item?.id ?? contentIds[i],
            Type: 'numbered_list_item',
            HasChildren: children.length > 0,
            NumberedListItem: {
              RichTexts: parseRichTexts(item?.properties?.title),
              Color:
                typeof item?.format?.block_color === 'string'
                  ? item?.format?.block_color
                  : 'default',
              Children: children.length > 0 ? children : undefined,
            },
          })
        }

        i++
      }

      blocks.push({
        Id: `${targetType}-${listItems[0]?.Id ?? i}`,
        Type:
          targetType === 'bulleted_list' ? 'bulleted_list' : 'numbered_list',
        HasChildren: listItems.some((item) => item.HasChildren),
        ListItems: listItems,
      })
      continue
    }

    const block = convertBlock(currentId, blockMap, headingBlocks)
    if (block) {
      blocks.push(block)
    }
    i++
  }

  return blocks
}

function convertBlock(
  blockId: string,
  blockMap: NotionBlockMap,
  headingBlocks: Block[],
): Block | null {
  const block = blockMap[blockId]?.value
  if (!block) return null

  const childIds = Array.isArray(block.content) ? block.content : []
  const children =
    childIds.length > 0 ? buildBlocks(childIds, blockMap, headingBlocks) : []
  const color =
    typeof block.format?.block_color === 'string'
      ? block.format?.block_color
      : 'default'

  switch (block.type) {
    case 'text': {
      return {
        Id: block.id,
        Type: 'paragraph',
        HasChildren: children.length > 0,
        Paragraph: {
          RichTexts: parseRichTexts(block.properties?.title),
          Color: color,
          Children: children.length > 0 ? children : undefined,
        },
      }
    }
    case 'header':
    case 'sub_header':
    case 'sub_sub_header': {
      const heading = {
        RichTexts: parseRichTexts(block.properties?.title),
        Color: color,
        IsToggleable: false,
        Children: children.length > 0 ? children : undefined,
      }

      const headingBlock: Block =
        block.type === 'header'
          ? {
              Id: block.id,
              Type: 'heading_1',
              HasChildren: children.length > 0,
              Heading1: heading,
            }
          : block.type === 'sub_header'
            ? {
                Id: block.id,
                Type: 'heading_2',
                HasChildren: children.length > 0,
                Heading2: heading,
              }
            : {
                Id: block.id,
                Type: 'heading_3',
                HasChildren: children.length > 0,
                Heading3: heading,
              }

      headingBlocks.push(headingBlock)
      return headingBlock
    }
    case 'code': {
      return {
        Id: block.id,
        Type: 'code',
        HasChildren: false,
        Code: {
          Caption: parseRichTexts(block.properties?.caption),
          RichTexts: parseRichTexts(block.properties?.title),
          Language:
            block.properties?.language?.[0]?.[0]?.toString()?.toLowerCase() ||
            'plain text',
        },
      }
    }
    case 'image': {
      const src =
        block.properties?.source?.[0]?.[0] || block.format?.display_source
      if (!src) return null
      const processed = toNotionImageUrl(src, block)
      return {
        Id: block.id,
        Type: 'image',
        HasChildren: false,
        Image: {
          Caption: parseRichTexts(block.properties?.caption),
          Type: 'external',
          External: { Url: processed },
          Width: block.format?.block_width,
          Height: block.format?.block_height,
        },
      }
    }
    case 'divider': {
      return { Id: block.id, Type: 'divider', HasChildren: false }
    }
    case 'quote': {
      return {
        Id: block.id,
        Type: 'quote',
        HasChildren: children.length > 0,
        Quote: {
          RichTexts: parseRichTexts(block.properties?.title),
          Color: color,
          Children: children.length > 0 ? children : undefined,
        },
      }
    }
    case 'callout': {
      return {
        Id: block.id,
        Type: 'callout',
        HasChildren: children.length > 0,
        Callout: {
          RichTexts: parseRichTexts(block.properties?.title),
          Icon: block.format?.page_icon
            ? { Type: 'emoji', Emoji: block.format?.page_icon }
            : null,
          Color: color,
          Children: children.length > 0 ? children : undefined,
        },
      }
    }
    case 'equation': {
      const expression =
        block.properties?.title?.[0]?.[0]?.toString() ||
        block.properties?.equation?.[0]?.[0]?.toString() ||
        ''

      if (!expression) return null

      return {
        Id: block.id,
        Type: 'equation',
        HasChildren: false,
        Equation: { Expression: expression },
      }
    }
    case 'tweet': {
      const url = block.properties?.source?.[0]?.[0] || ''
      if (!url) return null
      return {
        Id: block.id,
        Type: 'embed',
        HasChildren: false,
        Embed: { Url: url },
      }
    }
    case 'bookmark': {
      const url =
        block.properties?.link?.[0]?.[0] ||
        block.properties?.source?.[0]?.[0] ||
        block.properties?.title?.[0]?.[0] ||
        ''
      if (!url) return null
      return {
        Id: block.id,
        Type: 'bookmark',
        HasChildren: false,
        Bookmark: {
          Caption: parseRichTexts(block.properties?.title),
          Url: url,
        },
      }
    }
    case 'link_preview': {
      const url =
        block.properties?.link_url?.[0]?.[0] ||
        block.properties?.source?.[0]?.[0]
      if (!url) return null
      return {
        Id: block.id,
        Type: 'link_preview',
        HasChildren: false,
        LinkPreview: { Url: url },
      }
    }
    case 'embed': {
      const url =
        block.properties?.source?.[0]?.[0] || block.format?.display_source
      if (!url) return null
      return {
        Id: block.id,
        Type: 'embed',
        HasChildren: false,
        Embed: { Url: url },
      }
    }
    case 'video': {
      const url =
        block.properties?.source?.[0]?.[0] || block.format?.display_source
      if (!url) return null
      return {
        Id: block.id,
        Type: 'video',
        HasChildren: false,
        Video: {
          Caption: parseRichTexts(block.properties?.caption),
          Type: 'external',
          External: { Url: url },
        },
      }
    }
    case 'to_do': {
      const checked =
        block.properties?.checked?.[0]?.[0]?.toString().toLowerCase() === 'yes'
      return {
        Id: block.id,
        Type: 'to_do',
        HasChildren: children.length > 0,
        ToDo: {
          RichTexts: parseRichTexts(block.properties?.title),
          Checked: checked,
          Color: color,
          Children: children.length > 0 ? children : undefined,
        },
      }
    }
    case 'toggle': {
      return {
        Id: block.id,
        Type: 'toggle',
        HasChildren: children.length > 0,
        Toggle: {
          RichTexts: parseRichTexts(block.properties?.title),
          Color: color,
          Children: children.length > 0 ? children : undefined,
        },
      }
    }
    case 'column_list': {
      const columns =
        childIds.map((id) => {
          const col = blockMap[id]?.value
          const colChildren = Array.isArray(col?.content)
            ? buildBlocks(col?.content, blockMap, headingBlocks)
            : []
          return {
            Id: id,
            Type: 'column',
            HasChildren: colChildren.length > 0,
            Children: colChildren,
          }
        }) || []

      return {
        Id: block.id,
        Type: 'column_list',
        HasChildren: columns.some((c) => c.HasChildren),
        ColumnList: { Columns: columns },
      }
    }
    case 'synced_block': {
      const syncedFrom =
        block.synced_from && typeof block.synced_from.block_id === 'string'
          ? { BlockId: block.synced_from.block_id }
          : null

      return {
        Id: block.id,
        Type: 'synced_block',
        HasChildren: children.length > 0,
        SyncedBlock: {
          SyncedFrom: syncedFrom,
          Children: children.length > 0 ? children : undefined,
        },
      }
    }
    case 'table_of_contents': {
      return {
        Id: block.id,
        Type: 'table_of_contents',
        HasChildren: false,
        TableOfContents: { Color: color },
      }
    }
    case 'link_to_page': {
      const pageId =
        block.link_to_page_id || block.properties?.link_to_page_id?.[0]?.[0]
      return {
        Id: block.id,
        Type: 'link_to_page',
        HasChildren: false,
        LinkToPage: {
          Type: 'page',
          PageId: pageId,
        },
      }
    }
    default:
      return null
  }
}

export function renderRemoteBlockMap(
  blockMap: NotionBlockMap,
  rootId: string,
): RenderedRemoteContent {
  const headingBlocks: Block[] = []
  const root = blockMap[rootId]?.value
  const fallbackRoot =
    root ||
    Object.values(blockMap)
      .map((b) => b.value)
      .find(
        (value) =>
          Array.isArray(value?.content) &&
          (value.type === 'page' || value.type === 'collection_view_page'),
      )
  const contentOrder = Array.isArray(fallbackRoot?.content)
    ? fallbackRoot.content
    : []

  const blocks = buildBlocks(contentOrder, blockMap, headingBlocks)
  const headings: TOCHeading[] = headingBlocks.map((block) => {
    const heading = block.Heading1 || block.Heading2 || block.Heading3
    return {
      slug: buildHeadingId(heading),
      text: richTextToPlainText(heading?.RichTexts ?? []),
      depth:
        block.Type === 'heading_1' ? 2 : block.Type === 'heading_2' ? 3 : 4,
    }
  })

  const wordCount = countWords(blocks)

  return { blocks, headingBlocks, headings, wordCount }
}

export type TOCSection = {
  type: 'parent' | 'subpost'
  title: string
  headings: TOCHeading[]
  subpostId?: string
}

export async function getTOCSections(postId: string): Promise<TOCSection[]> {
  const post = await getPostById(postId)
  if (!post) return []

  const parentPost = post

  if (!parentPost) return []

  const sections: TOCSection[] = []

  const { headings } = await render(parentPost)
  if (headings.length > 0) {
    sections.push({
      type: 'parent',
      title: 'Overview',
      headings: headings.map((heading) => ({
        slug: heading.slug,
        text: heading.text,
        depth: heading.depth,
      })),
    })
  }

  return sections
}
