/* eslint-disable @typescript-eslint/no-unnecessary-condition */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import Markdown from 'react-markdown'
import { Link as RouterLink } from 'react-router-dom'
import rehypeRaw from 'rehype-raw'
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize'
import remarkBreaks from 'remark-breaks'
import remarkGfm from 'remark-gfm'
import { visit } from 'unist-util-visit'

import { RichTextEditor } from '#components/Input/RichTextEditor/RichTextEditor'
import { useAddFilterTag } from '#components/Map/hooks/useFilter'
import { useTags } from '#components/Map/hooks/useTags'
import { decodeTag } from '#utils/FormatTags'
import { hashTagRegex } from '#utils/HashTagRegex'
import { fixUrls, mailRegex } from '#utils/ReplaceURLs'

import type { Item } from '#types/Item'
import type { Tag } from '#types/Tag'
import type { Root } from 'hast'

/**
 * @category Map
 */
export const TextView = ({
  item,
  itemId,
  text,
  truncate = false,
  rawText,
}: {
  item?: Item
  itemId?: string
  text?: string
  truncate?: boolean
  rawText?: string
}) => {
  if (item) {
    text = item.text
    itemId = item.id
  }
  const tags = useTags()
  const addFilterTag = useAddFilterTag()

  const origin = window.location.origin

  let innerText = ''
  let replacedText = ''

  if (rawText) {
    innerText = replacedText = rawText
  } else if (text) {
    innerText = text
  }

  if (innerText && truncate) innerText = truncateText(removeMarkdownKeepParagraphs(innerText), 100)

  if (innerText) replacedText = fixUrls(innerText)

  if (replacedText) {
    replacedText = replacedText.replace(mailRegex, (url) => {
      return `[${url}](mailto:${url})`
    })
  }

  if (replacedText) {
    replacedText = replacedText.replace(hashTagRegex, (match) => {
      return `[${match}](${match})`
    })
  }

  const HashTag = ({ children, tag, itemId }: { children: string; tag: Tag; itemId?: string }) => {
    return (
      <a
        className='hashtag'
        style={
          tag && {
            color: tag.color,
          }
        }
        key={tag ? tag.name + itemId : itemId}
        onClick={(e) => {
          e.stopPropagation()
          addFilterTag(tag)
        }}
      >
        {decodeTag(children)}
      </a>
    )
  }

  const Link = ({ href, children }: { href: string; children: string }) => {
    // Youtube
    if (href.startsWith('https://www.youtube.com/watch?v=')) {
      const videoId = href?.split('v=')[1].split('&')[0]
      const youtubeEmbedUrl = `https://www.youtube-nocookie.com/embed/${videoId}`

      return (
        <iframe src={youtubeEmbedUrl} allow='fullscreen;  picture-in-picture' allowFullScreen />
      )
    }

    // Rumble
    if (href.startsWith('https://rumble.com/embed/')) {
      return <iframe src={href} allow='fullscreen;  picture-in-picture' allowFullScreen />
    }

    // HashTag
    if (href.startsWith('#')) {
      const tag = tags.find((t) => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase())
      if (tag)
        return (
          <HashTag tag={tag} itemId={itemId}>
            {children}
          </HashTag>
        )
      else return children
    }

    // 4) Interne Links auf gleiche Base-URL
    if (href.startsWith(origin)) {
      const to = href.slice(origin.length) || '/'
      return <RouterLink to={to}>{children}</RouterLink>
    }

    if (href.startsWith('/')) {
      return <RouterLink to={href}>{children}</RouterLink>
    }

    return (
      <a href={href} target='_blank' rel='noreferrer'>
        {children}
      </a>
    )
  }

  return <RichTextEditor defaultValue={replacedText} readOnly={true} />
}

function removeMarkdownKeepParagraphs(text: string): string {
  return (
    text
      // 1) Bilder entfernen
      .replace(/!\[.*?\]\(.*?\)/g, '')
      // 2) Markdown-Links [Text](URL) → URL
      .replace(/\[.*?\]\(\s*(https?:\/\/[^\s)]+)\s*\)/g, '$1')
      // 3) Autolinks <http://…> → http://…
      .replace(/<\s*(https?:\/\/[^\s>]+)\s*>/g, '$1')
      // 4) Code-Fences und Inline-Code entfernen
      .replace(/```[\s\S]*?```/g, '')
      .replace(/`([^`]+)`/g, '$1')
      // 8) Tabellen-Pipes entfernen
      .replace(/^\|(.+)\|$/gm, '$1')
      .replace(/^\s*\|[-\s|]+\|$/gm, '')
      // 9) Blockquotes
      .replace(/^>\s+(.*)$/gm, '$1')
      // 10) Echte HTML-Tags (außer Absätze) entfernen
      .replace(/<(?!\s*\/?\s*p\s*>)[^>]+>/g, '')
      // 11) Zeilenumbrüche normalisieren
      .replace(/\r\n|\r/g, '\n')
      // 12) Mehrfache Leerzeilen auf max. 2 reduzieren
      .replace(/\n{3,}/g, '\n\n')
      // 13) Trim
      .trim()
  )
}

function truncateText(text, limit) {
  if (text.length <= limit) {
    return text
  }

  let truncated = ''
  let length = 0

  // Split the text by paragraphs
  const paragraphs = text.split('\n')

  for (const paragraph of paragraphs) {
    if (length + paragraph.length > limit) {
      truncated += paragraph.slice(0, limit - length) + '...'
      break
    } else {
      truncated += paragraph + '\n'
      length += paragraph.length
    }
  }

  return truncated.trim()
}

export const sanitizeSchema = {
  ...defaultSchema,

  tagNames: [...(defaultSchema.tagNames ?? []), 'div', 'iframe'],
  attributes: {
    ...defaultSchema.attributes,
    div: [...(defaultSchema.attributes?.div ?? []), 'data-youtube-video'],
    iframe: [
      ...(defaultSchema.attributes?.iframe ?? []),
      'src',
      'width',
      'height',
      'allowfullscreen',
      'autoplay',
      'disablekbcontrols',
      'enableiframeapi',
      'endtime',
      'ivloadpolicy',
      'modestbranding',
      'origin',
      'playlist',
      'rel',
      'start',
    ],
    img: [...(defaultSchema.attributes?.img ?? []), 'style'],
  },

  protocols: {
    ...defaultSchema.protocols,
    src: [...(defaultSchema.protocols?.src ?? []), 'https'],
  },
}

export function rehypeFilterYouTubeIframes() {
  return (tree: Root) => {
    visit(tree, 'element', (node) => {
      // node ist hier typischerweise ein HAST-Element
      const el = node

      if (el.tagName === 'iframe') {
        const src = String(el.properties?.src ?? '')

        // Nur echte YouTube-Embed-URLs zulassen
        if (
          // eslint-disable-next-line security/detect-unsafe-regex
          !/^https:\/\/(?:www\.)?(?:youtube\.com|youtube-nocookie\.com)\/embed\/[A-Za-z0-9_-]+(?:\?.*)?$/.test(
            src,
          )
        ) {
          // ersetze es durch einen leeren div
          el.tagName = 'div'
          el.properties = {}
          el.children = []
        }
      }
    })
  }
}
