'use client';

import { useEffect, useRef, useState, useCallback } from 'react';
import { Maximize2, Minimize2, Copy, Check, Code, Eye, Download, Pencil, RotateCcw } from 'lucide-react';

interface MermaidDiagramProps {
  code: string;
  title?: string;
  className?: string;
  editable?: boolean;
  onCodeChange?: (code: string) => void;
}

let mermaidInstance: typeof import('mermaid') | null = null;
let mermaidLoading = false;
let mermaidLoadCallbacks: Array<(m: typeof import('mermaid')) => void> = [];

async function loadMermaid() {
  if (mermaidInstance) return mermaidInstance;
  if (mermaidLoading) {
    return new Promise<typeof import('mermaid')>((resolve) => {
      mermaidLoadCallbacks.push(resolve);
    });
  }
  mermaidLoading = true;
  try {
    const mod = await import('mermaid');
    mod.default.initialize({
      startOnLoad: false,
      theme: 'dark',
      themeVariables: {
        primaryColor: '#3b82f6',
        primaryTextColor: '#e2e8f0',
        primaryBorderColor: '#475569',
        lineColor: '#64748b',
        secondaryColor: '#1e293b',
        tertiaryColor: '#0f172a',
        background: '#0f172a',
        mainBkg: '#1e293b',
        nodeBorder: '#475569',
        clusterBkg: '#1e293b',
        clusterBorder: '#334155',
        titleColor: '#e2e8f0',
        edgeLabelBackground: '#1e293b',
        nodeTextColor: '#e2e8f0',
      },
      flowchart: { htmlLabels: true, curve: 'basis' },
      er: { useMaxWidth: true },
      fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
    });
    mermaidInstance = mod;
    mermaidLoadCallbacks.forEach(cb => cb(mod));
    mermaidLoadCallbacks = [];
    return mod;
  } catch (err) {
    mermaidLoading = false;
    throw err;
  }
}

export default function MermaidDiagram({ code, title, className, editable, onCodeChange }: MermaidDiagramProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [svg, setSvg] = useState<string>('');
  const [error, setError] = useState<string>('');
  const [expanded, setExpanded] = useState(false);
  const [showCode, setShowCode] = useState(false);
  const [copied, setCopied] = useState(false);
  const [editMode, setEditMode] = useState(false);
  const [editBuffer, setEditBuffer] = useState(code);
  const [editError, setEditError] = useState('');
  const idRef = useRef(`mermaid-${Math.random().toString(36).slice(2, 10)}`);

  const renderDiagram = useCallback(async () => {
    if (!code.trim()) return;
    try {
      const mermaid = await loadMermaid();
      // Validate first
      await mermaid.default.parse(code.trim());
      const { svg: rendered } = await mermaid.default.render(idRef.current, code.trim());
      setSvg(rendered);
      setError('');
    } catch (err) {
      console.warn('Mermaid render error:', err);
      setError(err instanceof Error ? err.message : 'Failed to render diagram');
    }
  }, [code]);

  useEffect(() => {
    renderDiagram();
  }, [renderDiagram]);

  // Sync edit buffer when code prop changes externally
  useEffect(() => {
    if (!editMode) setEditBuffer(code);
  }, [code, editMode]);

  const handleApplyEdit = async () => {
    const trimmed = editBuffer.trim();
    if (!trimmed || trimmed === code.trim()) {
      setEditMode(false);
      setEditError('');
      return;
    }
    try {
      const mermaid = await loadMermaid();
      await mermaid.default.parse(trimmed);
      setEditError('');
      setEditMode(false);
      onCodeChange?.(trimmed);
    } catch (err) {
      setEditError(err instanceof Error ? err.message : 'Invalid Mermaid syntax');
    }
  };

  const handleCancelEdit = () => {
    setEditBuffer(code);
    setEditMode(false);
    setEditError('');
  };

  const handleCopy = async () => {
    await navigator.clipboard.writeText(code);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  const handleExportSVG = () => {
    if (!svg) return;
    const blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${(title || 'diagram').replace(/\s+/g, '_').toLowerCase()}.svg`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const handleExportPNG = async () => {
    if (!svg) return;
    try {
      const tempDiv = document.createElement('div');
      tempDiv.innerHTML = svg;
      const svgEl = tempDiv.querySelector('svg');
      if (!svgEl) return;
      const bbox = svgEl.getBoundingClientRect?.() || { width: 800, height: 600 };
      const w = parseFloat(svgEl.getAttribute('width') || String(bbox.width)) || 800;
      const h = parseFloat(svgEl.getAttribute('height') || String(bbox.height)) || 600;
      const scale = 2;
      const canvas = document.createElement('canvas');
      canvas.width = w * scale;
      canvas.height = h * scale;
      const ctx = canvas.getContext('2d');
      if (!ctx) return;
      ctx.fillStyle = '#0f172a';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      const svgData = new XMLSerializer().serializeToString(svgEl);
      const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
      const url = URL.createObjectURL(svgBlob);
      const img = new Image();
      img.onload = () => {
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        URL.revokeObjectURL(url);
        canvas.toBlob((blob) => {
          if (!blob) return;
          const pngUrl = URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = pngUrl;
          a.download = `${(title || 'diagram').replace(/\s+/g, '_').toLowerCase()}.png`;
          a.click();
          URL.revokeObjectURL(pngUrl);
        }, 'image/png');
      };
      img.src = url;
    } catch (err) {
      console.warn('PNG export failed:', err);
    }
  };

  const [showExportMenu, setShowExportMenu] = useState(false);

  return (
    <div className={`rounded-lg border border-slate-700/50 overflow-hidden ${className || ''}`}>
      {/* Toolbar */}
      <div className="flex items-center justify-between px-3 py-2 bg-slate-800/80 border-b border-slate-700/30">
        <div className="flex items-center gap-2">
          {title && <span className="text-sm font-medium text-white">{title}</span>}
        </div>
        <div className="flex items-center gap-1">
          {editable && !editMode && (
            <button
              onClick={() => { setEditMode(true); setShowCode(false); }}
              className="p-1.5 rounded text-gray-500 hover:text-amber-400 transition-colors"
              title="Edit Mermaid source"
            >
              <Pencil className="w-3.5 h-3.5" />
            </button>
          )}
          {editMode && (
            <>
              <button
                onClick={handleApplyEdit}
                className="p-1.5 rounded text-green-400 hover:text-green-300 transition-colors"
                title="Apply changes"
              >
                <Check className="w-3.5 h-3.5" />
              </button>
              <button
                onClick={handleCancelEdit}
                className="p-1.5 rounded text-gray-500 hover:text-red-400 transition-colors"
                title="Cancel edit"
              >
                <RotateCcw className="w-3.5 h-3.5" />
              </button>
            </>
          )}
          <button
            onClick={() => { setShowCode(!showCode); if (editMode) handleCancelEdit(); }}
            className={`p-1.5 rounded text-xs transition-colors ${
              showCode ? 'bg-slate-700 text-white' : 'text-gray-500 hover:text-gray-300'
            }`}
            title={showCode ? 'Show diagram' : 'Show code'}
          >
            {showCode ? <Eye className="w-3.5 h-3.5" /> : <Code className="w-3.5 h-3.5" />}
          </button>
          <button
            onClick={handleCopy}
            className="p-1.5 rounded text-gray-500 hover:text-gray-300 transition-colors"
            title="Copy Mermaid code"
          >
            {copied ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
          </button>
          <div className="relative">
            <button
              onClick={() => setShowExportMenu(!showExportMenu)}
              disabled={!svg}
              className="p-1.5 rounded text-gray-500 hover:text-gray-300 disabled:opacity-30 transition-colors"
              title="Export diagram"
            >
              <Download className="w-3.5 h-3.5" />
            </button>
            {showExportMenu && (
              <div className="absolute right-0 top-full mt-1 bg-slate-800 border border-slate-600 rounded-lg shadow-xl z-20 min-w-[120px]">
                <button onClick={() => { handleExportSVG(); setShowExportMenu(false); }}
                  className="w-full text-left px-3 py-1.5 text-xs text-gray-300 hover:bg-slate-700 rounded-t-lg">Export SVG</button>
                <button onClick={() => { handleExportPNG(); setShowExportMenu(false); }}
                  className="w-full text-left px-3 py-1.5 text-xs text-gray-300 hover:bg-slate-700 rounded-b-lg">Export PNG</button>
              </div>
            )}
          </div>
          <button
            onClick={() => setExpanded(!expanded)}
            className="p-1.5 rounded text-gray-500 hover:text-gray-300 transition-colors"
            title={expanded ? 'Collapse' : 'Expand'}
          >
            {expanded ? <Minimize2 className="w-3.5 h-3.5" /> : <Maximize2 className="w-3.5 h-3.5" />}
          </button>
        </div>
      </div>

      {/* Content */}
      {editMode ? (
        <div className="p-4 bg-slate-950">
          {editError && (
            <div className="mb-2 p-2 bg-red-500/10 border border-red-500/20 rounded text-red-400 text-xs">
              {editError}
            </div>
          )}
          <textarea
            value={editBuffer}
            onChange={e => setEditBuffer(e.target.value)}
            className="w-full min-h-[200px] bg-slate-900 border border-slate-700 rounded-lg p-3 text-xs text-gray-300 font-mono resize-y focus:outline-none focus:border-amber-500/50"
            spellCheck={false}
          />
          <div className="flex items-center justify-between mt-2">
            <span className="text-[10px] text-gray-600">Edit the Mermaid source above, then click ✓ to apply</span>
            <div className="flex gap-2">
              <button onClick={handleCancelEdit} className="px-3 py-1 text-xs text-gray-400 hover:text-white bg-slate-800 rounded">Cancel</button>
              <button onClick={handleApplyEdit} className="px-3 py-1 text-xs text-white bg-amber-600 hover:bg-amber-700 rounded">Apply</button>
            </div>
          </div>
        </div>
      ) : showCode ? (
        <div className="p-4 bg-slate-950 overflow-x-auto">
          <pre className="text-xs text-gray-400 whitespace-pre-wrap font-mono">{code}</pre>
        </div>
      ) : error ? (
        <div className="p-4 bg-slate-950">
          <div className="p-3 bg-amber-500/10 border border-amber-500/20 rounded-lg text-amber-400 text-xs mb-3">
            Diagram render error: {error}
          </div>
          <pre className="text-xs text-gray-500 whitespace-pre-wrap font-mono">{code}</pre>
        </div>
      ) : svg ? (
        <div
          ref={containerRef}
          className={`p-4 bg-slate-950 overflow-auto flex items-center justify-center transition-all ${
            expanded ? 'max-h-none' : 'max-h-[500px]'
          }`}
          dangerouslySetInnerHTML={{ __html: svg }}
          style={{ minHeight: '200px' }}
        />
      ) : (
        <div className="p-8 bg-slate-950 flex items-center justify-center">
          <div className="flex items-center gap-2 text-gray-500 text-sm">
            <div className="w-4 h-4 border-2 border-gray-600 border-t-brand rounded-full animate-spin" />
            Rendering diagram...
          </div>
        </div>
      )}
    </div>
  );
}
