/**
 * Hook for rendering Mermaid diagrams with debounce and validation
 */

import mermaid from 'mermaid';
import { useEffect, useRef, useState } from 'react';

import { useMermaidCleanup } from './useMermaidCleanup';
import { useMermaidValidation } from './useMermaidValidation';

interface UseMermaidRendererProps {
    chart: string;
    theme: string;
    isCompact?: boolean;
}

interface MermaidRenderResult {
    mermaidRef: React.RefObject<HTMLDivElement>;
    svgContent: string;
    isVertical: boolean;
    isRendering: boolean;
}

// Utility function to apply text colors to Mermaid SVG
const applyMermaidTextColors = (container: HTMLElement, textColor: string) => {
    const svgElement = container.querySelector('svg');
    if (svgElement) {
        // SVG text elements use 'fill'
        svgElement.querySelectorAll('text').forEach((el) => {
            (el as SVGElement).style.fill = textColor;
        });

        // HTML elements inside foreignObject use 'color'
        svgElement.querySelectorAll('.nodeLabel, .edgeLabel').forEach((el) => {
            (el as HTMLElement).style.color = textColor;
        });
    }
};

// Detect if diagram is vertical (tall and narrow)
const isVerticalDiagram = (svgElement: SVGSVGElement): boolean => {
    const viewBox = svgElement.getAttribute('viewBox');
    if (viewBox) {
        const [, , width, height] = viewBox.split(' ').map(Number);
        return height > width * 1.5;
    }
    const bbox = svgElement.getBBox?.();
    if (bbox) {
        return bbox.height > bbox.width * 1.5;
    }
    return false;
};

export function useMermaidRenderer({ chart, theme, isCompact = false }: UseMermaidRendererProps): MermaidRenderResult {
    const mermaidRef = useRef<HTMLDivElement>(null);
    const renderTimerRef = useRef<NodeJS.Timeout | null>(null);
    const [svgContent, setSvgContent] = useState<string>('');
    const [isVertical, setIsVertical] = useState(false);
    const [isRendering, setIsRendering] = useState(false);

    const { isMermaidCodeComplete } = useMermaidValidation();
    const { cleanupMermaidErrors } = useMermaidCleanup();

    useEffect(() => {
        // Get CSS variables for semantic colors
        const getCSSVariable = (variable: string) => {
            if (typeof document === 'undefined') return '';
            const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
            if (!value) return '';
            // If value is already a complete color (hex, rgb, hsl with parentheses), return as-is
            if (value.startsWith('#') || value.startsWith('rgb') || value.startsWith('hsl(')) {
                return value;
            }
            // Otherwise assume it's HSL components and wrap in hsl()
            return `hsl(${value})`;
        };

        const diagramFontSize = isCompact ? '12px' : '14px';

        const themeVariables = theme === 'dark' ? {
            primaryColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            primaryTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',
            primaryBorderColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            secondaryColor: getCSSVariable('--muted') || 'hsl(217.2 32.6% 17.5%)',
            secondaryTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',
            secondaryBorderColor: getCSSVariable('--border') || 'hsl(217.2 32.6% 27.5%)',
            tertiaryColor: getCSSVariable('--accent') || 'hsl(217.2 32.6% 20%)',
            tertiaryTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',
            tertiaryBorderColor: getCSSVariable('--border') || 'hsl(217.2 32.6% 27.5%)',
            mainBkg: getCSSVariable('--card') || 'hsl(222.2 84% 8%)',
            textColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',
            nodeBorder: getCSSVariable('--border') || 'hsl(217.2 32.6% 27.5%)',
            nodeTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',
            secondBkg: getCSSVariable('--muted') || 'hsl(217.2 32.6% 17.5%)',
            lineColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            edgeLabelBackground: getCSSVariable('--card') || 'hsl(222.2 84% 8%)',
            clusterBkg: getCSSVariable('--muted') || 'hsl(217.2 32.6% 12%)',
            clusterBorder: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            background: getCSSVariable('--background') || 'hsl(222.2 84% 4.9%)',
            labelBackground: getCSSVariable('--card') || 'hsl(222.2 84% 8%)',
            labelTextColor: getCSSVariable('--foreground') || 'hsl(210 40% 98%)',
            errorBkgColor: getCSSVariable('--destructive') || 'hsl(0 62.8% 30.6%)',
            errorTextColor: 'hsl(210 40% 98%)',
            fontSize: diagramFontSize,
            fontFamily: 'Inter, system-ui, sans-serif',
        } : {
            primaryColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            primaryTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',
            primaryBorderColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            secondaryColor: getCSSVariable('--secondary') || 'hsl(210 40% 96.1%)',
            secondaryTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',
            secondaryBorderColor: getCSSVariable('--border') || 'hsl(214.3 31.8% 91.4%)',
            tertiaryColor: getCSSVariable('--muted') || 'hsl(210 40% 96.1%)',
            tertiaryTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',
            tertiaryBorderColor: getCSSVariable('--border') || 'hsl(214.3 31.8% 91.4%)',
            mainBkg: getCSSVariable('--card') || 'hsl(0 0% 100%)',
            textColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',
            nodeBorder: getCSSVariable('--border') || 'hsl(214.3 31.8% 91.4%)',
            nodeTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',
            secondBkg: getCSSVariable('--muted') || 'hsl(210 40% 96.1%)',
            lineColor: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            edgeLabelBackground: getCSSVariable('--card') || 'hsl(0 0% 100%)',
            clusterBkg: getCSSVariable('--accent') || 'hsl(210 40% 98%)',
            clusterBorder: getCSSVariable('--primary') || 'hsl(221.2 83.2% 53.3%)',
            background: getCSSVariable('--background') || 'hsl(0 0% 100%)',
            labelBackground: getCSSVariable('--card') || 'hsl(0 0% 100%)',
            labelTextColor: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)',
            errorBkgColor: getCSSVariable('--destructive') || 'hsl(0 84.2% 60.2%)',
            errorTextColor: 'hsl(210 40% 98%)',
            fontSize: diagramFontSize,
            fontFamily: 'Inter, system-ui, sans-serif',
        };

        mermaid.initialize({
            startOnLoad: false,
            theme: 'base',
            securityLevel: 'loose',
            suppressErrorRendering: true, // Prevent mermaid from appending errors to body
            fontFamily: 'Inter, system-ui, sans-serif',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis',
            },
            themeVariables,
        });

        const renderChart = async () => {
            if (!mermaidRef.current || !chart) return;

            // Validate code completeness
            if (!isMermaidCodeComplete(chart)) {
                setIsRendering(true);
                return;
            }

            try {
                setIsRendering(true);

                // Clear container
                if (mermaidRef.current) {
                    mermaidRef.current.innerHTML = '';
                }

                const id = `mermaid-${Math.random().toString(36).substring(2, 9)}`;
                const { svg } = await mermaid.render(id, chart);

                if (mermaidRef.current) {
                    const textColor = theme === 'dark'
                        ? getCSSVariable('--foreground') || 'hsl(0 0% 90%)'
                        : getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)';

                    const processedSvg = svg.replace(
                        /<svg /,
                        `<svg style="--mermaid-text-color: ${textColor};" `
                    );

                    mermaidRef.current.innerHTML = processedSvg;
                    setSvgContent(processedSvg);

                    applyMermaidTextColors(mermaidRef.current, textColor);

                    const svgElement = mermaidRef.current.querySelector('svg');
                    if (svgElement) {
                        svgElement.style.maxWidth = '100%';
                        svgElement.style.height = 'auto';
                        svgElement.style.display = 'block';
                        setIsVertical(isVerticalDiagram(svgElement));
                    }
                }

                setIsRendering(false);
            } catch (error) {
                console.error('Mermaid rendering error:', error);
                setIsRendering(false);
                cleanupMermaidErrors();

                if (mermaidRef.current) {
                    mermaidRef.current.innerHTML = `
                        <div class="p-4 text-destructive bg-destructive/10 border border-destructive/20 rounded-sm">
                            <p class="font-semibold">Mermaid Diagram Error</p>
                            <p class="text-sm">${error instanceof Error ? error.message : 'Unknown error'}</p>
                        </div>
                    `;
                }
            }
        };

        // Clear previous timer
        if (renderTimerRef.current) {
            clearTimeout(renderTimerRef.current);
        }

        // Debounce: wait 500ms after last update
        renderTimerRef.current = setTimeout(() => {
            renderChart();
        }, 500);

        return () => {
            if (renderTimerRef.current) {
                clearTimeout(renderTimerRef.current);
            }
        };
    }, [chart, theme, isCompact, isMermaidCodeComplete, cleanupMermaidErrors]);

    return {
        mermaidRef,
        svgContent,
        isVertical,
        isRendering,
    };
}
