const { useState, useEffect, useRef, useCallback } = React;

const EMBED_ORIGIN = 'https://embed.diagrams.net';
const EMBED_URL = `${EMBED_ORIGIN}/?embed=1&proto=json&spin=1&libraries=1`;

// ─── Service config field definitions ────────────────────────────────────────
const SERVICE_CONFIG_FIELDS = {
  ec2:        [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                 options: ['t3.micro','t3.small','t3.medium','t3.large','m5.large','m5.xlarge','c5.large','c5.xlarge','r5.large'] }],
  sagemaker:  [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                 options: ['ml.t3.medium','ml.t3.large','ml.m5.large','ml.m5.xlarge','ml.c5.large'] }],
  gamelift:   [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                 options: ['c5.large','c5.xlarge','m5.large','r5.large'] }],
  emr:        [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                 options: ['m5.xlarge','m5.2xlarge','c5.xlarge','r5.xlarge'] }],
  dms:        [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                 options: ['dms.t3.micro','dms.t3.medium','dms.c5.large'] }],
  rds: [
    { key: 'instanceType', label: 'Instance class', type: 'dropdown',
      options: ['db.t3.micro','db.t3.small','db.t3.medium','db.t3.large','db.r5.large','db.r5.xlarge'] },
    { key: 'engine', label: 'Engine', type: 'dropdown',
      options: ['postgresql','mysql','mariadb','oracle','sql-server','aurora-postgresql','aurora-mysql'] },
    { key: 'multiAz', label: 'Multi-AZ', type: 'toggle' },
  ],
  documentdb: [{ key: 'instanceType', label: 'Instance class', type: 'dropdown',
                 options: ['db.t3.medium','db.r5.large','db.r5.xlarge'] }],
  neptune:    [{ key: 'instanceType', label: 'Instance class', type: 'dropdown',
                 options: ['db.t3.medium','db.r5.large','db.r5.xlarge'] }],
  aurora:     [
    { key: 'instanceType', label: 'Instance class', type: 'dropdown',
      options: ['db.t3.medium','db.r5.large','db.r5.xlarge','db.r6g.large'] },
    { key: 'engine', label: 'Engine', type: 'dropdown',
      options: ['aurora-postgresql','aurora-mysql'] },
  ],
  'aurora-mysql':      [{ key: 'instanceType', label: 'Instance class', type: 'dropdown',
                          options: ['db.t3.medium','db.r5.large','db.r5.xlarge','db.r6g.large'] }],
  'aurora-postgresql': [{ key: 'instanceType', label: 'Instance class', type: 'dropdown',
                          options: ['db.t3.medium','db.r5.large','db.r5.xlarge','db.r6g.large'] }],
  elasticache: [{ key: 'nodeType', label: 'Node type', type: 'dropdown',
                  options: ['cache.t3.micro','cache.t3.small','cache.t3.medium','cache.m5.large','cache.r5.large'] }],
  opensearch:  [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                  options: ['t3.small.search','t3.medium.search','m5.large.search','r5.large.search'] }],
  redshift:    [{ key: 'nodeType', label: 'Node type', type: 'dropdown',
                  options: ['ra3.xlplus','ra3.4xlarge','dc2.large','dc2.8xlarge'] }],
  msk:         [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                  options: ['kafka.t3.small','kafka.m5.large','kafka.m5.xlarge','kafka.m5.4xlarge'] }],
  mq:          [{ key: 'instanceType', label: 'Instance type', type: 'dropdown',
                  options: ['mq.t3.micro','mq.m5.large'] }],
  lightsail:   [{ key: 'bundleId', label: 'Bundle', type: 'dropdown',
                  options: ['nano_3_0','micro_3_0','small_3_0','medium_3_0','large_3_0'] }],
  workspaces:  [{ key: 'bundleId', label: 'Bundle', type: 'dropdown',
                  options: ['standard','performance','power','powerpro'] }],
};

// ─── ServiceConfigSidebar ─────────────────────────────────────────────────────
function ServiceConfigSidebar({ serviceId, serviceType, attrs, onAttrChange, onClose }) {
  const fields = SERVICE_CONFIG_FIELDS[serviceType] ?? [];
  return (
    <div style={{
      width: 320, background: 'var(--surface, #fff)', borderLeft: '1px solid var(--line, #e0e0e0)',
      display: 'flex', flexDirection: 'column', flexShrink: 0,
    }}>
      <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--line, #e0e0e0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <span style={{ fontWeight: 600, fontSize: 14 }}>{serviceType ? serviceType.toUpperCase() : 'Service'}</span>
        <button className="btn" onClick={onClose} style={{ padding: '2px 8px' }}>×</button>
      </div>
      <div style={{ padding: 16, flex: 1, overflowY: 'auto' }}>
        {fields.length === 0 ? (
          <p style={{ color: 'var(--text-muted, #666)', fontSize: 13 }}>
            Uses standard cost assumptions — no configuration needed.
          </p>
        ) : fields.map(field => (
          <div key={field.key} style={{ marginBottom: 16 }}>
            <label style={{ display: 'block', fontSize: 12, fontWeight: 600, marginBottom: 4, color: 'var(--text-muted, #666)' }}>
              {field.label}
            </label>
            {field.type === 'dropdown' ? (
              <select
                value={attrs[field.key] ?? field.options[0]}
                onChange={e => onAttrChange(field.key, e.target.value)}
                style={{ width: '100%', padding: '6px 8px', border: '1px solid var(--line, #e0e0e0)', borderRadius: 4, fontSize: 13 }}
              >
                {field.options.map(opt => <option key={opt} value={opt}>{opt}</option>)}
              </select>
            ) : (
              <label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>
                <input
                  type="checkbox"
                  checked={!!attrs[field.key]}
                  onChange={e => onAttrChange(field.key, e.target.checked)}
                />
                <span style={{ fontSize: 13 }}>Enabled</span>
              </label>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── DrawioIframe ─────────────────────────────────────────────────────────────
function DrawioIframe({ drawioUrl, onSelectCell, onXmlReady, iframeRef }) {
  const handleMessage = useCallback(async (e) => {
    if (e.origin !== EMBED_ORIGIN) return;
    let msg;
    try { msg = JSON.parse(e.data); } catch { return; }

    if (msg.event === 'init') {
      try {
        const xml = await fetch(drawioUrl).then(r => {
          if (!r.ok) throw new Error(`draw.io XML fetch failed: ${r.status}`);
          return r.text();
        });
        iframeRef.current?.contentWindow?.postMessage(
          JSON.stringify({ action: 'load', xml }),
          EMBED_ORIGIN,
        );
      } catch (err) {
        console.error('[DiagramEditor] XML fetch failed', err);
      }
    } else if (msg.event === 'select') {
      onSelectCell(msg.ids?.[0] ?? null);
    } else if (msg.event === 'export' || msg.event === 'save') {
      // 'export' is the response to our { action: 'export' } request from Confirm.
      // 'save' fires when the user triggers the built-in save (Ctrl+S).
      // msg.xml contains the mxfile XML; msg.data is a base64 fallback.
      const xml = msg.xml ?? (msg.data ? atob(msg.data) : null);
      if (xml) onXmlReady(xml);
    } else if (msg.event === 'close') {
      // User clicked built-in close — treat as cancel by doing nothing
      // (parent's Cancel button is the authoritative close path).
    }
  }, [drawioUrl, onSelectCell, onXmlReady, iframeRef]);

  useEffect(() => {
    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [handleMessage]);

  return (
    <iframe
      ref={iframeRef}
      src={EMBED_URL}
      style={{ flex: 1, border: 'none', minWidth: 0 }}
      title="Diagram editor"
    />
  );
}

// ─── DiagramEditor ────────────────────────────────────────────────────────────
function DiagramEditor({ analysisId, drawioUrl, architecture, onConfirm, onCancel }) {
  const [selectedCellId, setSelectedCellId] = useState(null);
  const [serviceAttributes, setServiceAttributes] = useState({});
  const [status, setStatus] = useState('idle'); // 'idle' | 'saving' | 'error'
  const iframeRef = useRef(null);

  // Pre-populate from existing service.attributes so prior config isn't lost on re-edit
  useEffect(() => {
    if (!architecture?.services) return;
    const initial = {};
    for (const svc of architecture.services) {
      if (svc.attributes && Object.keys(svc.attributes).length > 0) {
        initial[svc.id] = svc.attributes;
      }
    }
    setServiceAttributes(initial);
  }, [architecture]);

  const selectedService = architecture?.services?.find(s => s.id === selectedCellId) ?? null;

  function handleAttrChange(key, value) {
    if (!selectedCellId) return;
    setServiceAttributes(prev => ({
      ...prev,
      [selectedCellId]: { ...(prev[selectedCellId] ?? {}), [key]: value },
    }));
  }

  function handleConfirm() {
    setStatus('saving');
    iframeRef.current?.contentWindow?.postMessage(
      JSON.stringify({ action: 'export', format: 'xml' }),
      EMBED_ORIGIN,
    );
  }

  async function handleXmlReady(xml) {
    try {
      const result = await window.API.updateArchitecture(analysisId, xml, serviceAttributes);
      setStatus('idle');
      onConfirm(result.architecture);
    } catch (err) {
      console.error('[DiagramEditor] update failed', err);
      setStatus('error');
    }
  }

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 1000,
      background: '#fff', display: 'flex', flexDirection: 'column',
    }}>
      {/* Header */}
      <div style={{
        height: 48, borderBottom: '1px solid var(--line, #e0e0e0)',
        display: 'flex', alignItems: 'center', padding: '0 16px',
        justifyContent: 'space-between', flexShrink: 0,
      }}>
        <span style={{ fontWeight: 600 }}>Edit Diagram</span>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          {status === 'error' && (
            <span style={{ color: 'red', fontSize: 12 }}>Save failed — try again</span>
          )}
          <button className="btn" onClick={onCancel} disabled={status === 'saving'}>
            Cancel
          </button>
          <button
            className="btn btn-primary"
            onClick={handleConfirm}
            disabled={status === 'saving'}
            style={{ fontWeight: 600 }}
          >
            {status === 'saving' ? 'Saving…' : '✓ Confirm'}
          </button>
        </div>
      </div>

      {/* Editor + sidebar */}
      <div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
        <DrawioIframe
          drawioUrl={drawioUrl}
          onSelectCell={setSelectedCellId}
          onXmlReady={handleXmlReady}
          iframeRef={iframeRef}
        />
        {selectedService && (
          <ServiceConfigSidebar
            serviceId={selectedCellId}
            serviceType={selectedService.type}
            attrs={serviceAttributes[selectedCellId] ?? {}}
            onAttrChange={handleAttrChange}
            onClose={() => setSelectedCellId(null)}
          />
        )}
      </div>
    </div>
  );
}

window.DiagramEditor = DiagramEditor;
