// JSON <-> YAML — bidirectional converter using js-yaml.

window.TOOL_HANDLERS['json-yaml'] = function JsonYamlTool() {
  const SAMPLE_JSON = JSON.stringify({
    project: 'MiniMagics',
    version: 2.1,
    features: ['privacy-first', 'no uploads', 'runs locally'],
    config: {
      theme: 'auto',
      maxFileSize: 52428800,
      enabled: true
    },
    authors: [
      { name: 'Alice', role: 'lead' },
      { name: 'Bob', role: 'contributor' }
    ]
  }, null, 2);

  const [json, setJson] = React.useState(SAMPLE_JSON);
  const [yaml, setYaml] = React.useState('');
  const [focus, setFocus] = React.useState('json');
  const [error, setError] = React.useState('');
  const [ready, setReady] = React.useState(false);
  const [copiedSide, setCopiedSide] = React.useState('');
  const timerRef = React.useRef(null);

  // Load js-yaml on mount
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        if (!window.jsyaml) {
          await window.loadScript('https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.min.js');
        }
        if (!cancelled) setReady(true);
      } catch (e) {
        if (!cancelled) setError('Failed to load js-yaml library.');
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // Initial conversion once library loads
  React.useEffect(() => {
    if (!ready) return;
    try {
      const parsed = JSON.parse(json);
      setYaml(window.jsyaml.dump(parsed, { indent: 2, lineWidth: -1 }));
      setError('');
    } catch (e) {
      setError(e.message);
    }
  }, [ready]);

  // Debounced conversion
  const convert = React.useCallback((source, value) => {
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => {
      if (!window.jsyaml) return;
      try {
        if (source === 'json') {
          if (!value.trim()) { setYaml(''); setError(''); return; }
          const parsed = JSON.parse(value);
          setYaml(window.jsyaml.dump(parsed, { indent: 2, lineWidth: -1 }));
        } else {
          if (!value.trim()) { setJson(''); setError(''); return; }
          const parsed = window.jsyaml.load(value);
          setJson(JSON.stringify(parsed, null, 2));
        }
        setError('');
      } catch (e) {
        setError(e.message);
      }
    }, 300);
  }, []);

  const onJsonChange = (e) => {
    const v = e.target.value;
    setJson(v);
    convert('json', v);
  };

  const onYamlChange = (e) => {
    const v = e.target.value;
    setYaml(v);
    convert('yaml', v);
  };

  const swap = () => {
    const oldJson = json;
    const oldYaml = yaml;
    setJson(oldYaml);
    setYaml(oldJson);
    setFocus(focus === 'json' ? 'yaml' : 'json');
    setError('');
  };

  const clear = () => {
    setJson('');
    setYaml('');
    setError('');
  };

  const formatJson = () => {
    try {
      const parsed = JSON.parse(json);
      const pretty = JSON.stringify(parsed, null, 2);
      setJson(pretty);
      setError('');
    } catch (e) {
      setError(e.message);
    }
  };

  const copy = (side) => {
    const text = side === 'json' ? json : yaml;
    navigator.clipboard.writeText(text);
    setCopiedSide(side);
    setTimeout(() => setCopiedSide(''), 1500);
  };

  const jsonKeys = React.useMemo(() => {
    try {
      const obj = JSON.parse(json);
      if (!obj || typeof obj !== 'object') return 0;
      const walk = (o) => {
        if (!o || typeof o !== 'object') return 0;
        if (Array.isArray(o)) return o.reduce((s, v) => s + walk(v), 0);
        return Object.keys(o).reduce((s, k) => s + 1 + walk(o[k]), 0);
      };
      return walk(obj);
    } catch { return 0; }
  }, [json]);

  const yamlKeys = React.useMemo(() => {
    try {
      const obj = window.jsyaml?.load(yaml);
      if (!obj || typeof obj !== 'object') return 0;
      const walk = (o) => {
        if (!o || typeof o !== 'object') return 0;
        if (Array.isArray(o)) return o.reduce((s, v) => s + walk(v), 0);
        return Object.keys(o).reduce((s, k) => s + 1 + walk(o[k]), 0);
      };
      return walk(obj);
    } catch { return 0; }
  }, [yaml]);

  const lineCount = (text) => text ? text.split('\n').length : 0;

  // Cleanup debounce timer on unmount
  React.useEffect(() => { return () => { if (timerRef.current) clearTimeout(timerRef.current); }; }, []);

  if (!ready && !error) {
    return (
      <div className="mini-tool" style={{ textAlign: 'center', padding: 40 }}>
        <window.LoadingCard label="Loading js-yaml..." />
      </div>
    );
  }

  const monoStyle = { minHeight: 280, fontFamily: 'var(--id-font-mono)', fontSize: 12, resize: 'vertical' };

  return (
    <div className="mini-tool">
      {/* Action bar */}
      <div className="cmp-actions" style={{ marginBottom: 14, justifyContent: 'center' }}>
        <button className="btn btn-secondary" onClick={swap}>
          <window.Icon name="swap" size={14} /> Swap
        </button>
        <button className="btn btn-secondary" onClick={formatJson}>
          Format JSON
        </button>
        <button className="btn btn-secondary" onClick={clear}>
          <window.Icon name="x" size={14} /> Clear
        </button>
      </div>

      {/* Side-by-side panels */}
      <div className="cmp-preview">
        {/* JSON panel */}
        <div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
            <label className="mini-label" style={{ margin: 0 }}>JSON</label>
            <button className="filter-pill" style={{ fontSize: 11, padding: '2px 10px', cursor: 'pointer' }} onClick={() => copy('json')}>
              <window.Icon name={copiedSide === 'json' ? 'check' : 'doc'} size={12} />
              {copiedSide === 'json' ? ' Copied' : ' Copy'}
            </button>
          </div>
          <textarea
            className="mini-input mini-textarea"
            style={monoStyle}
            value={json}
            onChange={onJsonChange}
            onFocus={() => setFocus('json')}
            placeholder="Paste JSON here..."
            spellCheck={false}
          />
          <div className="cmp-meta" style={{ marginTop: 4, fontSize: 11, color: 'var(--id-text-muted)' }}>
            {jsonKeys} keys &middot; {lineCount(json)} lines
          </div>
          {focus === 'json' && error && (
            <div style={{ marginTop: 6, fontSize: 12, color: 'var(--id-danger, #ef4444)' }}>{error}</div>
          )}
        </div>

        {/* YAML panel */}
        <div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
            <label className="mini-label" style={{ margin: 0 }}>YAML</label>
            <button className="filter-pill" style={{ fontSize: 11, padding: '2px 10px', cursor: 'pointer' }} onClick={() => copy('yaml')}>
              <window.Icon name={copiedSide === 'yaml' ? 'check' : 'doc'} size={12} />
              {copiedSide === 'yaml' ? ' Copied' : ' Copy'}
            </button>
          </div>
          <textarea
            className="mini-input mini-textarea"
            style={monoStyle}
            value={yaml}
            onChange={onYamlChange}
            onFocus={() => setFocus('yaml')}
            placeholder="Paste YAML here..."
            spellCheck={false}
          />
          <div className="cmp-meta" style={{ marginTop: 4, fontSize: 11, color: 'var(--id-text-muted)' }}>
            {yamlKeys} keys &middot; {lineCount(yaml)} lines
          </div>
          {focus === 'yaml' && error && (
            <div style={{ marginTop: 6, fontSize: 12, color: 'var(--id-danger, #ef4444)' }}>{error}</div>
          )}
        </div>
      </div>
    </div>
  );
};
