import { ElementType } from "domelementtype"
import parse, { type DOMNode, Element, type Text } from "html-react-parser"

import { Typography } from "@scandic-hotels/design-system/Typography"

import Link from "@/components/TempDesignSystem/Link"
import Table from "@/components/TempDesignSystem/Table"

import { NodeNames } from "./utils"

import styles from "./htmlContent.module.css"

type Node = Element | Text

interface HtmlContentProps {
  html: string
}

export default function HtmlContent({ html }: HtmlContentProps) {
  const cleanedHtml = html.replace("<p></p>\n", "")
  let parentIdx = 0
  const parsedContent = parse(cleanedHtml, {
    replace: (domNode: DOMNode) => {
      if (domNode instanceof Element) {
        return renderNode(domNode, parentIdx)
      } else {
        if (domNode.data === "\n") {
          return <br />
        }
      }
      parentIdx++
    },
  })
  return <div>{parsedContent}</div>
}

function renderChildren(node: Element) {
  return node.children?.map((child, idx) => renderNode(child as Node, idx))
}

function renderNode(domNode: Node, idx: number) {
  if (domNode.type === ElementType.Tag) {
    switch (domNode.name) {
      case NodeNames.h1:
        return (
          <Typography
            key={domNode.name + idx}
            variant="Title/md"
            className={styles.heading}
          >
            <domNode.name>{renderChildren(domNode)}</domNode.name>
          </Typography>
        )
      case NodeNames.h2: // TODO: change to lowercase
        return (
          <Typography
            key={domNode.name + idx}
            variant="Title/sm"
            className={styles.heading}
          >
            <domNode.name>{renderChildren(domNode)}</domNode.name>
          </Typography>
        )
      case NodeNames.h3:
        return (
          <Typography
            key={domNode.name + idx}
            variant="Title/xs"
            className={styles.heading}
          >
            <domNode.name>{renderChildren(domNode)}</domNode.name>
          </Typography>
        )
      case NodeNames.h4:
        return (
          <Typography
            key={domNode.name + idx}
            variant="Title/Subtitle/lg"
            className={styles.heading}
          >
            <domNode.name>{renderChildren(domNode)}</domNode.name>
          </Typography>
        )
      case NodeNames.h5:
        return (
          <Typography
            key={domNode.name + idx}
            variant="Title/Subtitle/md"
            className={styles.heading}
          >
            <domNode.name>{renderChildren(domNode)}</domNode.name>
          </Typography>
        )
      case NodeNames.br:
        return <br key={domNode.name + idx} />

      case NodeNames.a:
        if (!domNode.attribs.href) {
          return <span>{renderChildren(domNode)}</span>
        }
        return (
          <Link
            key={domNode.name + idx}
            color="Text/Interactive/Secondary"
            textDecoration="underline"
            weight="bold"
            target="_blank" //Always open in new tab
            href={domNode.attribs.href}
          >
            {renderChildren(domNode)}
          </Link>
        )

      case NodeNames.ul:
        let numberOfRows: number | undefined
        if (domNode.children.length > 4) {
          const half = domNode.children.length / 2
          numberOfRows = Math.ceil(half)
        }
        return (
          <ul
            key={domNode.name + idx}
            className={styles.ul}
            style={
              numberOfRows
                ? {
                    gridTemplateRows: `repeat(${numberOfRows}, auto)`,
                  }
                : {}
            }
          >
            {renderChildren(domNode)}
          </ul>
        )

      case NodeNames.ol:
        let numberOfOlRows: number | undefined
        if (domNode.children.length > 4) {
          const half = domNode.children.length / 2
          numberOfOlRows = Math.ceil(half)
        }
        return (
          <ol
            key={domNode.name + idx}
            className={styles.ol}
            style={
              numberOfOlRows
                ? {
                    gridTemplateRows: `repeat(${numberOfOlRows}, auto)`,
                  }
                : {}
            }
          >
            {renderChildren(domNode)}
          </ol>
        )

      case NodeNames.li:
        return <li key={domNode.name + idx}>{renderChildren(domNode)}</li>

      case NodeNames.td:
        return (
          <Table.TD key={domNode.name + idx}>
            {renderChildren(domNode)}
          </Table.TD>
        )

      case NodeNames.th:
        return (
          <Typography className={styles.heading}>
            <Table.TH key={domNode.name + idx}>
              {renderChildren(domNode)}
            </Table.TH>
          </Typography>
        )

      case NodeNames.tr:
        return (
          <Table.TR key={domNode.name + idx}>
            {renderChildren(domNode)}
          </Table.TR>
        )

      case NodeNames.tbody:
        return (
          <Table.TBody key={domNode.name + idx}>
            {renderChildren(domNode)}
          </Table.TBody>
        )

      case NodeNames.table:
        return (
          <div key={domNode.name + idx} className={styles.tableContainer}>
            <Table>{renderChildren(domNode)}</Table>
          </div>
        )

      case NodeNames.p:
        return (
          domNode.children.length !== 0 && (
            <Typography
              key={domNode.name + idx}
              variant="Body/Paragraph/mdRegular"
              className={styles.text}
            >
              <p>{renderChildren(domNode)}</p>
            </Typography>
          )
        )

      case NodeNames.em:
        return <em>{renderChildren(domNode)}</em>

      case NodeNames.strong:
        return <strong>{renderChildren(domNode)}</strong>

      case NodeNames.span:
        return <span>{renderChildren(domNode)}</span>
    }
  } else if (domNode.type === ElementType.Text) {
    return domNode.data
  }
  return null
}
