import { useState, useCallback } from 'react';
import { S } from '../lib.js';
import jsyaml from 'js-yaml';

// ── YAML Tree Node (collapsible, mit Einrück-Linien) ─────────────────────────
function YamlNode({ data, depth = 0, keyName = null, collapsed, onToggle, path }) {
  const indent = depth * 18; // px pro Level
  const isObj  = data !== null && typeof data === 'object' && !Array.isArray(data);
  const isArr  = Array.isArray(data);
  const isLeaf = !isObj && !isArr;

  const nodeKey   = path;
  const isCollapsed = collapsed.has(nodeKey);
  const hasChildren = isObj || isArr;

  const keyColor   = '#7ecaff';
  const strColor   = '#ce9178';
  const numColor   = '#b5cea8';
  const boolColor  = '#569cd6';
  const nullColor  = '#808080';
  const indentColor= 'rgba(255,255,255,0.08)';

  const valueColor = (v) => {
    if (v === null || v === undefined) return nullColor;
    if (typeof v === 'boolean') return boolColor;
    if (typeof v === 'number') return numColor;
    return strColor;
  };

  const renderValue = (v) => {
    if (v === null) return <span style={{color:nullColor}}>null</span>;
    if (v === undefined) return <span style={{color:nullColor}}>~</span>;
    if (typeof v === 'boolean') return <span style={{color:boolColor}}>{String(v)}</span>;
    if (typeof v === 'number') return <span style={{color:numColor}}>{v}</span>;
    const s = String(v);
    // Quote strings that need it
    const needsQuotes = /[:#\[\]{}&*!|>'"%@`]/.test(s) || s.trim()!==s || s==='' || /^(true|false|null|yes|no|on|off)$/i.test(s);
    return <span style={{color:strColor}}>{needsQuotes ? `"${s.replace(/"/g,'\\"')}"` : s}</span>;
  };

  // Leaf: key: value
  if (isLeaf) {
    return (
      <div style={{display:'flex',alignItems:'baseline',minHeight:20,position:'relative'}}>
        {/* Vertical indent lines */}
        {Array.from({length:depth},(_,i)=>(
          <div key={i} style={{position:'absolute',left:i*18+6,top:0,bottom:0,
            borderLeft:`1px solid ${indentColor}`,pointerEvents:'none'}}/>
        ))}
        <div style={{paddingLeft:indent,fontFamily:"'Courier New',monospace",fontSize:12,lineHeight:1.7,whiteSpace:'pre-wrap',wordBreak:'break-all'}}>
          {keyName!==null&&<span style={{color:keyColor}}>{keyName}<span style={{color:'rgba(255,255,255,0.4)'}}>: </span></span>}
          {renderValue(data)}
        </div>
      </div>
    );
  }

  const count = isObj ? Object.keys(data).length : data.length;
  const summary = isObj ? `{${count}}` : `[${count}]`;

  return (
    <div style={{position:'relative'}}>
      {/* Vertical indent lines for this level */}
      {Array.from({length:depth},(_,i)=>(
        <div key={i} style={{position:'absolute',left:i*18+6,top:0,bottom:0,
          borderLeft:`1px solid ${indentColor}`,pointerEvents:'none'}}/>
      ))}

      {/* Header row */}
      <div style={{display:'flex',alignItems:'center',minHeight:20,cursor:hasChildren?'pointer':'default',
        paddingLeft:indent,userSelect:'none'}}
        onClick={()=>hasChildren&&onToggle(nodeKey)}>
        {hasChildren&&(
          <span style={{color:'rgba(255,255,255,0.4)',fontSize:9,marginRight:5,flexShrink:0,
            transform:isCollapsed?'rotate(-90deg)':'rotate(0)',display:'inline-block',transition:'transform 0.15s'}}>▼</span>
        )}
        <span style={{fontFamily:"'Courier New',monospace",fontSize:12,lineHeight:1.7}}>
          {keyName!==null&&<span style={{color:keyColor}}>{keyName}<span style={{color:'rgba(255,255,255,0.4)'}}>: </span></span>}
          {isCollapsed&&<span style={{color:'rgba(255,255,255,0.3)',fontSize:10}}>{summary}</span>}
          {!isCollapsed&&isArr&&<span style={{color:'rgba(255,255,255,0.25)',fontSize:10}}># {count} Einträge</span>}
        </span>
      </div>

      {/* Children */}
      {!isCollapsed && (
        <div>
          {isObj && Object.entries(data).map(([k,v],i)=>(
            <YamlNode key={k} data={v} depth={depth+1} keyName={k}
              collapsed={collapsed} onToggle={onToggle} path={`${path}.${k}`}/>
          ))}
          {isArr && data.map((v,i)=>(
            <div key={i} style={{position:'relative'}}>
              <div style={{position:'absolute',left:(depth)*18+6,top:10,width:8,
                borderTop:`1px solid ${indentColor}`}}/>
              <div style={{paddingLeft:(depth+1)*18,minHeight:20,display:'flex',alignItems:'baseline'}}>
                <span style={{color:'rgba(255,255,255,0.35)',fontFamily:"'Courier New',monospace",fontSize:12,
                  position:'absolute',left:(depth)*18+8}}>-</span>
                {typeof v === 'object' && v !== null
                  ? <YamlNode data={v} depth={depth+1} keyName={null}
                      collapsed={collapsed} onToggle={onToggle} path={`${path}[${i}]`}/>
                  : <div style={{fontFamily:"'Courier New',monospace",fontSize:12,lineHeight:1.7}}>
                      {v===null?<span style={{color:nullColor}}>null</span>:typeof v==='boolean'?<span style={{color:boolColor}}>{String(v)}</span>:typeof v==='number'?<span style={{color:numColor}}>{v}</span>:<span style={{color:strColor}}>{String(v)}</span>}
                    </div>
                }
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function collectPaths(data, path='root', paths=[]) {
  if (data !== null && typeof data === 'object') {
    paths.push(path);
    if (Array.isArray(data)) data.forEach((_,i)=>collectPaths(data[i],`${path}[${i}]`,paths));
    else Object.entries(data).forEach(([k,v])=>collectPaths(v,`${path}.${k}`,paths));
  }
  return paths;
}

// ── YAML Auto-Fix: normalisiert Einrückung bevor js-yaml parst ───────────────
function fixYamlIndentation(text) {
  const lines = text.split('\n');

  // 1. Tabs → Spaces (4 oder 2)
  const detabbed = lines.map(l => l.replace(/\t/g, '  '));

  // 2. Finde die kleinste vorkommende Einrückung > 0 (das ist die Einheit)
  const indents = detabbed
    .filter(l => l.trim() && !l.trim().startsWith('#'))
    .map(l => l.search(/\S/))
    .filter(n => n > 0);
  const unit = indents.length ? Math.min(...indents) : 2;

  // 3. Remap: jede Einrückung → Niveau * 2 Spaces
  const remapped = detabbed.map(line => {
    if (!line.trim()) return '';
    if (line.trim().startsWith('#')) return line.trimEnd();
    const spaces = line.search(/\S/);
    if (spaces <= 0) return line.trimEnd();
    const level = Math.round(spaces / unit);
    return '  '.repeat(level) + line.trimStart().trimEnd();
  });

  return remapped.join('\n');
}

// ── YAML Tool ─────────────────────────────────────────────────────────────────
function YamlTool({ mobile }) {
  const [input,    setInput]    = useState('');
  const [parsed,   setParsed]   = useState(null);
  const [formatted,setFormatted]= useState('');
  const [error,    setError]    = useState('');
  const [warning,  setWarning]  = useState('');
  const [copied,   setCopied]   = useState(false);
  const [view,     setView]     = useState('tree');
  const [collapsed,setCollapsed]= useState(new Set());

  const process = useCallback((text) => {
    if (!text.trim()) { setParsed(null); setFormatted(''); setError(''); setWarning(''); return; }
    
    let obj, parseError = null;

    // Versuch 1: direkt parsen
    try { obj = jsyaml.load(text); }
    catch(e) { parseError = e; }

    // Versuch 2: wenn Fehler → Auto-Fix, dann nochmal
    if (parseError) {
      try {
        const fixed = fixYamlIndentation(text);
        obj = jsyaml.load(fixed);
        setWarning(`⚠ Einrückung automatisch korrigiert: ${parseError.message.split('\n')[0]}`);
      } catch(e2) {
        // Fix hat auch nicht geholfen – originalen Fehler zeigen
        setError(parseError.message);
        setWarning('');
        setParsed(null); setFormatted('');
        return;
      }
    } else {
      setWarning('');
    }

    try {
      setParsed(obj);
      setFormatted(jsyaml.dump(obj, { indent:2, lineWidth:-1, noRefs:true }));
      setError('');
      setCollapsed(new Set());
    } catch(e) {
      setError(e.message);
      setParsed(null); setFormatted('');
    }
  },[]);

  const onInput = v => { setInput(v); process(v); };

  const copy = async () => {
    try { await navigator.clipboard.writeText(formatted); setCopied(true); setTimeout(()=>setCopied(false),1500); } catch {}
  };

  const toggleCollapse = path => {
    setCollapsed(prev => {
      const n = new Set(prev);
      n.has(path) ? n.delete(path) : n.add(path);
      return n;
    });
  };

  const collapseAll = () => { if(parsed) setCollapsed(new Set(collectPaths(parsed))); };
  const expandAll   = () => setCollapsed(new Set());

  const colCols = mobile ? '1fr' : '1fr 1fr';

  return (
    <div>
      <div style={{display:'grid',gridTemplateColumns:colCols,gap:12,marginBottom:10}}>
        {/* Input */}
        <div>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:6}}>
            <label style={{...S.head,marginBottom:0,fontSize:10}}>EINGABE</label>
            {input&&<button onClick={()=>{setInput('');setParsed(null);setFormatted('');setError('');}}
              style={{background:'transparent',border:'none',color:'rgba(255,255,255,0.3)',cursor:'pointer',fontFamily:'monospace',fontSize:10}}>✕</button>}
          </div>
          <textarea value={input} onChange={e=>onInput(e.target.value)}
            placeholder={'name: Beispiel\nversion: 1.0\nkonfiguration:\n  host: localhost\n  port: 8080\nliste:\n  - item1\n  - item2'}
            rows={mobile?10:18}
            style={{...S.inp,resize:'vertical',fontFamily:"'Courier New',monospace",fontSize:12,lineHeight:1.7,
              width:'100%',boxSizing:'border-box'}}/>
        </div>

        {/* Output */}
        <div>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:6,flexWrap:'wrap',gap:6}}>
            <label style={{...S.head,marginBottom:0,fontSize:10}}>ERGEBNIS</label>
            <div style={{display:'flex',gap:5,flexWrap:'wrap'}}>
              {/* View toggle */}
              {['tree','raw'].map(v=>(
                <button key={v} onClick={()=>setView(v)} style={{
                  padding:'2px 8px',borderRadius:5,fontFamily:'monospace',fontSize:9,cursor:'pointer',
                  background:view===v?'rgba(78,205,196,0.15)':'transparent',
                  border:`1px solid ${view===v?'rgba(78,205,196,0.3)':'rgba(255,255,255,0.1)'}`,
                  color:view===v?'#4ecdc4':'rgba(255,255,255,0.4)'}}>
                  {v==='tree'?'🌲 Baum':'📄 Raw'}
                </button>
              ))}
              {parsed&&view==='tree'&&<>
                <button onClick={collapseAll} style={{padding:'2px 8px',borderRadius:5,fontFamily:'monospace',fontSize:9,cursor:'pointer',background:'transparent',border:'1px solid rgba(255,255,255,0.1)',color:'rgba(255,255,255,0.4)'}}>− Alle</button>
                <button onClick={expandAll}   style={{padding:'2px 8px',borderRadius:5,fontFamily:'monospace',fontSize:9,cursor:'pointer',background:'transparent',border:'1px solid rgba(255,255,255,0.1)',color:'rgba(255,255,255,0.4)'}}>+ Alle</button>
              </>}
              {formatted&&<button onClick={copy} style={{
                padding:'2px 9px',borderRadius:5,fontFamily:'monospace',fontSize:9,cursor:'pointer',
                background:copied?'rgba(78,205,196,0.15)':'rgba(255,255,255,0.05)',
                border:`1px solid ${copied?'rgba(78,205,196,0.3)':'rgba(255,255,255,0.1)'}`,
                color:copied?'#4ecdc4':'rgba(255,255,255,0.5)'}}>
                {copied?'✓':'⎘'} Kopieren
              </button>}
            </div>
          </div>

          {error ? (
            <div style={{background:'rgba(255,107,157,0.08)',border:'1px solid rgba(255,107,157,0.2)',
              borderRadius:8,padding:14,color:'#ff6b9d',fontFamily:'monospace',fontSize:11,lineHeight:1.7}}>
              ⚠ {error}
            </div>
          ) : (<>
            {warning && (
              <div style={{background:'rgba(255,230,109,0.07)',border:'1px solid rgba(255,230,109,0.2)',
                borderRadius:7,padding:'7px 12px',color:'#ffe66d',fontFamily:'monospace',
                fontSize:10,lineHeight:1.6,marginBottom:8}}>
                {warning}
              </div>
            )}
            {view==='raw' ? (
            <pre style={{margin:0,padding:14,minHeight:200,background:'rgba(0,0,0,0.35)',
              border:'1px solid rgba(255,255,255,0.07)',borderRadius:8,
              color:formatted?'#d4e6b5':'rgba(255,255,255,0.15)',
              fontFamily:"'Courier New',monospace",fontSize:12,lineHeight:1.7,
              overflowX:'auto',whiteSpace:'pre',maxHeight:440,overflowY:'auto'}}>
              {formatted||'# Ergebnis erscheint hier'}
            </pre>
          ) : parsed!==null ? (
            <div style={{background:'rgba(0,0,0,0.35)',border:'1px solid rgba(255,255,255,0.07)',
              borderRadius:8,padding:'10px 10px 10px 12px',minHeight:200,maxHeight:440,overflowY:'auto',
              overflowX:'auto',position:'relative'}}>
              <YamlNode data={parsed} depth={0} keyName={null}
                collapsed={collapsed} onToggle={toggleCollapse} path="root"/>
            </div>
          ) : (
            <div style={{background:'rgba(0,0,0,0.2)',border:'1px solid rgba(255,255,255,0.06)',
              borderRadius:8,padding:30,textAlign:'center',color:'rgba(255,255,255,0.15)',
              fontFamily:'monospace',fontSize:11,minHeight:100,display:'flex',alignItems:'center',justifyContent:'center'}}>
              YAML eingeben → wird live formatiert
            </div>
          )}
          </>)}
        </div>
      </div>
      <div style={{color:'rgba(255,255,255,0.15)',fontFamily:'monospace',fontSize:9}}>
        Powered by js-yaml · 2-Space-Einrückung · YAML 1.2 kompatibel
      </div>
    </div>
  );
}

// ── Tool-Definitionen ─────────────────────────────────────────────────────────
const TOOL_DEFS = [
  { id:'yaml',      label:'📄 YAML Formatter',  desc:'YAML korrekt einrücken und formatieren',     ready:true, component:YamlTool },
  { id:'json',      label:'{ } JSON Formatter', desc:'JSON formatieren und validieren',             ready:false },
  { id:'base64',    label:'🔐 Base64',           desc:'Text ↔ Base64 kodieren/dekodieren',           ready:false },
  { id:'regex',     label:'🔍 Regex Tester',     desc:'Reguläre Ausdrücke live testen',             ready:false },
  { id:'diff',      label:'± Text Diff',        desc:'Zwei Texte vergleichen',                     ready:false },
  { id:'jwt',       label:'🔑 JWT Decoder',      desc:'JSON Web Tokens dekodieren',                 ready:false },
  { id:'timestamp', label:'🕐 Timestamp',        desc:'Unix Timestamps umrechnen',                  ready:false },
  { id:'color',     label:'🎨 Farben',           desc:'HEX ↔ RGB ↔ HSL umrechnen',                 ready:false },
];

export default function DevTools({ toast, mobile }) {
  const [activeTool, setActiveTool] = useState('yaml');
  const active = TOOL_DEFS.find(t=>t.id===activeTool);

  return (
    <div style={{padding:mobile?'14px 14px 90px':'36px 44px',maxWidth:1100}}>
      <div style={{display:'flex',alignItems:'center',gap:12,marginBottom:20,flexWrap:'wrap'}}>
        <h1 style={{color:'#fff',fontFamily:"'Space Mono',monospace",fontSize:mobile?17:22,margin:0}}>Dev-Tools</h1>
        <span style={{color:'rgba(255,255,255,0.25)',fontFamily:'monospace',fontSize:10}}>Konverter · Formatter · Helfer</span>
      </div>

      <div style={{display:'flex',gap:8,flexWrap:'wrap',marginBottom:20}}>
        {TOOL_DEFS.map(t=>(
          <button key={t.id}
            onClick={()=>t.ready ? setActiveTool(t.id) : toast('Kommt bald 🚧','error')}
            title={t.desc}
            style={{
              padding:'8px 14px',borderRadius:10,fontFamily:'monospace',fontSize:11,cursor:t.ready?'pointer':'default',
              background: activeTool===t.id?'#4ecdc4':t.ready?'rgba(255,255,255,0.06)':'rgba(255,255,255,0.02)',
              color:       activeTool===t.id?'#0d0d0f':t.ready?'rgba(255,255,255,0.65)':'rgba(255,255,255,0.2)',
              border:      activeTool===t.id?'none':t.ready?'1px solid rgba(255,255,255,0.1)':'1px solid rgba(255,255,255,0.05)',
              fontWeight:  activeTool===t.id?700:400,
            }}>
            {t.label}{!t.ready&&<span style={{marginLeft:4,fontSize:8,opacity:0.5}}>bald</span>}
          </button>
        ))}
      </div>

      <div style={{...S.card}}>
        <div style={{display:'flex',alignItems:'baseline',gap:10,marginBottom:14}}>
          <div style={{...S.head,marginBottom:0}}>{active?.label}</div>
          <span style={{color:'rgba(255,255,255,0.25)',fontFamily:'monospace',fontSize:10}}>{active?.desc}</span>
        </div>
        {active?.component && <active.component toast={toast} mobile={mobile}/>}
      </div>
    </div>
  );
}
