import React from 'react';
import { DrawIoEmbed } from 'react-drawio';
import { cn } from '@/lib/utils';

export interface DiagramEditorHandle {
  getXml: () => string;
}

export interface DiagramEditorProps {
  xml: string;
  readOnly?: boolean;
  className?: string;
  onChange?: (xml: string) => void;
}

const BLANK_XML = '<mxfile><diagram id="new" name="Page-1"><mxGraphModel dx="0" dy="0" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel></diagram></mxfile>';

function detectDark(): boolean {
  if (typeof document === 'undefined') return false;
  const theme = document.documentElement.getAttribute('data-theme');
  return theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches);
}

export const DiagramEditor = React.forwardRef<DiagramEditorHandle, DiagramEditorProps>(
  function DiagramEditor({ xml, readOnly, className, onChange }, ref) {
    const latestXmlRef = React.useRef(xml);
    const drawioRef = React.useRef<React.ComponentRef<typeof DrawIoEmbed>>(null);
    const hasShownTemplate = React.useRef(false);
    const [isDark, setIsDark] = React.useState(detectDark);
    const stableXmlRef = React.useRef(xml);

    // When the parent switches files (xml prop changes), reset the stable
    // reference so the new content renders instead of the first file's content.
    const prevXmlRef = React.useRef(xml);
    if (prevXmlRef.current !== xml) {
      prevXmlRef.current = xml;
      stableXmlRef.current = xml;
      latestXmlRef.current = xml;
    }

    const prevIsDark = React.useRef(isDark);
    if (prevIsDark.current !== isDark) {
      prevIsDark.current = isDark;
      stableXmlRef.current = latestXmlRef.current;
    }

    const containerRef = React.useRef<HTMLDivElement>(null);

    React.useEffect(() => {
      const check = () => setIsDark(detectDark());
      check();
      const observer = new MutationObserver(check);
      observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
      return () => observer.disconnect();
    }, []);

    // Focus the iframe once on mount so keyboard shortcuts work without
    // clicking the canvas. Intentionally not keyed on isDark — re-focusing
    // on every theme toggle would steal keyboard focus from the user.
    React.useEffect(() => {
      const id = setTimeout(() => {
        containerRef.current?.querySelector<HTMLIFrameElement>('.diagrams-iframe')?.focus();
      }, 600);
      return () => clearTimeout(id);
    }, []);

    React.useImperativeHandle(ref, () => ({
      getXml: () => latestXmlRef.current,
    }));

    const handleLoad = React.useCallback(() => {
      if (!xml && !hasShownTemplate.current) {
        hasShownTemplate.current = true;
        setTimeout(() => {
          drawioRef.current?.template({});
        }, 500);
      }
    }, [xml]);

    const handleAutoSave = React.useCallback((data: { xml: string }) => {
      latestXmlRef.current = data.xml;
      onChange?.(data.xml);
    }, [onChange]);

    return (
      <div ref={containerRef} className={cn('h-full w-full', className)}>
        <DrawIoEmbed
          key={isDark ? 'dark' : 'light'}
          ref={drawioRef}
          xml={stableXmlRef.current || BLANK_XML}
          autosave
          urlParameters={{
            ui: readOnly ? 'simple' : isDark ? 'dark' : 'kennedy',
            spin: true,
            libraries: !readOnly,
            chrome: readOnly,
            nav: readOnly,
            layers: readOnly,
            noSaveBtn: true,
            noExitBtn: true,
            saveAndExit: false,
          }}
          onLoad={handleLoad}
          onAutoSave={handleAutoSave}
        />
      </div>
    );
  },
);
