import ReactMarkdown, { type Components } from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import rehypeSanitize from 'rehype-sanitize'
import remarkGfm from 'remark-gfm'

export interface MarkdownContentProps {
  /** Markdown source. */
  content: string
  /**
   * Element overrides. Consumers (`MarkdownUI`, `Note`, …) supply their own
   * typography / link styling here; the engine itself stays opinion-free.
   */
  components?: Components
  /**
   * When `true`, raw HTML in the source is rendered. Defaults to `false` so
   * caption slots like `Note` stay safe-by-default; the document-style
   * Markdown widget opts in.
   */
  allowHtml?: boolean
  /**
   * When `true`, `<img>` / `![alt](url)` markdown produces an `<img>` tag.
   * Defaults to `false` so caption slots stay text-only by default.
   */
  allowImages?: boolean
  /**
   * When `true`, enables GitHub Flavored Markdown (tables, strikethrough,
   * task lists, autolinks) via `remark-gfm`. Defaults to `false` so existing
   * consumers keep CommonMark-only parsing.
   */
  gfm?: boolean
}

// Allowlist of URL schemes considered safe for `<a href>` and `<img src>`.
// Anything outside this set (e.g. `data:`, `javascript:`, `vbscript:`) is
// stripped by `safeUrlTransform`. Belt-and-braces with `rehype-sanitize`'s
// `defaultSchema` (which already restricts protocols when raw HTML is parsed)
// — this layer also covers the `allowHtml=false` path, where the sanitizer
// doesn't run but `react-markdown`'s default `urlTransform` only blocks
// `javascript:`.
const SAFE_URL_PREFIX = /^(https?:|mailto:|tel:|#|\/|\.\/|\.\.\/)/i

function safeUrlTransform(url: string): string {
  const trimmed = (url ?? '').trim()
  if (!trimmed) return ''
  if (SAFE_URL_PREFIX.test(trimmed)) return url
  return ''
}

/**
 * Low-level Markdown rendering primitive. Wraps `react-markdown` with two
 * opt-in capabilities (`allowHtml`, `allowImages`) and a consumer-supplied
 * component map for typography. Both default OFF — Note-style consumers
 * are safe-by-default; MarkdownUI opts both ON to render rich content.
 *
 * `allowHtml` plugs in `rehype-raw` so raw HTML nodes in the source are
 * actually parsed, then `rehype-sanitize` with the default schema strips
 * `<script>`, event handlers, and dangerous URL schemes from the parsed
 * tree. `safeUrlTransform` is always applied as a second layer for markdown
 * links/images on the `allowHtml=false` path.
 */
export function MarkdownContent({
  content,
  components,
  allowHtml = false,
  allowImages = false,
  gfm = false,
}: MarkdownContentProps) {
  const disallowed = allowImages ? undefined : ['img']
  return (
    <ReactMarkdown
      components={components}
      disallowedElements={disallowed}
      skipHtml={!allowHtml}
      remarkPlugins={gfm ? [remarkGfm] : undefined}
      rehypePlugins={allowHtml ? [rehypeRaw, rehypeSanitize] : undefined}
      urlTransform={safeUrlTransform}
    >
      {content}
    </ReactMarkdown>
  )
}
