import {AppBskyRichtextFacet,type RichText,UnicodeString} from '@atproto/api'

import {toShortUrl} from './url-helpers'

export function restoreLinks(
  text: string,
  facets?: AppBskyRichtextFacet.Main[],
): string {
  if (!facets?.length) {
    return text
  }

  const rt = new UnicodeString(text)
  const parts: string[] = []
  let lastIndex = 0

  const sortedFacets = [...facets].sort(
    (a, b) => a.index.byteStart - b.index.byteStart,
  )

  for (const facet of sortedFacets) {
    const isLink = facet.features.find(AppBskyRichtextFacet.isLink)
    if (!isLink) {
      continue
    }

    parts.push(rt.slice(lastIndex, facet.index.byteStart))
    parts.push(isLink.uri)
    lastIndex = facet.index.byteEnd
  }

  parts.push(rt.slice(lastIndex))

  return parts.join('')
}

export function shortenLinks(rt: RichText): RichText {
  if (!rt.facets?.length) {
    return rt
  }
  rt = rt.clone()
  // enumerate the link facets
  if (rt.facets) {
    for (const facet of rt.facets) {
      const isLink = !!facet.features.find(AppBskyRichtextFacet.isLink)
      if (!isLink) {
        continue
      }

      // extract and shorten the URL
      const {byteStart, byteEnd} = facet.index
      const url = rt.unicodeText.slice(byteStart, byteEnd)
      const shortened = new UnicodeString(toShortUrl(url))

      // insert the shorten URL
      rt.insert(byteStart, shortened.utf16)
      // update the facet to cover the new shortened URL
      facet.index.byteStart = byteStart
      facet.index.byteEnd = byteStart + shortened.length
      // remove the old URL
      rt.delete(byteStart + shortened.length, byteEnd + shortened.length)
    }
  }
  return rt
}

// filter out any mention facets that didn't map to a user
export function stripInvalidMentions(rt: RichText): RichText {
  if (!rt.facets?.length) {
    return rt
  }
  rt = rt.clone()
  if (rt.facets) {
    rt.facets = rt.facets?.filter(facet => {
      const mention = facet.features.find(AppBskyRichtextFacet.isMention)
      if (mention && !mention.did) {
        return false
      }
      return true
    })
  }
  return rt
}

export function parseMarkdownLinks(text: string): {
  text: string
  facets: AppBskyRichtextFacet.Main[]
} {
  const regex = /\[([^\]]+)\]\(([^)]+)\)/g
  let match
  let newText = ''
  let lastIndex = 0
  const facets: AppBskyRichtextFacet.Main[] = []

  while ((match = regex.exec(text)) !== null) {
    const [fullMatch, linkText, linkUrl] = match
    const matchStart = match.index
    newText += text.slice(lastIndex, matchStart)
    const startByte = new UnicodeString(newText).length
    newText += linkText
    const endByte = new UnicodeString(newText).length
    let validUrl = linkUrl
    if (!validUrl.startsWith('http://') && !validUrl.startsWith('https://') && !validUrl.startsWith('mailto:')) {
      validUrl = `https://${validUrl}`
    }

    facets.push({
      index: {
        byteStart: startByte,
        byteEnd: endByte,
      },
      features: [
        {
          $type: 'app.bsky.richtext.facet#link',
          uri: validUrl,
        },
      ],
    })

    lastIndex = matchStart + fullMatch.length
  }

  newText += text.slice(lastIndex)

  return {text: newText, facets}
}
