import spoiler from "@aeharding/remark-lemmy-spoiler";
import superSub from "@aeharding/remark-lemmy-supersub";
import { MouseEvent } from "react";
import ReactMarkdown, { Options as ReactMarkdownOptions } from "react-markdown";
import rehypeHighlight from "rehype-highlight";

import { buildMediaId } from "#/features/media/video/VideoPortalProvider";
import { cx } from "#/helpers/css";
import { useAppSelector } from "#/store";

import InAppExternalLink from "../InAppExternalLink";
import Details from "./components/spoiler/Details";
import Summary from "./components/spoiler/Summary";
import Table from "./components/Table";
import customRemarkGfm from "./customRemarkGfm";
import LinkInterceptor from "./LinkInterceptor";
import MarkdownImg from "./MarkdownImg";

import styles from "./Markdown.module.css";

export interface MarkdownProps extends Omit<
  ReactMarkdownOptions,
  "remarkPlugins"
> {
  className?: string;

  disableInternalLinkRouting?: boolean;

  /**
   * Prevent propagating events if an interactive element is clicked.
   */
  preventInteractionPropagation?: boolean;

  /**
   * ID should be unique (prefixed, if using autoincrement id like lemmy uses)
   * Ideally, just use the `ap_id`
   *
   * This is used so spoilers can track open state
   */
  id: string;
}

export default function Markdown({
  id,
  disableInternalLinkRouting,
  className,
  preventInteractionPropagation,
  ...props
}: MarkdownProps) {
  const connectedInstance = useAppSelector(
    (state) => state.auth.connectedInstance,
  );

  function onLinkClick(onClick?: (e: MouseEvent<HTMLAnchorElement>) => void) {
    return (e: MouseEvent<HTMLAnchorElement>) => {
      if (preventInteractionPropagation) {
        e.stopPropagation();
        return;
      }

      onClick?.(e);
    };
  }

  return (
    <div className={cx(className, styles.markdown)}>
      <ReactMarkdown
        {...props}
        components={{
          img: (props) => (
            <MarkdownImg
              {...props}
              onClick={(e) => e.stopPropagation()}
              portalWithMediaId={buildMediaId(
                id,
                props.node?.position?.start.offset,
              )}
            />
          ),
          table: Table,
          a: disableInternalLinkRouting
            ? (props) => (
                <InAppExternalLink
                  {...props}
                  target="_blank"
                  rel="noopener noreferrer"
                  onClick={onLinkClick(props.onClick)}
                />
              )
            : (props) => (
                <LinkInterceptor
                  {...props}
                  onClick={onLinkClick(props.onClick)}
                />
              ),
          summary: Summary,
          details: (props) => <Details {...props} id={id} />,
          ...props.components,
        }}
        remarkPlugins={[
          superSub,
          [customRemarkGfm, { connectedInstance }],
          spoiler,
        ]}
        rehypePlugins={[[rehypeHighlight, { detect: true }]]}
      />
    </div>
  );
}
