import { CopyOutlined } from "@ant-design/icons";
import { App, Button } from "antd";
import { useCallback, useEffect, useState } from "react";
import { codeToHtml } from "shiki";

import { useIsDark } from "../../../shared/hooks/use-is-dark";

interface HighlightBlockProps {
  code: string;
  isStreaming: boolean;
  lang: string;
}

export function HighlightBlock({ code, isStreaming, lang }: HighlightBlockProps) {
  const { message } = App.useApp();
  const isDark = useIsDark();
  const [highlighted, setHighlighted] = useState<null | string>(null);

  const handleCopy = useCallback(() => {
    navigator.clipboard.writeText(code).then(
      () => message.success("已复制"),
      () => message.error("复制失败"),
    );
  }, [code, message]);

  useEffect(() => {
    if (isStreaming || !code) return;

    let cancelled = false;
    codeToHtml(code, {
      lang,
      theme: isDark ? "github-dark" : "github-light",
    })
      .then((html) => {
        if (!cancelled) setHighlighted(html);
      })
      .catch(() => {
        if (!cancelled) setHighlighted(null);
      });

    return () => {
      cancelled = true;
    };
  }, [code, lang, isDark, isStreaming]);

  if (isStreaming) {
    return (
      <pre className="code-block">
        <code>{code}</code>
      </pre>
    );
  }

  return (
    <div className="code-block">
      <div className="code-block-header">
        <span className="code-block-lang">{lang}</span>
        <Button className="btn-dimmed" icon={<CopyOutlined />} onClick={handleCopy} size="small" type="text" />
      </div>
      {highlighted ? (
        <div className="code-block-body" dangerouslySetInnerHTML={{ __html: highlighted }} />
      ) : (
        <div className="code-block-body">
          <pre>
            <code>{code}</code>
          </pre>
        </div>
      )}
    </div>
  );
}
