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 Stufe 1: Einheits-Normalisierung (kleine Fehler) ────────────
function fixByUnit(text) {
  const lines = text.split('\n').map(l => l.replace(/\t/g, '  '));
  const indents = lines
    .filter(l => l.trim() && !l.trim().startsWith('#'))
    .map(l => l.search(/\S/))
    .filter(n => n > 0);
  if (!indents.length) return text;
  const unit = Math.min(...indents);
  if (unit === 2) return lines.join('\n'); // bereits 2-space
  return lines.map(line => {
    if (!line.trim()) return '';
    if (line.trim().startsWith('#')) return line.trimEnd();
    const spaces = line.search(/\S/);
    if (spaces <= 0) return line.trimEnd();
    return '  '.repeat(Math.round(spaces / unit)) + line.trimStart().trimEnd();
  }).join('\n');
}

// ── YAML Auto-Fix Stufe 2: Stack-basiert (starke Schäden) ────────────────────
function fixByStack(text) {
  const lines = text.split('\n').map(l => l.replace(/\t/g, '  '));
  const stack = [{ indent: -1, depth: -1 }];
  const result = [];
  for (const line of lines) {
    if (!line.trim()) { result.push(''); continue; }
    const indent  = line.search(/\S/);
    const content = line.trim();
    if (content.startsWith('#')) {
      result.push('  '.repeat(Math.max(0, stack[stack.length-1].depth + 1)) + content);
      continue;
    }
    while (stack.length > 1 && stack[stack.length-1].indent >= indent) stack.pop();
    const depth = stack[stack.length-1].depth + 1;
    stack.push({ indent, depth });
    result.push('  '.repeat(depth) + content);
  }
  return result.join('\n');
}

function shortError(e) {
  const first = e.message.split('\n')[0];
  return first.length > 120 ? first.slice(0, 120) + '…' : first;
}

// ── 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; }

    const tryParse = (t) => { try { return { obj: jsyaml.load(t), err: null }; } catch(e) { return { obj: null, err: e }; } };

    // Stufe 1: direkt
    const r1 = tryParse(text);
    if (!r1.err) {
      setParsed(r1.obj); setFormatted(jsyaml.dump(r1.obj, {indent:2,lineWidth:-1,noRefs:true}));
      setError(''); setWarning(''); setCollapsed(new Set()); return;
    }

    // Stufe 2: Unit-Normalisierung (für kleine Fehler wie 4-space statt 2-space)
    const fixed1 = fixByUnit(text);
    const r2 = tryParse(fixed1);
    if (!r2.err) {
      setParsed(r2.obj); setFormatted(jsyaml.dump(r2.obj, {indent:2,lineWidth:-1,noRefs:true}));
      setWarning('✓ Einrückung normalisiert'); setError(''); setCollapsed(new Set()); return;
    }

    // Stufe 3: Stack-Fix (für stärker beschädigte Struktur)
    const fixed2 = fixByStack(text);
    const r3 = tryParse(fixed2);
    if (!r3.err) {
      setParsed(r3.obj); setFormatted(jsyaml.dump(r3.obj, {indent:2,lineWidth:-1,noRefs:true}));
      setWarning('⚠ Einrückung stark korrigiert – bitte Ergebnis prüfen'); setError(''); setCollapsed(new Set()); return;
    }

    // Stufe 4: best-effort – zeige korrigierten Text zum manuellen Nachbessern
    setError(shortError(r1.err));
    setWarning('Struktur nicht automatisch reparierbar – normalisierter Text zum manuellen Korrigieren:');
    setParsed(null);
    setFormatted(fixed2);
  }, []);

  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 && !formatted ? (
            <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: error ? 'rgba(255,230,109,0.07)' : 'rgba(78,205,196,0.07)',
                border:`1px solid ${error ? 'rgba(255,230,109,0.25)' : 'rgba(78,205,196,0.2)'}`,
                borderRadius:7,padding:'7px 12px',
                color: error ? '#ffe66d' : '#4ecdc4',
                fontFamily:'monospace',fontSize:10,lineHeight:1.6,marginBottom:8}}>
                {error ? '⚠ ' : '✓ '}{warning}
              </div>
            )}
            {error && formatted && (
              <div style={{background:'rgba(255,107,157,0.06)',border:'1px solid rgba(255,107,157,0.15)',
                borderRadius:7,padding:'6px 12px',color:'rgba(255,107,157,0.7)',
                fontFamily:'monospace',fontSize:9,lineHeight:1.6,marginBottom:8}}>
                ⚠ {error}
              </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>
  );
}
