"use client";

import React, { useEffect, useRef, useState } from "react";
import mermaid from "mermaid";
import { ComponentShareButton } from "./ComponentShareButton";
import { Reveal } from "./Reveal";

interface MermaidProps {
  graph?: string;
  children?: React.ReactNode;
  id?: string;
  title?: string;
  showShare?: boolean;
  fontSize?: string;
  nodeFontSize?: string;
  labelFontSize?: string;
  actorFontSize?: string;
  messageFontSize?: string;
  noteFontSize?: string;
  titleFontSize?: string;
  sectionFontSize?: string;
  legendFontSize?: string;
}

class MermaidErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean }> {
  constructor(props: { children: React.ReactNode }) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(_error: any) {
    return { hasError: true };
  }

  componentDidCatch(error: any, errorInfo: any) {
    console.error("MermaidErrorBoundary caught an error:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="p-4 bg-red-50 border border-red-100 rounded text-red-600 text-sm font-mono text-center my-8">
          Diagram rendering crashed.
        </div>
      );
    }
    return this.props.children;
  }
}

const MermaidInternal: React.FC<MermaidProps> = ({
  graph,
  children,
  id: providedId,
  title,
  showShare = false,
  fontSize = "20px",
  nodeFontSize,
  labelFontSize,
  actorFontSize,
  messageFontSize,
  noteFontSize,
  titleFontSize,
  sectionFontSize,
  legendFontSize,
}) => {
  const [id, setId] = useState<string | null>(null);
  const wrapperRef = useRef<HTMLDivElement>(null);
  const [svgContent, setSvgContent] = useState<string>("");
  const [isVisible, setIsVisible] = useState(true); // Forced true specifically to bypass lazy loading bug
  const [isRendered, setIsRendered] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Extract text from React children nodes (MDX parses multi-line content as React nodes)
  const extractTextFromChildren = (node: React.ReactNode): string => {
    if (typeof node === 'string') return node;
    if (typeof node === 'number') return String(node);
    if (Array.isArray(node)) return node.map(extractTextFromChildren).join('\n');
    if (React.isValidElement(node)) {
      const props = node.props as { children?: React.ReactNode };
      if (props.children) {
        return extractTextFromChildren(props.children);
      }
    }
    return '';
  };

  const rawGraph = graph || extractTextFromChildren(children) || "";

  // MDXRemote double-escapes \n in plain string props (e.g., "graph TD\\nA-->B" becomes "graph TD\\\\nA-->B")
  // We need to unescape these back to real newlines for Mermaid to parse
  const sanitizedGraph = rawGraph
    .trim()
    .replace(/^`+|`+$/g, '')
    .replace(/\\n/g, '\n')
    .replace(/\\"/g, '"')
    .replace(/\\'/g, "'");

  // Early return for empty graph — show fallback instead of blank space
  if (!sanitizedGraph || sanitizedGraph.length < 5) {
    return (
      <div className="not-prose my-8 p-6 bg-slate-50 border border-slate-200 rounded-xl text-center">
        <p className="text-sm text-slate-400 font-medium">Diagramm konnte nicht geladen werden</p>
      </div>
    );
  }

  useEffect(() => {
    const generatedId = providedId || `mermaid-${Math.random().toString(36).substring(2, 11)}`;
    setId(generatedId);
  }, [providedId]);

  // Observer to detect when the component is actually in view and layout is ready
  useEffect(() => {
    if (!wrapperRef.current) return;

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setIsVisible(true);
            observer.disconnect(); // Render once per diagram
          }
        });
      },
      { rootMargin: "200px" } // Start rendering 200px before it scrolls into view
    );

    observer.observe(wrapperRef.current);
    return () => observer.disconnect();
  }, [id]);

  useEffect(() => {
    if (!isVisible || !id || isRendered) {
      return;
    }

    mermaid.initialize({
      startOnLoad: false,
      theme: "base",
      darkMode: false,
      htmlLabels: false,
      flowchart: {
        useMaxWidth: true,
        htmlLabels: false,
        curve: 'basis',
        nodeSpacing: 50,
        rankSpacing: 60,
        padding: 15
      },
      sequence: {
        useMaxWidth: true,
        showSequenceNumbers: false,
        height: 40,
        actorMargin: 30,
        messageMargin: 30
      },
      gantt: { useMaxWidth: true },
      pie: { useMaxWidth: true },
      state: { useMaxWidth: true },
      themeVariables: {
        primaryColor: "#f8fafc", // slate-50
        primaryTextColor: "#334155", // slate-700
        primaryBorderColor: "#cbd5e1", // slate-300
        lineColor: "#64748b", // slate-500
        secondaryColor: "#f1f5f9", // slate-100
        tertiaryColor: "#e2e8f0", // slate-200
        background: "#ffffff",
        mainBkg: "#ffffff",
        secondBkg: "#f8fafc",
        tertiaryBkg: "#f1f5f9",
        textColor: "#1e293b",
        labelTextColor: "#475569",
        nodeBorder: "#cbd5e1",
        clusterBkg: "#f8fafc",
        clusterBorder: "#cbd5e1",
        edgeLabelBackground: "#ffffff",
        fontFamily: "var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
        fontSize: fontSize || "18px",
        nodeFontSize: nodeFontSize || fontSize || "18px",
        labelFontSize: labelFontSize || fontSize || "16px",
        actorFontSize: actorFontSize || fontSize || "18px",
        messageFontSize: messageFontSize || fontSize || "16px",
        noteFontSize: noteFontSize || fontSize || "16px",
        titleFontSize: titleFontSize || "24px",
        sectionFontSize: sectionFontSize || fontSize || "18px",
        legendFontSize: legendFontSize || fontSize || "18px",
        pie1: "#0f172a",
        pie2: "#334155",
        pie3: "#64748b",
        pie4: "#94a3b8",
        pie5: "#cbd5e1",
        pie6: "#1e293b",
        pie7: "#475569",
        pie8: "#000000",
        pie9: "#e2e8f0",
        pie10: "#020617",
        pie11: "#525252",
        pie12: "#262626",
      },
      securityLevel: "loose",
    });

    const renderGraph = async () => {
      if (!wrapperRef.current) return;
      if (wrapperRef.current.clientWidth === 0) return;

      const maxRetries = 3;
      let attempt = 0;
      let success = false;

      while (attempt < maxRetries && !success) {
        attempt++;
        try {
          if (!sanitizedGraph) return;
          if (!mermaid.render) return;

          const uniqueSvgId = `${id}-svg-${Date.now()}`;
          const tempDiv = document.createElement('div');
          document.body.appendChild(tempDiv);
          tempDiv.style.position = 'absolute';
          tempDiv.style.left = '-9999px';
          tempDiv.style.visibility = 'hidden';

          let rawSvg: string;
          try {
            const result = await mermaid.render(uniqueSvgId, sanitizedGraph, tempDiv);
            rawSvg = result.svg;
          } finally {
            if (document.body.contains(tempDiv)) {
              document.body.removeChild(tempDiv);
            }
          }

          let scaledSvg = rawSvg;
          const svgStartEnd = rawSvg.indexOf('>');
          if (svgStartEnd > -1) {
            const svgTag = rawSvg.substring(0, svgStartEnd + 1);
            const rest = rawSvg.substring(svgStartEnd + 1);
            const newSvgTag = svgTag.replace(/width="[^"]*"/, 'width="100%"').replace(/height="[^"]*"/, 'height="auto"');
            scaledSvg = newSvgTag + rest;
          }

          setSvgContent(scaledSvg);
          setIsRendered(true);
          setError(null);
          success = true;
        } catch (err) {
          if (attempt >= maxRetries) {
            setError("Diagramm konnte nicht geladen werden (Render-Fehler).");
            setIsRendered(true);
          } else {
            await new Promise(resolve => setTimeout(resolve, attempt * 200));
          }
        }
      }
    };

    const resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        if (entry.contentRect.width > 0 && !isRendered) {
          requestAnimationFrame(() => renderGraph());
          resizeObserver.disconnect();
        }
      }
    });

    resizeObserver.observe(wrapperRef.current);

    if (wrapperRef.current && wrapperRef.current.clientWidth > 0) {
      renderGraph();
      resizeObserver.disconnect();
    }

    return () => resizeObserver.disconnect();
  }, [isVisible, id, sanitizedGraph, fontSize, nodeFontSize, labelFontSize, actorFontSize, messageFontSize, noteFontSize, titleFontSize, sectionFontSize, legendFontSize]);

  if (!id) return null;

  return (
    <Reveal direction="up" delay={0.1}>
      <figure ref={wrapperRef} className="mermaid-wrapper not-prose my-16 w-full max-w-full group relative transition-all duration-500 ease-out z-10">

        <div className="absolute -inset-1 bg-gradient-to-r from-slate-200 to-slate-100/50 rounded-[2rem] blur opacity-20 group-hover:opacity-40 transition duration-1000 -z-10" />

        <div className="glass bg-white/80 backdrop-blur-xl border border-slate-100 rounded-2xl shadow-sm group-hover:shadow-md group-hover:border-slate-200 transition-all duration-500 overflow-hidden relative">

          <div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white to-transparent opacity-80" />

          <div className="w-full flex flex-col items-center justify-center p-6 md:p-8 lg:p-10 relative z-10">

            {showShare && (
              <div className="absolute top-6 right-6 md:opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-50">
                <ComponentShareButton targetId={id} title={title || 'System Architecture'} />
              </div>
            )}

            {title && (
              <header className="w-full mb-8 flex flex-col md:flex-row md:justify-between md:items-end gap-2 border-b border-slate-100 pb-4">
                <div>
                  <h4 className="text-xl md:text-2xl font-bold text-slate-900 tracking-tight m-0 flex items-center gap-3">
                    <span className="w-2 h-2 rounded-full bg-slate-400 shadow-[0_0_8px_rgba(148,163,184,0.6)] hidden md:block" />
                    {title}
                  </h4>
                </div>
              </header>
            )}

            <div className="flex justify-center w-full overflow-x-auto relative z-20">
              <div
                className={`mermaid 
                  w-full flex justify-center
                  [&>div]:!w-full [&>div]:!flex [&>div]:!justify-center
                  [&_svg]:!max-w-full [&_svg]:max-w-4xl [&_svg]:!h-auto [&_svg]:!max-h-[60vh] md:[&_svg]:!max-h-[600px]
                  [&_.node_rect]:!rx-[8px] [&_.node_rect]:!ry-[8px] 
                  [&_.node_rect]:!fill-white 
                  [&_.node_rect]:!stroke-slate-200 [&_.node_rect]:!stroke-[2px]
                  [&_.edgePath_path]:!stroke-slate-400 [&_.edgePath_path]:!stroke-[1.5px]
                  [&_.marker]:!fill-slate-400 [&_.marker]:!stroke-slate-400
                  [&_.nodeLabel]:!font-sans [&_.nodeLabel]:!font-bold [&_.nodeLabel]:!text-slate-700
                `}
                id={id}
                style={{
                  maxWidth: "100%",
                  overflow: "visible"
                }}
              >
                {error ? (
                  <div className="text-red-500 p-4 border border-red-200 bg-red-50 text-xs font-mono uppercase tracking-widest text-center w-full h-32 flex items-center justify-center rounded-xl">
                    {error}
                  </div>
                ) : svgContent ? (
                  <div dangerouslySetInnerHTML={{ __html: svgContent }} />
                ) : (
                  <div style={{ display: 'none' }}>{sanitizedGraph}</div>
                )}
              </div>
            </div>
          </div>
        </div>
      </figure>
    </Reveal>
  );
};

export const Mermaid = (props: MermaidProps) => (
  <MermaidErrorBoundary>
    <MermaidInternal {...props} />
  </MermaidErrorBoundary>
);
