"use client";

import { useEffect, useState, useCallback, useRef } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import rehypeHighlight from "rehype-highlight";
import "highlight.js/styles/atom-one-dark.min.css";
import styles from "./lesson-markdown.module.css";

type TocItem = { level: number; text: string; id: string };

function extractToc(content: string): TocItem[] {
  const items: TocItem[] = [];
  const lines = content.split("\n");
  let idCounter = 0;
  for (const line of lines) {
    const h1 = line.match(/^# (.+)$/);
    const h2 = line.match(/^## (.+)$/);
    if (h1) {
      items.push({ level: 1, text: h1[1].replace(/#{1,6}\s/g, "").trim(), id: `h-${idCounter++}` });
    } else if (h2) {
      items.push({ level: 2, text: h2[1].replace(/#{1,6}\s/g, "").trim(), id: `h-${idCounter++}` });
    }
  }
  return items;
}

function slugify(text: string): string {
  return text
    .replace(/[^\p{L}\p{N}\s-]/gu, "")
    .replace(/\s+/g, "-")
    .toLowerCase();
}

export function LessonMarkdown({ content }: { content: string }) {
  const [readProgress, setReadProgress] = useState(0);
  const [showBackTop, setShowBackTop] = useState(false);
  const [showToc, setShowToc] = useState(false);
  const contentRef = useRef<HTMLDivElement>(null);
  const toc = extractToc(content);

  useEffect(() => {
    let ticking = false;
    const onScroll = () => {
      if (ticking) return;
      ticking = true;
      requestAnimationFrame(() => {
        const scrollTop = window.scrollY || document.documentElement.scrollTop;
        const docHeight = document.documentElement.scrollHeight - window.innerHeight;
        setReadProgress(docHeight > 0 ? Math.min(100, (scrollTop / docHeight) * 100) : 0);
        setShowBackTop(scrollTop > 400);
        ticking = false;
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const handleTocJump = useCallback((index: number) => {
    setShowToc(false);
    const root = contentRef.current;
    if (!root) return;
    const headings = root.querySelectorAll("h1, h2");
    const el = headings[index] as HTMLElement;
    if (el) {
      el.scrollIntoView({ behavior: "smooth", block: "start" });
    }
  }, []);

  return (
    <>
      <div className={styles.readingProgress} style={{ width: `${readProgress}%` }} />

      <div ref={contentRef} className={`${styles.markdownBody} markdown-body`}>
        <ReactMarkdown
          remarkPlugins={[remarkGfm]}
          rehypePlugins={[[rehypeHighlight, { detect: true }]]}
          components={{
            h1: ({ children }) => {
              const text = String(children);
              const id = slugify(text);
              return (
                <h1 id={id} className="scroll-mt-24">
                  {children}
                </h1>
              );
            },
            h2: ({ children }) => {
              const text = String(children);
              const id = slugify(text);
              return (
                <h2 id={id} className="scroll-mt-24">
                  {children}
                </h2>
              );
            },
            h3: ({ children }) => <h3 className="scroll-mt-20">{children}</h3>,
            h4: ({ children }) => <h4>{children}</h4>,
            h5: ({ children }) => <h5>{children}</h5>,
            h6: ({ children }) => <h6>{children}</h6>,
            p: ({ children }) => <p>{children}</p>,
            ul: ({ children }) => <ul>{children}</ul>,
            ol: ({ children }) => <ol>{children}</ol>,
            li: ({ children, className }) => (
              <li className={className?.includes("task-list-item") ? "flex items-start gap-2" : ""}>
                {children}
              </li>
            ),
            pre: ({ children }) => (
              <pre className={styles.codeBlock}>{children}</pre>
            ),
            code: ({ className, children }) => (
              <code className={className}>{children}</code>
            ),
            blockquote: ({ children }) => <blockquote>{children}</blockquote>,
            a: ({ href, children }) => (
              <a href={href} target="_blank" rel="noopener noreferrer">
                {children}
              </a>
            ),
            img: ({ src, alt }) => (
              // eslint-disable-next-line @next/next/no-img-element
              <img src={src || ""} alt={alt || ""} loading="lazy" decoding="async" />
            ),
            table: ({ children }) => (
              <div className="overflow-x-auto">
                <table>{children}</table>
              </div>
            ),
            th: ({ children }) => <th>{children}</th>,
            td: ({ children }) => <td>{children}</td>,
            hr: () => <hr />,
            strong: ({ children }) => <strong>{children}</strong>,
            em: ({ children }) => <em>{children}</em>,
          }}
        >
          {content}
        </ReactMarkdown>
      </div>

      {/* 目录抽屉 */}
      <div
        className={`${styles.drawerMask} ${showToc ? styles.drawerMaskOpen : ""}`}
        onClick={() => setShowToc(false)}
        aria-hidden="true"
      />
      <aside className={`${styles.drawer} ${showToc ? styles.drawerOpen : ""}`}>
        <div className={styles.drawerTitle}>目录</div>
        {toc.map((item, i) => (
          <div
            key={item.id}
            role="button"
            tabIndex={0}
            className={item.level === 2 ? `${styles.drawerItem} ${styles.drawerItemH2}` : styles.drawerItem}
            onClick={() => handleTocJump(i)}
            onKeyDown={(e) => {
              if (e.key === "Enter" || e.key === " ") handleTocJump(i);
            }}
          >
            {item.text}
          </div>
        ))}
      </aside>

      {showBackTop && (
        <>
          {toc.length > 0 && (
            <button
              type="button"
              className={styles.tocButton}
              onClick={() => setShowToc(true)}
              aria-label="打开目录"
            >
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <line x1="3" y1="6" x2="21" y2="6" />
                <line x1="3" y1="12" x2="21" y2="12" />
                <line x1="3" y1="18" x2="21" y2="18" />
              </svg>
            </button>
          )}
          <button
            type="button"
            className={styles.backToTop}
            onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
            aria-label="回到顶部"
          >
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M18 15l-6-6-6 6" />
            </svg>
          </button>
        </>
      )}
    </>
  );
}
