import { useState, useEffect } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import rehypeSlug from 'rehype-slug';
import { highlight } from './highlight';
import { copyToClipboard } from 'helpers/clipboard';

type HastNode = {
  type: string;
  value?: string;
  tagName?: string;
  properties?: Record<string, unknown>;
  children?: HastNode[];
};

type MarkdownRendererProps = {
  content: string;
  scrollContainer: React.RefObject<HTMLDivElement | null>;
};

function getNodeText(node: HastNode): string {
  if (node.type === 'text') return node.value ?? '';
  if (node.children) return node.children.map(getNodeText).join('');
  return '';
}

export const MarkdownRenderer = ({ content, scrollContainer }: MarkdownRendererProps) => {
  const handleAnchorClick = (ev: React.MouseEvent<HTMLElement>) => {
    const target = (ev.target as HTMLElement).closest('a');
    if (!target) return;
    const href = target.getAttribute('href');
    if (!href?.startsWith('#')) return;
    ev.preventDefault();
    const id = href.slice(1);
    const el = scrollContainer.current?.querySelector(`#${CSS.escape(id)}`);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };

  return (
    <article className="file-viewer-md" onClick={handleAnchorClick}>
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        rehypePlugins={[rehypeRaw, rehypeSlug]}
        components={{
          a({ href, children, ...props }) {
            const isExternal = href && !href.startsWith('#');
            return (
              <a href={href} {...(isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {})} {...props}>
                {children}
              </a>
            );
          },
          pre({ node, children }) {
            const codeChild = node?.children[0];
            if (codeChild?.type === 'element' && codeChild.tagName === 'code') {
              const classes = (codeChild.properties?.className ?? []) as string[];
              const lang = classes[0]?.replace('language-', '') ?? '';
              const text = getNodeText(codeChild).replace(/\n$/, '');
              return <HighlightedCodeBlock code={text} lang={lang} />;
            }
            return <pre>{children}</pre>;
          },
          code({ children, ...props }) {
            return (
              <code className="px-1.5 py-0.5 rounded bg-duck-teal/10 text-duck-teal text-[0.85em] font-mono" {...props}>
                {children}
              </code>
            );
          },
        }}
      >
        {content}
      </ReactMarkdown>
    </article>
  );
};

// ── Internal helpers ──

const CopyButton = ({ text }: { text: string }) => {
  const [copied, setCopied] = useState(false);
  return (
    <button
      onClick={() => {
        copyToClipboard(text);
        setCopied(true);
        setTimeout(() => setCopied(false), 1500);
      }}
      className="absolute top-2 right-2 px-2 py-1 text-[10px] font-mono rounded bg-white/10 text-white/60 hover:text-white hover:bg-white/20 transition-colors cursor-pointer"
    >
      {copied ? 'Copied!' : 'Copy'}
    </button>
  );
};

const HighlightedCodeBlock = ({ code, lang }: { code: string; lang: string }) => {
  const [html, setHtml] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    highlight(code, lang).then((result) => {
      if (!cancelled) setHtml(result);
    });
    return () => {
      cancelled = true;
    };
  }, [code, lang]);

  return (
    <div className="relative my-4">
      <CopyButton text={code} />
      {lang && (
        <span className="absolute top-2 left-3 text-[10px] font-mono text-white/30 uppercase tracking-wider z-10">
          {lang}
        </span>
      )}
      {html ? (
        <div
          className="[&_pre]:rounded-lg [&_pre]:p-4 [&_pre]:pt-8 [&_pre]:overflow-x-auto [&_pre]:text-sm [&_pre]:font-mono [&_pre]:leading-relaxed [&_pre]:border [&_pre]:border-white/5 [&_code]:font-mono"
          dangerouslySetInnerHTML={{ __html: html }}
        />
      ) : (
        <pre className="rounded-lg bg-[#0d1117] text-[#e6edf3] p-4 pt-8 overflow-x-auto text-sm font-mono leading-relaxed border border-white/5">
          <code>{code}</code>
        </pre>
      )}
    </div>
  );
};
