import { useState, useEffect, useRef, useCallback } from 'react';
import { api, S } from './lib.js';
import { TOOLS, getGroupedTools } from './toolRegistry.js';
import CalendarWidget, { CalendarSettings } from './calendar.jsx';
import { DateiSettings } from './tools/dateien.jsx';
import { useConfirm } from './confirm.jsx';
import { HomeIcon, AppsIcon, AdminIcon, MoreIcon, UserIcon, LogOutIcon, ChevronIcon, UpdateIcon, TrashIcon } from './icons.jsx';

const ICONS = ['🔗','🌐','📊','📁','🛠','📧','🗓','💾','🖥','📡','🔒','📖','🎯','⚡','🏠','🔧','📱','🎮','🚀','💡'];

// ── Responsive Hook ───────────────────────────────────────────────────────────
function useIsMobile() {
  const [mobile, setMobile] = useState(window.innerWidth < 768);
  useEffect(() => {
    // Nur auf Breite reagieren, nicht auf Keyboard-Open (Höhenänderung)
    const fn = () => {
      const isMob = window.innerWidth < 768;
      setMobile(prev => prev === isMob ? prev : isMob);
    };
    window.addEventListener('resize', fn);
    return () => window.removeEventListener('resize', fn);
  }, []);
  return mobile;
}

// ── Toast ─────────────────────────────────────────────────────────────────────
function Toast({ msg, type }) {
  if (!msg) return null;
  const c = type === 'error' ? '#ff6b9d' : '#4ecdc4';
  return (
    <div style={{ position:'fixed', bottom:80, right:16, zIndex:9999, background:'#1a1a1e',
      border:`1px solid ${c}55`, borderRadius:10, padding:'10px 16px',
      color:c, fontFamily:'monospace', fontSize:12, animation:'fadeIn 0.2s ease',
      boxShadow:`0 4px 24px ${c}22`, maxWidth:'calc(100vw - 32px)' }}>
      {type==='error'?'✕ ':'✓ '}{msg}
    </div>
  );
}

// ── Modal ─────────────────────────────────────────────────────────────────────
function Modal({ title, onClose, children }) {
  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.8)', zIndex:5000,
      display:'flex',
      alignItems: window.innerWidth>=768 ? 'center' : 'flex-end',
      justifyContent:'center', padding: window.innerWidth>=768 ? 24 : 0 }}
      onClick={e=>e.target===e.currentTarget&&onClose()}>
      <div style={{ background:'#1a1a1e', border:'1px solid rgba(255,255,255,0.15)',
        borderRadius: window.innerWidth>=768 ? 16 : '16px 16px 0 0',
        padding:'20px 20px 40px', width:'100%',
        maxWidth:600, maxHeight:'85vh', overflowY:'auto',
        boxShadow: window.innerWidth>=768 ? '0 24px 80px rgba(0,0,0,0.6)' : 'none' }}>
      {window.innerWidth < 768 && <div style={{ width:36, height:4, background:'rgba(255,255,255,0.2)', borderRadius:2, margin:'0 auto 20px' }}/>}
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:18 }}>
          <span style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:14, fontWeight:700 }}>{title}</span>
          <button onClick={onClose} style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.4)', fontSize:20, cursor:'pointer', padding:'0 4px' }}>✕</button>
        </div>
        {children}
      </div>
    </div>
  );
}

// ── PWA Splash Screen ─────────────────────────────────────────────────────────
function SplashScreen({ onDone }) {
  const [fade, setFade] = useState(false);
  useEffect(() => {
    const t1 = setTimeout(() => setFade(true), 1200);
    const t2 = setTimeout(() => onDone(), 1700);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);
  return (
    <div style={{
      position:'fixed', inset:0, background:'#0d0d0f',
      display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
      zIndex:99999, transition:'opacity 0.5s ease',
      opacity: fade ? 0 : 1, pointerEvents: fade ? 'none' : 'auto',
    }}>
      <div style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:22, fontWeight:700, marginBottom:24, letterSpacing:2 }}>
        DICKEN<span style={{color:'#4ecdc4'}}>DOCK</span>
      </div>
      <div style={{
        width:72, height:72, background:'linear-gradient(135deg,#4ecdc4,#ff6b9d)',
        borderRadius:18, display:'flex', alignItems:'center', justifyContent:'center', fontSize:36,
      }}>⚒</div>
    </div>
  );
}

// ── Login ─────────────────────────────────────────────────────────────────────
function Login({ onLogin }) {
  const [u,setU]=useState(''); const [p,setP]=useState('');
  const [err,setErr]=useState(''); const [busy,setBusy]=useState(false);
  const go = async () => {
    setErr(''); setBusy(true);
    try { const d=await api('/auth/login',{body:{username:u,password:p}}); localStorage.setItem('sk_token',d.token); onLogin(d.user); }
    catch(e) { setErr(e.message); } finally { setBusy(false); }
  };
  return (
    <div style={{
      position:'fixed', inset:0,
      background:'#0d0d0f',
      display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      padding:'24px 20px', overflow:'hidden',
    }}>
      <div style={{ width:'100%', maxWidth:340 }}>
        <div style={{ textAlign:'center', marginBottom:36 }}>
          <div style={{ width:56, height:56, background:'linear-gradient(135deg,#4ecdc4,#ff6b9d)',
            borderRadius:14, display:'flex', alignItems:'center', justifyContent:'center',
            fontSize:26, margin:'0 auto 14px' }}>⚒</div>
          <div style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:20, fontWeight:700 }}>
            DICKEN<span style={{ color:'#4ecdc4' }}>DOCK</span>
          </div>
        </div>
        {[['BENUTZERNAME',u,setU,'text'],['PASSWORT',p,setP,'password']].map(([l,v,s,t])=>(
          <div key={l} style={{ marginBottom:14 }}>
            <label style={{ ...S.head, display:'block', marginBottom:5 }}>{l}</label>
            <input type={t} value={v} onChange={e=>s(e.target.value)}
              onKeyDown={e=>e.key==='Enter'&&go()}
              style={{ ...S.inp, fontSize:16, padding:'13px 14px', borderRadius:10,
                border:'1px solid rgba(255,255,255,0.12)' }}
              autoCapitalize="none" autoCorrect="off" />
          </div>
        ))}
        {err && <div style={{ color:'#ff6b9d', fontSize:12, fontFamily:'monospace', marginBottom:12, textAlign:'center' }}>✕ {err}</div>}
        <button onClick={go} disabled={busy} style={{
          width:'100%', background:'linear-gradient(135deg,#4ecdc4,#45b7d1)', border:'none',
          borderRadius:12, padding:'15px 0', color:'#0d0d0f',
          fontFamily:"'Space Mono',monospace", fontWeight:700, fontSize:15,
          cursor:busy?'default':'pointer', opacity:busy?0.7:1, marginTop:6,
        }}>{busy?'…':'Einloggen →'}</button>
      </div>
    </div>
  );
}

// ── Update Modal ──────────────────────────────────────────────────────────────
function UpdateModal({ data, onClose }) {
  return (
    <Modal title="📦 Update verfügbar" onClose={onClose}>
      <div style={{ marginBottom:14, padding:'8px 12px', background:'rgba(255,230,109,0.06)',
        border:'1px solid rgba(255,230,109,0.2)', borderRadius:8 }}>
        <span style={{ color:'rgba(255,255,255,0.5)', fontSize:12, fontFamily:'monospace' }}>
          Installiert: <span style={{ color:'#4ecdc4' }}>{data.currentVersion}</span>
          {' → '}<span style={{ color:'#ffe66d' }}>{data.latestVersion}</span>
        </span>
      </div>
      {(data.releases||[]).map((r,i)=>(
        <div key={i} style={{ marginBottom:12, padding:'12px 14px',
          background:i===0?'rgba(78,205,196,0.05)':'rgba(255,255,255,0.02)',
          border:`1px solid ${i===0?'rgba(78,205,196,0.2)':'rgba(255,255,255,0.05)'}`, borderRadius:8 }}>
          <div style={{ display:'flex', justifyContent:'space-between', marginBottom:6 }}>
            <span style={{ color:i===0?'#4ecdc4':'#fff', fontFamily:"'Space Mono',monospace", fontSize:13, fontWeight:700 }}>{r.name||r.version}</span>
            <span style={{ color:'rgba(255,255,255,0.3)', fontSize:10, fontFamily:'monospace' }}>
              {r.publishedAt?new Date(r.publishedAt).toLocaleDateString('de-DE'):''}
            </span>
          </div>
          <pre style={{ color:'rgba(255,255,255,0.5)', fontSize:12, fontFamily:'monospace', whiteSpace:'pre-wrap', lineHeight:1.6, margin:0 }}>{r.body}</pre>
        </div>
      ))}
      <div style={{ color:'rgba(255,255,255,0.55)', fontSize:11, fontFamily:'monospace', marginTop:8, lineHeight:1.8 }}>
        Update: <code style={{ color:'#4ecdc4' }}>docker compose up -d --build</code>
      </div>
    </Modal>
  );
}

// ── Desktop Sidebar ───────────────────────────────────────────────────────────
function Sidebar({ active, setActive, user, onLogout, updateInfo, onUpdateClick }) {
  const [appsOpen, setAppsOpen] = useState(true);
  const [collapsed, setCollapsed] = useState(false);

  const NavBtn = ({ item, sub=false }) => {
    const ic = active===item.id ? '#4ecdc4' : 'rgba(255,255,255,0.55)';
    return (
      <button onClick={()=>setActive(item.id)} title={collapsed ? item.label : undefined} style={{
        width:'100%', display:'flex', alignItems:'center', gap:9,
        padding: collapsed ? '8px 0' : '8px 12px',
        justifyContent: collapsed ? 'center' : 'flex-start',
        borderRadius:7, border:'none',
        background: active===item.id ? 'linear-gradient(90deg,rgba(78,205,196,0.14),rgba(78,205,196,0.02))' : 'transparent',
        cursor:'pointer', fontSize:12,
        fontFamily:"'Space Mono',monospace", textAlign:'left', marginBottom:1,
        borderLeft: active===item.id ? '2px solid #4ecdc4' : '2px solid transparent',
      }}>
        {!collapsed && sub && <span style={{ width:1, alignSelf:'stretch', background:'rgba(255,255,255,0.08)', marginRight:3, flexShrink:0 }}/>}
        <span style={{ display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
          {item.Icon ? (() => { const I = item.Icon; return <I size={collapsed?18:15} color={ic}/>; })() : <span style={{color:ic,fontSize:collapsed?16:13}}>{item.icon}</span>}
        </span>
        {!collapsed && <span style={{ flex:1, color:ic }}>{item.label}</span>}
      </button>
    );
  };

  return (
    <aside style={{ width:collapsed?56:210, minHeight:'100vh', background:'#0d0d0f',
      borderRight:'1px solid rgba(255,255,255,0.06)', display:'flex', flexDirection:'column', flexShrink:0,
      transition:'width 0.2s ease', overflow:'hidden', position:'relative' }}>
      <div style={{ padding:'12px 8px', borderBottom:'1px solid rgba(255,255,255,0.06)', marginBottom:8 }}>
        {collapsed ? (
          <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:8 }}>
            <div style={{ width:30, height:30, background:'linear-gradient(135deg,#4ecdc4,#ff6b9d)',
              borderRadius:7, display:'flex', alignItems:'center', justifyContent:'center', fontSize:14 }}>⚒</div>
            <button onClick={()=>setCollapsed(false)} style={{
              background:'rgba(78,205,196,0.2)', border:'1px solid rgba(78,205,196,0.5)',
              borderRadius:6, color:'#4ecdc4', cursor:'pointer', padding:'4px 6px',
              fontSize:14, lineHeight:1, fontWeight:700, width:'100%' }}>›</button>
          </div>
        ) : (
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <div style={{ width:30, height:30, background:'linear-gradient(135deg,#4ecdc4,#ff6b9d)',
              borderRadius:7, display:'flex', alignItems:'center', justifyContent:'center', fontSize:14, flexShrink:0 }}>⚒</div>
            <div style={{flex:1,minWidth:0}}>
              <div style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:13, fontWeight:700, whiteSpace:'nowrap' }}>
                DICKEN<span style={{ color:'#4ecdc4' }}>DOCK</span>
              </div>
            </div>
            <button onClick={()=>setCollapsed(true)} style={{
              background:'rgba(78,205,196,0.15)', border:'1px solid rgba(78,205,196,0.4)',
              borderRadius:6, color:'#4ecdc4', cursor:'pointer', padding:'4px 8px', flexShrink:0,
              fontSize:14, lineHeight:1, fontWeight:700 }}>‹</button>
          </div>
        )}
      </div>
      <nav style={{ flex:1, padding:'0 8px' }}>
        <NavBtn item={{ id:'dashboard', Icon:HomeIcon, label:'Dashboard' }} />

        {/* Apps Sektion mit Gruppenüberschriften */}
        <button onClick={()=>setAppsOpen(v=>!v)} title={collapsed?'Apps':undefined} style={{
          width:'100%', display:'flex', alignItems:'center', gap:9,
          padding: collapsed ? '9px 0' : '9px 12px',
          justifyContent: collapsed ? 'center' : 'flex-start',
          borderRadius:7, border:'none', background:'transparent',
          cursor:'pointer', fontSize:12,
          fontFamily:"'Space Mono',monospace", textAlign:'left', marginBottom:1,
          borderLeft:'2px solid transparent',
        }}>
          <AppsIcon size={collapsed?18:15} color="rgba(255,255,255,0.6)"/>
          {!collapsed && <span style={{ flex:1, color:'rgba(255,255,255,0.65)' }}>Apps</span>}
          {!collapsed && <ChevronIcon size={13} color="rgba(255,255,255,0.35)" dir={appsOpen?'down':'right'}/>}
        </button>
        {appsOpen && getGroupedTools().map(([group, tools]) => (
          <div key={group}>
            {!collapsed && <div style={{ color:'rgba(78,205,196,0.85)', fontSize:9, fontFamily:'monospace',
              letterSpacing:2, padding:'8px 12px 3px 12px' }}>{group.toUpperCase()}</div>}
            {tools.map(t => <NavBtn key={t.id} item={t} sub />)}
          </div>
        ))}

        <NavBtn item={{ id:'admin', Icon:AdminIcon, label:'Einstellungen' }} />
      </nav>
      {updateInfo?.hasUpdate && (
        <button onClick={onUpdateClick} style={{
          margin:'0 8px 8px', background:'rgba(255,230,109,0.08)',
          border:'1px solid rgba(255,230,109,0.3)', borderRadius:8,
          padding:'8px 12px', cursor:'pointer', display:'flex', alignItems:'center', gap:8,
        }}>
          <span style={{ width:7, height:7, borderRadius:'50%', background:'#ffe66d', flexShrink:0, boxShadow:'0 0 6px #ffe66d', display:'inline-block' }} />
          <span style={{ color:'#ffe66d', fontSize:11, fontFamily:'monospace' }}>Update</span>
          <span style={{ color:'rgba(255,230,109,0.5)', fontSize:10, fontFamily:'monospace', marginLeft:'auto' }}>{updateInfo.latestVersion}</span>
        </button>
      )}
      <div style={{ padding:'10px 12px 16px', borderTop:'1px solid rgba(255,255,255,0.06)' }}>
        {!collapsed && <><div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
          <div style={{ width:24, height:24, borderRadius:'50%', background:'linear-gradient(135deg,#ff6b9d,#4ecdc4)',
            display:'flex', alignItems:'center', justifyContent:'center', overflow:'hidden', flexShrink:0 }}>
            {localStorage.getItem('dd_avatar')
              ? <img src={localStorage.getItem('dd_avatar')} style={{width:'100%',height:'100%',objectFit:'cover'}} alt=""/>
              : <UserIcon size={14} color="#0d0d0f"/>}
          </div>
          <div style={{ color:'#fff', fontSize:11, fontFamily:'monospace' }}>{user?.username}</div>
        </div>
        <button onClick={onLogout} style={{ ...S.btn('#ff6b9d',true), width:'100%', textAlign:'center' }}>Ausloggen</button></>}
        {collapsed && <button onClick={onLogout} title="Ausloggen" style={{ background:'transparent', border:'none', cursor:'pointer', padding:'4px', width:'100%', display:'flex', justifyContent:'center' }}><LogOutIcon size={18} color="rgba(255,107,157,0.7)"/></button>}
      </div>
    </aside>
  );
}

// ── Mobile Bottom Navigation ──────────────────────────────────────────────────
function BottomNav({ active, setActive, user, onLogout, updateInfo, onUpdateClick }) {
  const [menuOpen, setMenuOpen] = useState(false);
  const [appsOpen, setAppsOpen] = useState(false);
  const NAV_H = 56;

  const MI = ({Icon, icon, label, onClick, color='rgba(255,255,255,0.85)'}) => {
    const Ic = Icon;
    return (
      <button onClick={onClick} style={{ width:'100%', padding:'11px 20px', background:'transparent',
        border:'none', display:'flex', alignItems:'center', gap:12, cursor:'pointer' }}>
        <span style={{flexShrink:0, width:22, display:'flex', alignItems:'center', justifyContent:'center'}}>
          {Ic ? <Ic size={18} color={color}/> : <span style={{fontSize:17, color}}>{icon}</span>}
        </span>
        <span style={{color, fontFamily:'monospace', fontSize:13}}>{label}</span>
      </button>
    );
  };

  const Sheet = ({open, onClose, children}) => {
    if (!open) return null;
    const isDesktop = window.innerWidth >= 768;
    if (isDesktop) return (
      <div style={{ position:'fixed', inset:0, zIndex:4000, background:'rgba(0,0,0,0.6)',
        display:'flex', alignItems:'center', justifyContent:'center', padding:24 }}
        onClick={onClose}>
        <div style={{ background:'#1a1a1e', border:'1px solid rgba(255,255,255,0.15)',
          borderRadius:16, padding:'20px 0', width:'100%', maxWidth:380,
          boxShadow:'0 24px 80px rgba(0,0,0,0.6)' }}
          onClick={e=>e.stopPropagation()}>
          {children}
        </div>
      </div>
    );
    return (
      <div style={{ position:'fixed', inset:0, zIndex:4000, background:'rgba(0,0,0,0.6)' }}
        onClick={onClose}>
        <div style={{ position:'absolute', bottom:`calc(${NAV_H}px + env(safe-area-inset-bottom, 0px))`,
          left:0, right:0, background:'#1a1a1e',
          borderTop:'1px solid rgba(255,255,255,0.1)',
          borderRadius:'16px 16px 0 0', paddingTop:8 }}
          onClick={e=>e.stopPropagation()}>
          <div style={{ width:36, height:4, background:'rgba(255,255,255,0.15)', borderRadius:2, margin:'0 auto 10px' }}/>
          {children}
          <div style={{height:'env(safe-area-inset-bottom, 0px)'}}/>
        </div>
      </div>
    );
  };

  const mainNav = [
    { id:'dashboard', Icon:HomeIcon,  label:'Home' },
    { id:'_apps',     Icon:AppsIcon,  label:'Apps'  },
    { id:'admin', Icon:AdminIcon, label:'Einst.' },
    { id:'_mehr',     Icon:MoreIcon,  label:'Mehr'  },
  ];

  return (
    <>
      {/* Apps Sheet mit Gruppenüberschriften */}
      <Sheet open={appsOpen} onClose={()=>setAppsOpen(false)}>
        <div style={{ paddingBottom:4 }}>
          {getGroupedTools().map(([group, tools]) => (
            <div key={group}>
              <div style={{ color:'rgba(78,205,196,0.85)', fontSize:9, fontFamily:'monospace',
                letterSpacing:2, padding:'12px 20px 5px' }}>{group.toUpperCase()}</div>
              {tools.map(t => (
                <MI key={t.id} Icon={t.Icon} label={t.label}
                  onClick={() => { setActive(t.id); setAppsOpen(false); }} />
              ))}
            </div>
          ))}
        </div>
      </Sheet>

      {/* Mehr Sheet */}
      <Sheet open={menuOpen} onClose={()=>setMenuOpen(false)}>
        {updateInfo?.hasUpdate && <MI Icon={UpdateIcon} label={`Update: ${updateInfo.latestVersion}`} onClick={()=>{setMenuOpen(false);onUpdateClick();}} color="#ffe66d"/>}
        <div style={{height:1, background:'rgba(255,255,255,0.08)', margin:'4px 0'}}/>
        <MI Icon={UserIcon} label={user?.username||''} onClick={()=>{}} color="rgba(255,255,255,0.35)"/>
        <MI Icon={LogOutIcon} label="Ausloggen" onClick={()=>{onLogout();setMenuOpen(false);}} color="#ff6b9d"/>
      </Sheet>

      {/* Bottom Bar */}
      <nav style={{ position:'fixed', bottom:0, left:0, right:0, zIndex:3000,
        background:'#0d0d0f', borderTop:'1px solid rgba(255,255,255,0.12)' }}>
        <div style={{ display:'flex', height:NAV_H }}>
          {mainNav.map(item => {
            const isApps = item.id === '_apps';
            const isMehr = item.id === '_mehr';
            const isActive = isApps ? appsOpen : isMehr ? menuOpen : active === item.id;
            return (
              <button key={item.id}
                onClick={() => {
                  if (isApps) { setAppsOpen(v=>!v); setMenuOpen(false); }
                  else if (isMehr) { setMenuOpen(v=>!v); setAppsOpen(false); }
                  else { setActive(item.id); setAppsOpen(false); setMenuOpen(false); }
                }}
                style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center',
                  justifyContent:'center', gap:3, background:'transparent', border:'none',
                  cursor:'pointer', position:'relative', minWidth:0, padding:'0 4px' }}>
                {isMehr && updateInfo?.hasUpdate && (
                  <span style={{ position:'absolute', top:6, right:'calc(50% - 16px)',
                    width:8, height:8, borderRadius:'50%', background:'#ffe66d',
                    boxShadow:'0 0 6px #ffe66d', display:'inline-block' }} />
                )}
                {(() => { const I = item.Icon; return I ? <I size={20} color={isActive ? '#4ecdc4' : 'rgba(255,255,255,0.45)'}/> : null; })()}
                <span style={{ fontSize:9, fontFamily:'monospace', letterSpacing:0.3,
                  color: isActive ? '#4ecdc4' : 'rgba(255,255,255,0.4)' }}>{item.label}</span>
                {isActive && !isApps && !isMehr && (
                  <span style={{ position:'absolute', top:0, left:'50%', transform:'translateX(-50%)',
                    width:24, height:2, background:'#4ecdc4', borderRadius:'0 0 3px 3px' }} />
                )}
              </button>
            );
          })}
        </div>
        <div style={{ height:'env(safe-area-inset-bottom, 0px)', background:'#0d0d0f' }}/>
      </nav>
    </>
  );
}


// ── Dashboard Widgets ─────────────────────────────────────────────────────────
function QuickLinks({ toast, mobile }) {
  const { confirm, ConfirmDialog } = useConfirm();
  const [links,   setLinks]   = useState([]);
  const [editMode, setEdit]   = useState(false);
  const [showForm, setForm]   = useState(false);
  const [form,     setF]      = useState({ title:'', url:'', icon:'🔗' });
  const [editId,   setEditId] = useState(null);

  useEffect(() => { api('/dashboard/links').then(setLinks).catch(() => {}); }, []);

  const getFavicon = url => {
    try { return `https://www.google.com/s2/favicons?sz=64&domain=${new URL(url).hostname}`; }
    catch { return null; }
  };

  const save = async () => {
    if (!form.title.trim() || !form.url.trim()) { toast('Titel und URL erforderlich', 'error'); return; }
    let url = form.url.trim();
    if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
    // Auto favicon if user left default
    const icon = form.icon === '🔗' ? (getFavicon(url) || '🔗') : form.icon;
    try {
      if (editId) {
        const u = await api(`/dashboard/links/${editId}`, { method:'PUT', body:{...form, icon, url} });
        setLinks(p => p.map(l => l.id===editId ? u : l));
      } else {
        const n = await api('/dashboard/links', { body:{...form, icon, url} });
        setLinks(p => [...p, n]);
      }
      toast(editId ? 'Aktualisiert' : 'Gespeichert');
      setF({ title:'', url:'', icon:'🔗' }); setForm(false); setEditId(null);
    } catch(e) { toast(e.message, 'error'); }
  };

  const del = async id => {
    if (!await confirm('Link wirklich löschen?')) return;
    try { await api(`/dashboard/links/${id}`, { method:'DELETE' }); setLinks(p => p.filter(l => l.id!==id)); toast('Gelöscht'); }
    catch(e) { toast(e.message, 'error'); }
  };

  return (
    <div style={{ ...S.card, marginBottom:10 }}>
      <ConfirmDialog/>
      <div style={{ marginBottom:10 }}>
        <div style={S.head}>SCHNELLZUGRIFF</div>
      </div>

      {/* Link-Grid */}
      {links.length === 0 && !editMode
        ? <div style={{ color:'rgba(255,255,255,0.5)', fontSize:11, fontFamily:'monospace', padding:'6px 0' }}>Links können unter Einstellungen → Dashboard hinzugefügt werden.</div>
        : <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
            {links.map(l => (
              <div key={l.id} style={{ position:'relative' }}>

                <a href={l.url} target="_blank" rel="noopener noreferrer"
                  
                  style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:4,
                    padding:'10px 14px', background:'rgba(255,255,255,0.04)',
                    border:'1px solid rgba(255,255,255,0.08)', borderRadius:10,
                    textDecoration:'none', minWidth:60, cursor:'pointer' }}>
                  {l.icon && l.icon.startsWith('http')
                    ? <img src={l.icon} alt="" style={{width:26,height:26,objectFit:'contain'}} onError={e=>e.target.style.display='none'}/>
                    : <span style={{ fontSize:26 }}>{l.icon}</span>}
                  <span style={{ color:'rgba(255,255,255,0.65)', fontSize:9, fontFamily:'monospace',
                    maxWidth:64, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{l.title}</span>
                </a>
              </div>
            ))}
          </div>
      }

      {/* Formular */}
      {showForm && (
        <div style={{ marginTop:12, padding:12, background:'rgba(0,0,0,0.25)', border:'1px solid rgba(255,255,255,0.06)', borderRadius:10 }}>
          {/* Icon-Picker */}
          <div style={{ marginBottom:10 }}>
            <div style={{ ...S.head, marginBottom:6 }}>ICON</div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:5 }}>
              {ICONS.map(ic => (
                <button key={ic} onClick={() => setF(f => ({...f, icon:ic}))} style={{
                  width:36, height:36, borderRadius:7, fontSize:18, cursor:'pointer',
                  border:`1px solid ${form.icon===ic ? '#4ecdc4' : 'rgba(255,255,255,0.1)'}`,
                  background: form.icon===ic ? 'rgba(78,205,196,0.15)' : 'rgba(255,255,255,0.04)',
                }}>{ic}</button>
              ))}
            </div>
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8, marginBottom:10 }}>
            <div>
              <label style={{ ...S.head, display:'block', marginBottom:3 }}>TITEL</label>
              <input value={form.title} onChange={e => setF(f => ({...f, title:e.target.value}))}
                style={{ ...S.inp, fontSize:16 }} placeholder="Mein Link" />
            </div>
            <div>
              <label style={{ ...S.head, display:'block', marginBottom:3 }}>URL</label>
              <input value={form.url} onChange={e => setF(f => ({...f, url:e.target.value}))}
                onKeyDown={e => e.key==='Enter' && save()}
                style={{ ...S.inp, fontSize:16 }} placeholder="https://…" inputMode="url" autoCapitalize="none" />
            </div>
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <button onClick={save} style={{ ...S.btn('#4ecdc4'), flex:1, textAlign:'center' }}>{editId ? '✓ Aktualisieren' : '✓ Speichern'}</button>
            <button onClick={() => { setForm(false); setEditId(null); setF({ title:'', url:'', icon:'🔗' }); }} style={{ ...S.btn('#ff6b9d'), flex:1, textAlign:'center' }}>Abbrechen</button>
          </div>
        </div>
      )}
    </div>
  );
}

function TodoList({ toast }) {
  const [items, setItems] = useState([]);
  const [text,  setText]  = useState('');
  const [isOpen, setIsOpen] = useState(false);
  useEffect(() => { api('/dashboard/todos').then(setItems).catch(() => {}); }, []);

  const add = async () => {
    if (!text.trim()) return;
    try { const n = await api('/dashboard/todos', { body:{ text:text.trim() } }); setItems(p => [...p, n]); setText(''); }
    catch(e) { toast(e.message, 'error'); }
  };
  const toggle = async item => {
    try { const u = await api(`/dashboard/todos/${item.id}`, { method:'PUT', body:{ done:!item.done } }); setItems(p => p.map(i => i.id===item.id ? u : i)); }
    catch(e) { toast(e.message, 'error'); }
  };
  const del = async id => {
    try { await api(`/dashboard/todos/${id}`, { method:'DELETE' }); setItems(p => p.filter(i => i.id!==id)); }
    catch(e) { toast(e.message, 'error'); }
  };

  const open = items.filter(i => !i.done);
  const done = items.filter(i =>  i.done);

  return (
    <div style={{ ...S.card, marginBottom:10 }}>
      <button onClick={()=>setIsOpen(v=>!v)} style={{width:'100%',background:'transparent',border:'none',
        display:'flex',justifyContent:'space-between',alignItems:'center',cursor:'pointer',padding:0}}>
        <div style={S.head}>TO-DO{items.filter(i=>!i.done).length > 0
          ? <span style={{color:'#4ecdc4',fontFamily:'monospace',fontSize:10,marginLeft:6}}>({items.filter(i=>!i.done).length})</span>
          : null}</div>
        <span style={{color:'rgba(255,255,255,0.4)',fontSize:11,display:'inline-block',
          transform:isOpen?'rotate(90deg)':'rotate(0)',transition:'transform 0.2s'}}>▶</span>
      </button>
      {isOpen && <><div style={{ display:'flex', gap:6, marginBottom:10, marginTop:10 }}>
        <input value={text} onChange={e => setText(e.target.value)}
          onKeyDown={e => e.key==='Enter' && add()}
          style={{ ...S.inp, flex:1, fontSize:16 }} placeholder="Neue Aufgabe…" />
        <button onClick={add} style={{ ...S.btn('#4ecdc4'), padding:'0 16px', fontSize:20, lineHeight:1 }}>+</button>
      </div>
      <div style={{ maxHeight:220, overflowY:'auto' }}>
        {open.length === 0 && done.length === 0 && (
          <div style={{ color:'rgba(255,255,255,0.45)', fontSize:11, fontFamily:'monospace', padding:'6px 0' }}>Noch keine Aufgaben.</div>
        )}
        {open.map(item => (
          <div key={item.id} style={{ display:'flex', alignItems:'center', gap:10, padding:'11px 0', borderBottom:'1px solid rgba(255,255,255,0.04)' }}>
            <button onClick={() => toggle(item)} style={{
              width:22, height:22, borderRadius:5, flexShrink:0, cursor:'pointer',
              border:'1.5px solid rgba(78,205,196,0.5)', background:'transparent',
            }} />
            <span style={{ color:'rgba(255,255,255,0.8)', fontSize:13, fontFamily:'monospace', flex:1, lineHeight:1.4 }}>{item.text}</span>
            <button onClick={() => del(item.id)} style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.5)', cursor:'pointer', fontSize:18, padding:'0 2px', lineHeight:1 }}>✕</button>
          </div>
        ))}
        {done.length > 0 && (
          <>
            <div style={{ ...S.head, padding:'10px 0 4px', marginBottom:0 }}>ERLEDIGT</div>
            {done.map(item => (
              <div key={item.id} style={{ display:'flex', alignItems:'center', gap:10, padding:'9px 0', opacity:0.4 }}>
                <button onClick={() => toggle(item)} style={{
                  width:22, height:22, borderRadius:5, flexShrink:0, cursor:'pointer',
                  border:'1.5px solid rgba(78,205,196,0.4)', background:'rgba(78,205,196,0.15)',
                  color:'#4ecdc4', fontSize:12, lineHeight:1,
                }}>✓</button>
                <span style={{ color:'rgba(255,255,255,0.4)', fontSize:13, fontFamily:'monospace', flex:1, textDecoration:'line-through' }}>{item.text}</span>
                <button onClick={() => del(item.id)} style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.5)', cursor:'pointer', fontSize:18 }}>✕</button>
              </div>
            ))}
          </>
        )}
      </div></>}
    </div>
  );
}

function Notepad({ toast }) {
  const [content,  setContent]  = useState('');
  const [saved,    setSaved]    = useState(true);
  const [saveTime, setSaveTime] = useState(null);
  const [isOpen,   setIsOpen]   = useState(false);
  const tmr = useRef(null);

  useEffect(() => {
    api('/dashboard/note').then(d => { setContent(d.content || ''); setSaveTime(d.updated_at); }).catch(() => {});
  }, []);

  const change = val => {
    setContent(val); setSaved(false); clearTimeout(tmr.current);
    tmr.current = setTimeout(async () => {
      try { const r = await api('/dashboard/note', { method:'PUT', body:{ content:val } }); setSaved(true); setSaveTime(r.updated_at); }
      catch(e) { toast(e.message, 'error'); }
    }, 900);
  };

  return (
    <div style={{ ...S.card }}>
      <button onClick={()=>setIsOpen(v=>!v)} style={{width:'100%',background:'transparent',border:'none',
        display:'flex',alignItems:'center',gap:8,cursor:'pointer',padding:0}}>
        <div style={S.head}>NOTIZEN</div>
        {!isOpen && content.length > 0 && (
          <span style={{color:'rgba(255,255,255,0.45)',fontFamily:'monospace',fontSize:10}}>
            {content.length} Zeichen
          </span>
        )}
        <span style={{color:'rgba(255,255,255,0.4)',fontSize:11,display:'inline-block',marginLeft:'auto',
          transform:isOpen?'rotate(90deg)':'rotate(0)',transition:'transform 0.2s'}}>▶</span>
      </button>
      {isOpen && <div style={{ color: saved ? 'rgba(78,205,196,0.5)' : 'rgba(255,230,109,0.6)',
        fontSize:10, fontFamily:'monospace', marginTop:4, marginBottom:6, textAlign:'right' }}>
        {saved ? (saveTime ? `✓ ${new Date(saveTime).toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit' })}` : '✓') : '…'}
      </div>}
      {isOpen && <textarea value={content} onChange={e => change(e.target.value)}
        placeholder="Notizen, IPs, Zugangsdaten…"
        style={{ ...S.inp, width:'100%', minHeight:140, resize:'vertical', lineHeight:1.7, padding:'10px 12px', fontSize:14 }} />}
    </div>
  );
}


// ── Bestell-Statistik Widget ─────────────────────────────────────────────────
function BestellStats() {
  const [stats,  setStats]  = useState(null);
  const [open,   setOpen]   = useState(false);
  const [loaded, setLoaded] = useState(false);

  const load = () => {
    if (loaded) return;
    api('/dashboard/stats').then(s => { setStats(s); setLoaded(true); }).catch(() => {});
  };

  const toggle = () => { setOpen(v => !v); if (!open) load(); };

  const Row = ({label, val, color='#fff'}) => (
    <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'7px 0',borderBottom:'1px solid rgba(255,255,255,0.05)'}}>
      <span style={{color:'rgba(255,255,255,0.45)',fontFamily:'monospace',fontSize:12}}>{label}</span>
      <span style={{color,fontFamily:"'Space Mono',monospace",fontSize:13,fontWeight:700}}>{val}</span>
    </div>
  );

  return (
    <div style={{...S.card,marginBottom:10}}>
      <button onClick={toggle} style={{width:'100%',background:'transparent',border:'none',
        display:'flex',justifyContent:'space-between',alignItems:'center',cursor:'pointer',padding:0}}>
        <div style={S.head}>3D-DRUCK STATISTIK</div>
        <span style={{color:'rgba(255,255,255,0.3)',fontSize:11,display:'inline-block',
          transform:open?'rotate(90deg)':'rotate(0)',transition:'transform 0.2s'}}>▶</span>
      </button>
      {open && (
        <div style={{marginTop:12}}>
          {!stats ? (
            <div style={{color:'rgba(255,255,255,0.55)',fontFamily:'monospace',fontSize:12}}>Lädt…</div>
          ) : (
            <>
              <div style={{marginBottom:12}}>
                <div style={{...S.head,marginBottom:6}}>BESTELLUNGEN</div>
                <Row label="Gesamt" val={stats.totalOrders}/>
                <Row label="Diesen Monat" val={stats.ordersThisMonth} color="#4ecdc4"/>
                <Row label="Warteliste" val={stats.byStatus.warteliste||0} color="#ffe66d"/>
                <Row label="In Arbeit" val={stats.byStatus.in_arbeit||0} color="#4ecdc4"/>
                <Row label="Fertig (unbezahlt)" val={stats.byStatus.fertig||0} color="#6bcb77"/>
                <Row label="Bezahlt" val={stats.bezahltOrders} color="#c084fc"/>
              </div>
              <div>
                <div style={{...S.head,marginBottom:6}}>EINNAHMEN</div>
                <Row label="Eingenommen (bezahlt)" val={`${stats.totalRevenue.toFixed(2)} €`} color="#6bcb77"/>
                <Row label="Offen (in Arbeit/Fertig)" val={`${stats.offeneRevenue.toFixed(2)} €`} color="#ffe66d"/>
                <Row label="Archiv-Einträge" val={stats.totalCalcs} color="rgba(255,255,255,0.5)"/>
              </div>
            </>
          )}
        </div>
      )}
    </div>
  );
}

function Dashboard({ toast, mobile }) {
  return (
    <div style={{ padding: mobile ? '14px 12px 90px' : '36px 44px', maxWidth:1100 }}>
      <div style={{ marginBottom:16 }}>
        <h1 style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:mobile ? 17 : 22, margin:0 }}>Dashboard</h1>
        <p style={{ color:'rgba(255,255,255,0.55)', fontFamily:'monospace', fontSize:10, marginTop:3 }}>
          {new Date().toLocaleDateString('de-DE', { weekday:'long', day:'numeric', month:'long' })}
        </p>
      </div>
      <QuickLinks toast={toast} mobile={mobile} />
      <CalendarWidget/>
      <BestellStats/>
      <TodoList   toast={toast} />
      <Notepad    toast={toast} />
    </div>
  );
}


// ── Admin Panel ───────────────────────────────────────────────────────────────
// Sec muss außerhalb von AdminPanel definiert sein damit Inputs den Fokus behalten
const Sec = ({title, children}) => (
  <div style={{...S.card, marginBottom:12}}>
    <div style={S.head}>{title}</div>
    {children}
  </div>
);

// ── Account-Löschung ─────────────────────────────────────────────────────────
function DeleteAccountSection({ toast, user }) {
  const [pw,  setPw]  = useState('');
  const [busy, setBusy] = useState(false);
  const { confirm, ConfirmDialog } = useConfirm();

  const doDelete = async () => {
    if (!pw) { toast('Passwort eingeben', 'error'); return; }
    if (!await confirm(`Account "${user.username}" und alle Daten wirklich löschen? Das kann nicht rückgängig gemacht werden.`)) return;
    setBusy(true);
    try {
      await api('/auth/delete-account', { method:'DELETE', body:{ password:pw } });
      localStorage.removeItem('sk_token');
      window.location.reload();
    } catch(e) { toast(e.message, 'error'); } finally { setBusy(false); }
  };

  return (
    <div>
      <ConfirmDialog/>
      <Field label="PASSWORT ZUR BESTÄTIGUNG" type="password" value={pw} onChange={e=>setPw(e.target.value)}/>
      <button onClick={doDelete} disabled={busy} style={{
        ...S.btn('#ff6b9d'), width:'100%', textAlign:'center', padding:'11px 0',
        opacity: busy ? 0.6 : 1,
      }}>
        {busy ? '…' : '✕ Account unwiderruflich löschen'}
      </button>
    </div>
  );
}

// ── QuickLinks Einstellungen ─────────────────────────────────────────────────
function QuickLinksSettings({ toast }) {
  const [links,   setLinks]   = useState([]);
  const [showForm, setForm]   = useState(false);
  const [form,    setF]       = useState({ title:'', url:'', icon:'🔗' });
  const [editId,  setEditId]  = useState(null);
  const { confirm, ConfirmDialog } = useConfirm();

  useEffect(() => { api('/dashboard/links').then(setLinks).catch(() => {}); }, []);

  const getFavicon = url => {
    try { return `https://www.google.com/s2/favicons?sz=64&domain=${new URL(url).hostname}`; }
    catch { return null; }
  };

  const save = async () => {
    if (!form.title.trim() || !form.url.trim()) { toast('Titel und URL erforderlich', 'error'); return; }
    let url = form.url.trim();
    if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
    const icon = form.icon === '🔗' ? (getFavicon(url) || '🔗') : form.icon;
    try {
      if (editId) {
        const u = await api(`/dashboard/links/${editId}`, { method:'PUT', body:{...form, icon, url} });
        setLinks(p => p.map(l => l.id===editId ? u : l));
      } else {
        const n = await api('/dashboard/links', { body:{...form, icon, url} });
        setLinks(p => [...p, n]);
      }
      toast(editId ? 'Aktualisiert' : 'Gespeichert');
      setF({ title:'', url:'', icon:'🔗' }); setForm(false); setEditId(null);
    } catch(e) { toast(e.message, 'error'); }
  };

  const del = async id => {
    if (!await confirm('Link wirklich löschen?')) return;
    try { await api(`/dashboard/links/${id}`, { method:'DELETE' }); setLinks(p => p.filter(l => l.id!==id)); toast('Gelöscht'); }
    catch(e) { toast(e.message, 'error'); }
  };

  return (
    <div>
      <ConfirmDialog/>
      {/* Link-Liste */}
      {links.length > 0 && (
        <div style={{ marginBottom:12 }}>
          {links.map(l => (
            <div key={l.id} style={{ display:'flex', alignItems:'center', gap:10, padding:'8px 0',
              borderBottom:'1px solid rgba(255,255,255,0.05)' }}>
              <span style={{ fontSize:18, width:24, textAlign:'center', flexShrink:0 }}>
                {l.icon && l.icon.startsWith('http')
                  ? <img src={l.icon} alt="" style={{width:18,height:18,objectFit:'contain'}} onError={e=>e.target.style.display='none'}/>
                  : l.icon}
              </span>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ color:'#fff', fontFamily:'monospace', fontSize:13 }}>{l.title}</div>
                <div style={{ color:'rgba(255,255,255,0.4)', fontFamily:'monospace', fontSize:10,
                  overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{l.url}</div>
              </div>
              <div style={{ display:'flex', gap:5, flexShrink:0 }}>
                <button onClick={() => { setF({ title:l.title, url:l.url, icon:l.icon }); setEditId(l.id); setForm(true); }}
                  style={S.btn('#4ecdc4', true)}>✎</button>
                <button onClick={() => del(l.id)} style={S.btn('#ff6b9d', true)}>✕</button>
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Formular */}
      {showForm ? (
        <div style={{ background:'rgba(0,0,0,0.2)', border:'1px solid rgba(255,255,255,0.07)', borderRadius:10, padding:12 }}>
          <div style={{ marginBottom:10 }}>
            <div style={{ ...S.head, marginBottom:6 }}>ICON</div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:5 }}>
              {['🔗','🌐','📊','📁','🛠','📧','🗓','💾','🖥','📡','🔒','📖','🎯','⚡','🏠','🔧','📱','🎮','🚀','💡'].map(ic => (
                <button key={ic} onClick={() => setF(f => ({...f, icon:ic}))} style={{
                  width:34, height:34, borderRadius:7, fontSize:17, cursor:'pointer',
                  border:`1px solid ${form.icon===ic ? '#4ecdc4' : 'rgba(255,255,255,0.1)'}`,
                  background: form.icon===ic ? 'rgba(78,205,196,0.15)' : 'rgba(255,255,255,0.04)',
                }}>{ic}</button>
              ))}
            </div>
          </div>
          <Field label="TITEL" value={form.title} onChange={e => setF(f => ({...f, title:e.target.value}))} placeholder="Mein Link"/>
          <Field label="URL" value={form.url} onChange={e => setF(f => ({...f, url:e.target.value}))} placeholder="https://…" autoCapitalize="none"/>
          <div style={{ display:'flex', gap:8, marginTop:4 }}>
            <button onClick={save} style={{ ...S.btn('#4ecdc4'), flex:1, textAlign:'center', padding:'10px 0' }}>{editId ? '✓ Aktualisieren' : '✓ Speichern'}</button>
            <button onClick={() => { setForm(false); setEditId(null); setF({ title:'', url:'', icon:'🔗' }); }}
              style={{ ...S.btn('#ff6b9d'), flex:1, textAlign:'center', padding:'10px 0' }}>Abbrechen</button>
          </div>
        </div>
      ) : (
        <button onClick={() => { setForm(true); setEditId(null); setF({ title:'', url:'', icon:'🔗' }); }}
          style={{ ...S.btn('#4ecdc4'), width:'100%', textAlign:'center', padding:'10px 0' }}>
          + Link hinzufügen
        </button>
      )}
    </div>
  );
}

// ── Benutzerverwaltung ────────────────────────────────────────────────────────
function UserManagement({ toast }) {
  const [users,   setUsers]   = useState([]);
  const [loading, setLoading] = useState(true);
  const [form,    setForm]    = useState({ username:'', password:'', role:'user' });
  const [resetId, setResetId] = useState(null);
  const [resetPw, setResetPw] = useState('');
  const [delId,   setDelId]   = useState(null);
  const { confirm, ConfirmDialog } = useConfirm();

  const load = () => {
    setLoading(true);
    api('/admin/users').then(setUsers).catch(e=>toast(e.message,'error')).finally(()=>setLoading(false));
  };
  useEffect(()=>{ load(); },[]);

  const create = async () => {
    if (!form.username.trim()||!form.password) { toast('Alle Felder ausfüllen','error'); return; }
    try {
      await api('/admin/users',{body:form});
      toast(`Benutzer "${form.username}" angelegt`);
      setForm({username:'',password:'',role:'user'}); load();
    } catch(e) { toast(e.message,'error'); }
  };

  const del = async id => {
    if (!await confirm('Benutzer und alle seine Daten wirklich löschen?')) return;
    try { await api(`/admin/users/${id}`,{method:'DELETE'}); toast('Gelöscht'); load(); }
    catch(e) { toast(e.message,'error'); }
  };

  const resetPassword = async () => {
    if (!resetPw||resetPw.length<8) { toast('Mind. 8 Zeichen','error'); return; }
    try {
      await api(`/admin/users/${resetId}/reset-password`,{method:'PUT',body:{newPassword:resetPw}});
      toast('Passwort zurückgesetzt'); setResetId(null); setResetPw('');
    } catch(e) { toast(e.message,'error'); }
  };

  return (
    <div>
      <ConfirmDialog/>

      {/* Neuen Benutzer anlegen */}
      <Sec title="NEUEN BENUTZER ANLEGEN">
        <Field label="BENUTZERNAME" value={form.username} onChange={e=>setForm(f=>({...f,username:e.target.value}))} autoCapitalize="none"/>
        <Field label="PASSWORT (mind. 8 Zeichen)" type="password" value={form.password} onChange={e=>setForm(f=>({...f,password:e.target.value}))}/>
        <div style={{marginBottom:12}}>
          <label style={{...S.head,display:'block',marginBottom:4}}>ROLLE</label>
          <select value={form.role} onChange={e=>setForm(f=>({...f,role:e.target.value}))} style={{...S.inp,fontSize:14}}>
            <option value="user" style={{background:'#1a1a1e'}}>Benutzer</option>
            <option value="admin" style={{background:'#1a1a1e'}}>Administrator</option>
          </select>
        </div>
        <button onClick={create} style={{...S.btn('#4ecdc4'),width:'100%',textAlign:'center',padding:'11px 0'}}>
          + Benutzer anlegen
        </button>
      </Sec>

      {/* Passwort-Reset Modal */}
      {resetId && (
        <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,0.8)',zIndex:5000,
          display:'flex',alignItems:'center',justifyContent:'center',padding:20}}>
          <div style={{...S.card,width:'100%',maxWidth:360}}>
            <div style={{color:'#fff',fontFamily:"'Space Mono',monospace",fontSize:14,fontWeight:700,marginBottom:16}}>
              Passwort zurücksetzen
            </div>
            <Field label="NEUES PASSWORT" type="password" value={resetPw} onChange={e=>setResetPw(e.target.value)}/>
            <div style={{display:'flex',gap:8}}>
              <button onClick={resetPassword} style={{...S.btn('#4ecdc4'),flex:1,textAlign:'center',padding:'10px 0'}}>✓ Setzen</button>
              <button onClick={()=>{setResetId(null);setResetPw('');}} style={{...S.btn('#ff6b9d'),flex:1,textAlign:'center',padding:'10px 0'}}>Abbrechen</button>
            </div>
          </div>
        </div>
      )}

      {/* Benutzerliste */}
      <Sec title="BENUTZER">
        {loading && <div style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:12}}>Lädt…</div>}
        {users.map(u => (
          <div key={u.id} style={{
            padding:'12px 0', borderBottom:'1px solid rgba(255,255,255,0.06)',
          }}>
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:8}}>
              <div>
                <span style={{color:'#fff',fontFamily:'monospace',fontSize:13,fontWeight:700}}>{u.username}</span>
                <span style={{
                  marginLeft:8, fontSize:9, fontFamily:'monospace',
                  color: u.role==='admin'?'#ffe66d':'#4ecdc4',
                  background: u.role==='admin'?'rgba(255,230,109,0.1)':'rgba(78,205,196,0.1)',
                  border:`1px solid ${u.role==='admin'?'rgba(255,230,109,0.3)':'rgba(78,205,196,0.3)'}`,
                  borderRadius:4, padding:'1px 6px',
                }}>{u.role}</span>
              </div>
              <div style={{display:'flex',gap:5}}>
                <button onClick={()=>{setResetId(u.id);setResetPw('');}}
                  style={{...S.btn('#ffe66d',true),fontSize:10}}>🔑 PW</button>
                <button onClick={()=>del(u.id)} style={{...S.btn('#ff6b9d',true)}}>
                  <TrashIcon size={13} color="#ff6b9d"/>
                </button>
              </div>
            </div>
            {/* Statistik */}
            <div style={{display:'flex',flexWrap:'wrap',gap:6}}>
              {[
                ['◈ Archiv', u.archiv],
                ['📦 Bestellungen', u.bestellung],
                ['✓ Todos', u.todos],
                ['🔗 Links', u.links],
                ['📁 Dateien', u.files],
                ['📅 iCals', u.icals],
                [`✎ ${u.noteLen} Zeichen`, null],
              ].map(([label, val]) => (
                <span key={label} style={{
                  fontSize:10, fontFamily:'monospace',
                  color:'rgba(255,255,255,0.55)',
                  background:'rgba(255,255,255,0.04)',
                  border:'1px solid rgba(255,255,255,0.08)',
                  borderRadius:8, padding:'2px 8px',
                }}>
                  {label}{val !== null ? `: ${val}` : ''}
                </span>
              ))}
            </div>
          </div>
        ))}
      </Sec>
    </div>
  );
}

// Field außerhalb definiert → Tastatur bleibt beim Tippen erhalten
const Field = ({ label, type='text', value, onChange, placeholder='', autoCapitalize='off' }) => (
  <div style={{ marginBottom:12 }}>
    <label style={{ ...S.head, display:'block', marginBottom:4 }}>{label}</label>
    <input type={type} value={value} onChange={onChange} placeholder={placeholder}
      autoCapitalize={autoCapitalize}
      style={{ ...S.inp, fontSize:16, padding:'11px 12px' }} />
  </div>
);

function AdminPanel({ toast, mobile, user }) {
  const [section, setSection] = useState('profil');
  const [pw,  setPw]  = useState({ current:'', newPw:'', confirm:'' });
  const [avatar, setAvatar] = useState(localStorage.getItem('dd_avatar') || null);
  const [un,  setUn]  = useState({ newUsername:'', unPw:'' });
  const [file, setFile] = useState(null);
  const [busy, setBusy] = useState({ pw:false, un:false, restore:false });
  const set = (key, val) => setBusy(b => ({...b, [key]:val}));

  const changePw = async () => {
    if (pw.newPw !== pw.confirm) { toast('Passwörter stimmen nicht überein', 'error'); return; }
    if (pw.newPw.length < 8)    { toast('Mindestens 8 Zeichen', 'error'); return; }
    set('pw', true);
    try { await api('/auth/change-password', { body:{ currentPassword:pw.current, newPassword:pw.newPw } }); toast('Passwort geändert'); setPw({ current:'', newPw:'', confirm:'' }); }
    catch(e) { toast(e.message, 'error'); } finally { set('pw', false); }
  };

  const changeUn = async () => {
    if (!un.newUsername.trim()) { toast('Benutzername eingeben', 'error'); return; }
    set('un', true);
    try {
      await api('/auth/change-username', { body:{ newUsername:un.newUsername.trim(), password:un.unPw } });
      toast('Benutzername geändert – bitte neu einloggen');
      setUn({ newUsername:'', unPw:'' });
      setTimeout(() => { localStorage.removeItem('sk_token'); window.location.reload(); }, 1800);
    } catch(e) { toast(e.message, 'error'); } finally { set('un', false); }
  };

  const backup = async () => {
    try {
      const blob = await api('/admin/backup');
      const a = Object.assign(document.createElement('a'), {
        href: URL.createObjectURL(blob),
        download: `dickendock-backup-${new Date().toISOString().split('T')[0]}.db`
      });
      a.click(); URL.revokeObjectURL(a.href); toast('Backup heruntergeladen');
    } catch(e) { toast(e.message, 'error'); }
  };

  const restore = async () => {
    if (!file) { toast('Datei auswählen', 'error'); return; }
    if (!window.confirm('⚠️ Aktuelle Datenbank wird ersetzt. Fortfahren?')) return;
    set('restore', true);
    try {
      const f = new FormData(); f.append('database', file);
      await api('/admin/restore', { method:'POST', body:f, isFile:true });
      toast('Wiederhergestellt'); setFile(null);
    } catch(e) { toast(e.message, 'error'); } finally { set('restore', false); }
  };

  return (
    <div style={{ padding: mobile ? '14px 12px 90px' : '36px 44px', maxWidth:560 }}>
      <h1 style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:mobile?17:22, marginBottom:16 }}>Einstellungen</h1>

      <div style={{ display:'flex', gap:6, marginBottom:18, flexWrap:'wrap' }}>
        {[['profil','Profil'],['dashboard','Dashboard'], ...(user?.role==='admin'?[['benutzer','Benutzer'],['backup','Backup']]:[])]
          .map(([k,l]) => (
          <button key={k} onClick={()=>setSection(k)} style={{
            padding:'6px 16px', borderRadius:20, fontFamily:'monospace', fontSize:12, cursor:'pointer',
            border:`1px solid ${section===k?'rgba(78,205,196,0.5)':'rgba(255,255,255,0.15)'}`,
            background: section===k?'rgba(78,205,196,0.12)':'transparent',
            color: section===k?'#4ecdc4':'rgba(255,255,255,0.55)',
          }}>{l}</button>
        ))}
      </div>

      {section === 'profil' && (
        <div>
          <Sec title="AVATAR">
            <div style={{ display:'flex', alignItems:'center', gap:14, marginBottom:12 }}>
              <div style={{ width:60, height:60, borderRadius:'50%', overflow:'hidden', flexShrink:0,
                background:'linear-gradient(135deg,#ff6b9d,#4ecdc4)',
                display:'flex', alignItems:'center', justifyContent:'center' }}>
                {avatar
                  ? <img src={avatar} alt="Avatar" style={{width:'100%',height:'100%',objectFit:'cover'}}/>
                  : <UserIcon size={28} color="#0d0d0f"/>}
              </div>
              <div style={{flex:1}}>
                <label style={{...S.head,display:'block',marginBottom:6}}>PROFILBILD</label>
                <input type="file" accept="image/*" onChange={async e => {
                  const file = e.target.files?.[0]; if(!file) return;
                  const reader = new FileReader();
                  reader.onload = ev => {
                    const canvas = document.createElement('canvas');
                    const img = new Image(); img.onload = () => {
                      const size = 120;
                      canvas.width = size; canvas.height = size;
                      const ctx = canvas.getContext('2d');
                      ctx.beginPath(); ctx.arc(size/2,size/2,size/2,0,Math.PI*2);
                      ctx.clip();
                      const min = Math.min(img.width,img.height);
                      ctx.drawImage(img,(img.width-min)/2,(img.height-min)/2,min,min,0,0,size,size);
                      const data = canvas.toDataURL('image/jpeg',0.85);
                      setAvatar(data); localStorage.setItem('dd_avatar',data); toast('Avatar gespeichert');
                    }; img.src = ev.target.result;
                  }; reader.readAsDataURL(file);
                }} style={{...S.inp,fontSize:13,padding:'7px 10px',cursor:'pointer'}}/>
              </div>
            </div>
            {avatar && <button onClick={()=>{setAvatar(null);localStorage.removeItem('dd_avatar');toast('Avatar entfernt');}}
              style={{...S.btn('#ff6b9d',true)}}>✕ Entfernen</button>}
          </Sec>
          {user?.role==='admin' && <Sec title="BENUTZERNAME ÄNDERN">
            <Field label="NEUER BENUTZERNAME" value={un.newUsername} onChange={e=>setUn(p=>({...p,newUsername:e.target.value}))} />
            <Field label="PASSWORT ZUR BESTÄTIGUNG" type="password" value={un.unPw} onChange={e=>setUn(p=>({...p,unPw:e.target.value}))} />
            <button onClick={changeUn} disabled={busy.un} style={{ ...S.btn('#4ecdc4'), width:'100%', textAlign:'center', padding:'11px 0' }}>
              {busy.un ? '…' : '✓ Benutzername ändern'}
            </button>
          </Sec>}
          <Sec title="PASSWORT ÄNDERN">
            <Field label="AKTUELLES PASSWORT"  type="password" value={pw.current} onChange={e=>setPw(p=>({...p,current:e.target.value}))} />
            <Field label="NEUES PASSWORT"      type="password" value={pw.newPw}   onChange={e=>setPw(p=>({...p,newPw:e.target.value}))} />
            <Field label="BESTÄTIGEN"          type="password" value={pw.confirm} onChange={e=>setPw(p=>({...p,confirm:e.target.value}))} />
            <button onClick={changePw} disabled={busy.pw} style={{ ...S.btn('#4ecdc4'), width:'100%', textAlign:'center', padding:'11px 0' }}>
              {busy.pw ? '…' : '✓ Passwort ändern'}
            </button>
          </Sec>
          <Sec title="ACCOUNT LÖSCHEN">
            <p style={{ color:'rgba(255,255,255,0.55)', fontSize:12, fontFamily:'monospace', marginBottom:12, lineHeight:1.6 }}>
              Löscht deinen Account und alle deine Daten unwiderruflich.
            </p>
            <DeleteAccountSection toast={toast} user={user}/>
          </Sec>
        </div>
      )}

      {section === 'benutzer' && user?.role==='admin' && (
        <div><UserManagement toast={toast}/></div>
      )}

      {section === 'dashboard' && (
        <div>
          <Sec title="SCHNELLZUGRIFF">
            <QuickLinksSettings toast={toast}/>
          </Sec>
          <Sec title="KALENDER (iCal)">
            <CalendarSettings toast={toast}/>
          </Sec>
          {user?.role==='admin' && <Sec title="DATEI-MANAGER LIMITS">
            <DateiSettings toast={toast}/>
          </Sec>}
        </div>
      )}

      {section === 'backup' && (
        <div>
          <Sec title="DATENBANK">
            <p style={{ color:'rgba(255,255,255,0.55)', fontSize:12, fontFamily:'monospace', marginBottom:12, lineHeight:1.6 }}>
              Vollständige SQLite-Datenbank sichern oder wiederherstellen.
            </p>
            <button onClick={backup} style={{ ...S.btn('#ffe66d'), width:'100%', textAlign:'center', padding:'11px 0', marginBottom:12 }}>
              ↓ Backup herunterladen
            </button>
            <label style={{ ...S.head, display:'block', marginBottom:4 }}>SICHERUNG EINSPIELEN (.db)</label>
            <div style={{ display:'flex', gap:8 }}>
              <input type="file" accept=".db" onChange={e => setFile(e.target.files[0])}
                style={{ ...S.inp, flex:1, padding:'9px 10px', cursor:'pointer', fontSize:13 }} />
              <button onClick={restore} disabled={busy.restore || !file}
                style={{ ...S.btn('#ff6b9d'), opacity: busy.restore || !file ? 0.4 : 1, padding:'0 14px', flexShrink:0 }}>
                {busy.restore ? '…' : '↑'}
              </button>
            </div>
            {file && <div style={{ color:'rgba(255,255,255,0.55)', fontSize:10, fontFamily:'monospace', marginTop:5 }}>{file.name}</div>}
          </Sec>
        </div>
      )}
    </div>
  );
}


// ── App Shell ─────────────────────────────────────────────────────────────────
export default function App() {
  const mobile = useIsMobile();
  const [splash, setSplash] = useState(() => {
    // Only show splash in standalone PWA mode, and only once per session
    return window.matchMedia('(display-mode: standalone)').matches && !sessionStorage.getItem('splash_shown');
  });
  const [user,setUser]=useState(null);
  const [active,setActive]=useState('dashboard');
  const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
  const [updateInfo,setUpdateInfo]=useState(null);
  const [showUpd,setShowUpd]=useState(false);

  useEffect(()=>{
    const token=localStorage.getItem('sk_token');
    if(!token)return;
    try{const p=JSON.parse(atob(token.split('.')[1]));
      if(p.exp*1000>Date.now())setUser({id:p.id,username:p.username,role:p.role});
      else localStorage.removeItem('sk_token');
    }catch{localStorage.removeItem('sk_token');}
  },[]);

  useEffect(()=>{
    if(!user)return;
    const check=()=>api('/system/update-check').then(setUpdateInfo).catch(()=>{});
    check();
    const t=setInterval(check,5*60*1000);
    return()=>clearInterval(t);
  },[user]);

  const toast=useCallback((msg,type='success')=>{
    setToastMsg({msg,type});
    setTimeout(()=>setToastMsg({msg:'',type:'success'}),3500);
  },[]);

  if(splash) return <SplashScreen onDone={()=>{ setSplash(false); sessionStorage.setItem('splash_shown','1'); }}/>;
  if(!user) return <Login onLogin={u=>setUser(u)}/>;

  const activeTool = TOOLS.find(t=>t.id===active);

  // Mobile padding bottom für fixed nav
  const mainStyle = { flex:1, overflowY:'auto', ...(mobile ? { paddingBottom:'calc(56px + env(safe-area-inset-bottom, 0px))' } : {}) };

  return(
    <>
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');
        *{margin:0;padding:0;box-sizing:border-box;}
        body{background:#111114;-webkit-tap-highlight-color:transparent;}
        input,textarea,select{-webkit-appearance:none;appearance:none;}
        input[type=number]::-webkit-inner-spin-button{opacity:0.25;}
        @keyframes fadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
        ::-webkit-scrollbar{width:3px;}::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.1);border-radius:2px;}
        select option,textarea{background:#111114;}
      `}</style>
      <div style={{display:'flex',minHeight:'100vh',background:'#111114'}}>
        {!mobile && (
          <Sidebar active={active} setActive={setActive} user={user}
            onLogout={()=>{localStorage.removeItem('sk_token');setUser(null);}}
            updateInfo={updateInfo} onUpdateClick={()=>setShowUpd(true)}/>
        )}
        <main style={mainStyle}>
          {active==='dashboard' && <Dashboard toast={toast} mobile={mobile}/>}
          {active==='admin' && <AdminPanel toast={toast} mobile={mobile} user={user}/>}
          {activeTool && <activeTool.component toast={toast} mobile={mobile}/>}
        </main>
      </div>
      {mobile && (
        <BottomNav active={active} setActive={setActive} user={user}
          onLogout={()=>{localStorage.removeItem('sk_token');setUser(null);}}
          updateInfo={updateInfo} onUpdateClick={()=>setShowUpd(true)}/>
      )}
      <Toast msg={toastMsg.msg} type={toastMsg.type}/>
      {showUpd&&updateInfo&&<UpdateModal data={updateInfo} onClose={()=>setShowUpd(false)}/>}
    </>
  );
}
