import rangeParser from "parse-numeric-range";
import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter";
import tsx from "react-syntax-highlighter/dist/cjs/languages/prism/tsx";
import typescript from "react-syntax-highlighter/dist/cjs/languages/prism/typescript";
import scss from "react-syntax-highlighter/dist/cjs/languages/prism/scss";
import bash from "react-syntax-highlighter/dist/cjs/languages/prism/bash";
import markdown from "react-syntax-highlighter/dist/cjs/languages/prism/markdown";
import json from "react-syntax-highlighter/dist/cjs/languages/prism/json";
import { coldarkDark as defaulttheme } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { BiCopy } from "react-icons/bi";
import { Components } from "react-markdown";
import { generateSlug } from "../utils/general";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
SyntaxHighlighter.registerLanguage("tsx", tsx);
SyntaxHighlighter.registerLanguage("typescript", typescript);
SyntaxHighlighter.registerLanguage("scss", scss);
SyntaxHighlighter.registerLanguage("bash", bash);
SyntaxHighlighter.registerLanguage("markdown", markdown);
SyntaxHighlighter.registerLanguage("json", json);

export const StyledMarkdown = ({ html }: { html: string }) => {
  const MarkdownComponents: Components = {
    h3: (props: any) => {
      const arr = props.children;
      let heading = "";

      for (let i = 0; i < arr.length; i++) {
        if (arr[i]?.type !== undefined) {
          for (let j = 0; j < arr[i].props.children.length; j++) {
            heading += arr[i]?.props?.children[0];
          }
        } else heading += arr[i];
      }

      const slug = generateSlug(heading);
      return (
        <h3 id={slug}>
          <a href={`#${slug}`} {...props}></a>
        </h3>
      );
    },
    code({ node, inline, className, ...props }: any) {
      const match = /language-(\w+)/.exec(className || "");
      const hasMeta = node?.data?.meta;

      const applyHighlights: object = (applyHighlights: number) => {
        if (hasMeta) {
          const RE = /{([\d,-]+)}/;
          const metadata = node.data.meta?.replace(/\s/g, "");
          const strlineNumbers = RE?.test(metadata)
            ? // @ts-ignore
              RE?.exec(metadata)[1]
            : "0";
          const highlightLines = rangeParser(strlineNumbers);
          const highlight = highlightLines;
          const data = highlight.includes(applyHighlights) ? "highlight" : null;
          return { data };
        } else {
          return {};
        }
      };

      return match ? (
        <div>
          <div className="w-full">
            <button
              className="w-fit ml-2 important"
              onClick={() => navigator.clipboard.writeText(props.children)}
            >
              <BiCopy />
            </button>
          </div>
          <SyntaxHighlighter
            style={defaulttheme}
            language={match[1]}
            PreTag="div"
            className="codeStyle"
            showLineNumbers={true}
            wrapLines={hasMeta ? true : false}
            useInlineStyles={true}
            lineProps={applyHighlights}
            {...props}
          />
        </div>
      ) : (
        <code className={className} {...props} />
      );
    },
  };
  return (
    <div
      className="
        prose 
        prose-code:font-mono prose-code:text-gray-100 prose-code:bg-gray-700 prose-code:p-1 prose-code:m-1 prose-code:rounded-md 
        prose-headings:text-gray-800 dark:prose-headings:text-primary-text prose-p:text-gray-600 dark:prose-p:text-gray-100 
        prose-img:w-full prose-img:h-auto xl:prose-img:max-h-96 prose-img:object-cover 
        prose-li text-gray-600 dark:prose-li:text-gray-300 prose-td:text-gray-600 dark:prose-td:text-gray-400 
      prose-a:text-primary dark:prose-a:text-action prose-strong:text-gray-900 dark:prose-strong:text-gray-50
        dark:prose-hr:bg-gray-200 prose-hr:bg-gray-400
      "
    >
      <ReactMarkdown
        components={MarkdownComponents}
        remarkPlugins={[remarkGfm]}
        children={html}
      />
    </div>
  );
};
