const { useState, useEffect } = React;

const api = {
  get: async (url) => {
    const r = await fetch(url);
    const data = await r.json().catch(() => ({}));
    if (!r.ok) throw new Error(data.error || 'GET fehlgeschlagen');
    return data;
  },
  post: async (url, body) => {
    const r = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body || {})
    });
    const data = await r.json().catch(() => ({}));
    if (!r.ok) throw new Error(data.error || 'POST fehlgeschlagen');
    return data;
  },
  put: async (url, body) => {
    const r = await fetch(url, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body || {})
    });
    const data = await r.json().catch(() => ({}));
    if (!r.ok) throw new Error(data.error || 'PUT fehlgeschlagen');
    return data;
  },
  del: async (url) => {
    const r = await fetch(url, { method: 'DELETE' });
    const data = await r.json().catch(() => ({}));
    if (!r.ok) throw new Error(data.error || 'DELETE fehlgeschlagen');
    return data;
  },
  upload: async (url, file, fields = {}) => {
    const fd = new FormData();
    fd.append('file', file);
    Object.entries(fields).forEach(([k, v]) => fd.append(k, v || ''));
    const r = await fetch(url, { method: 'POST', body: fd });
    const data = await r.json().catch(() => ({}));
    if (!r.ok) throw new Error(data.error || 'Upload fehlgeschlagen');
    return data;
  }
};

function App() {
  const [view, setView] = useState('dashboard');
  const [selectedAppId, setSelectedAppId] = useState(null);
  const [health, setHealth] = useState(null);

  useEffect(() => {
    api.get('/api/health').then(setHealth).catch(() => setHealth(null));
  }, []);

  function openApp(id) {
    setSelectedAppId(id);
    setView('detail');
  }

  return (
    <div className="min-h-screen">
      <header className="aok-green text-white p-4 shadow flex justify-between items-center">
        <div>
          <h1 className="text-2xl font-bold">🧰 AppVault</h1>
          <div className="text-sm opacity-80">Eigene Apps · Versionen · Anleitungen · Word-Dokumente · Codes</div>
        </div>
        <div className="text-xs bg-green-700 px-3 py-1 rounded">
          {health?.status || '...'}
        </div>
      </header>

      <nav className="bg-white border-b shadow-sm p-2 flex gap-2 overflow-x-auto">
        <NavButton active={view === 'dashboard'} onClick={() => setView('dashboard')}>Dashboard</NavButton>
        <NavButton active={view === 'apps'} onClick={() => setView('apps')}>Apps</NavButton>
        {selectedAppId && <NavButton active={view === 'detail'} onClick={() => setView('detail')}>App-Details</NavButton>}
      </nav>

      <main className="container mx-auto max-w-7xl p-6">
        {view === 'dashboard' && <Dashboard onOpen={openApp} />}
        {view === 'apps' && <Apps onOpen={openApp} />}
        {view === 'detail' && selectedAppId && <AppDetail appId={selectedAppId} onBack={() => setView('apps')} />}
      </main>
    </div>
  );
}

function NavButton({ active, onClick, children }) {
  return (
    <button onClick={onClick} className={`px-4 py-2 rounded ${active ? 'aok-green text-white' : 'hover:bg-gray-100'}`}>
      {children}
    </button>
  );
}

function Dashboard({ onOpen }) {
  const [data, setData] = useState(null);
  const [apps, setApps] = useState([]);

  async function load() {
    setData(await api.get('/api/dashboard'));
    setApps(await api.get('/api/apps'));
  }

  useEffect(() => { load(); }, []);

  if (!data) return <div>Lade Dashboard...</div>;

  return (
    <div className="space-y-6">
      <h2 className="text-2xl font-bold">Dashboard</h2>

      <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
        <Stat title="Apps" value={data.counts.apps} />
        <Stat title="Versionen" value={data.counts.versions} />
        <Stat title="Codeblöcke" value={data.counts.codeBlocks} />
        <Stat title="Dokumente" value={data.counts.documents || 0} />
      </div>

      <div className="grid lg:grid-cols-2 gap-4">
        <div className="card p-6">
          <h3 className="font-bold mb-4">Apps</h3>
          <div className="space-y-2">
            {apps.slice(0, 8).map(a => (
              <div key={a.id} onClick={() => onOpen(a.id)} className="border-b pb-2 cursor-pointer hover:bg-gray-50 p-2 rounded">
                <div className="font-semibold">{a.title}</div>
                <div className="text-xs text-gray-500">
                  v{a.currentVersion} · {a.status} · Port {a.port || '-'} · Dokumente {a.documentsCount || 0}
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="card p-6">
          <h3 className="font-bold mb-4">Letzte Ereignisse</h3>
          <div className="space-y-2 text-sm">
            {data.recentEvents.map(e => (
              <div key={e.id} className="border-b pb-2">
                <span className="text-gray-500">{new Date(e.createdAt).toLocaleString('de-DE')}</span><br />
                {e.message}
              </div>
            ))}
            {data.recentEvents.length === 0 && <div className="text-gray-500">Noch keine Ereignisse.</div>}
          </div>
        </div>
      </div>
    </div>
  );
}

function Stat({ title, value }) {
  return (
    <div className="card p-4 text-center">
      <div className="text-3xl font-bold aok-green-text">{value}</div>
      <div className="text-sm text-gray-600">{title}</div>
    </div>
  );
}

function Apps({ onOpen }) {
  const [apps, setApps] = useState([]);
  const [show, setShow] = useState(false);
  const empty = {
    title: '',
    currentVersion: '1.0.0',
    status: 'Idee',
    category: '',
    shortDescription: '',
    internalUrl: '',
    externalUrl: '',
    port: '',
    dockerPath: '',
    techStack: ''
  };
  const [form, setForm] = useState(empty);

  async function load() {
    setApps(await api.get('/api/apps'));
  }

  useEffect(() => { load(); }, []);

  async function create() {
    await api.post('/api/apps', form);
    setForm(empty);
    setShow(false);
    load();
  }

  async function remove(id, e) {
    e.stopPropagation();
    if (!confirm('App wirklich löschen?')) return;
    await api.del('/api/apps/' + id);
    load();
  }

  return (
    <div className="space-y-6">
      <div className="flex justify-between">
        <h2 className="text-2xl font-bold">Apps</h2>
        <button onClick={() => setShow(!show)} className="aok-green text-white px-4 py-2 rounded">+ Neue App</button>
      </div>

      {show && (
        <div className="card p-6">
          <h3 className="font-bold mb-4">Neue App erfassen</h3>
          <div className="grid md:grid-cols-3 gap-4">
            <Input label="Titel der App" value={form.title} onChange={v => setForm({...form, title:v})} />
            <Input label="Version" value={form.currentVersion} onChange={v => setForm({...form, currentVersion:v})} />
            <Select label="Status" value={form.status} onChange={v => setForm({...form, status:v})}
              options={['Idee','In Entwicklung','Test','Produktiv','Archiviert'].map(x => [x,x])} />
            <Input label="Kategorie" value={form.category} onChange={v => setForm({...form, category:v})} />
            <Input label="Interne URL" value={form.internalUrl} onChange={v => setForm({...form, internalUrl:v})} />
            <Input label="Externe URL" value={form.externalUrl} onChange={v => setForm({...form, externalUrl:v})} />
            <Input label="Port" value={form.port} onChange={v => setForm({...form, port:v})} />
            <Input label="Docker-Pfad" value={form.dockerPath} onChange={v => setForm({...form, dockerPath:v})} />
            <Input label="Tech Stack" value={form.techStack} onChange={v => setForm({...form, techStack:v})} />
          </div>
          <Textarea label="Kurzbeschreibung" value={form.shortDescription} onChange={v => setForm({...form, shortDescription:v})} />
          <button onClick={create} className="aok-green text-white px-4 py-2 rounded mt-4">Anlegen</button>
        </div>
      )}

      <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
        {apps.map(a => (
          <div key={a.id} onClick={() => onOpen(a.id)} className="card p-4 cursor-pointer hover:shadow-lg transition">
            <div className="flex justify-between gap-2">
              <h3 className="font-bold text-lg">{a.title}</h3>
              <span className="text-xs bg-gray-100 px-2 py-1 rounded h-fit">{a.status}</span>
            </div>
            <p className="text-sm text-gray-600">v{a.currentVersion} · {a.category || '-'}</p>
            <p className="text-sm mt-2">{a.shortDescription}</p>
            <p className="text-xs text-gray-500 mt-2">
              Port: {a.port || '-'} · Codeblöcke: {a.codeBlocksCount || 0} · Dokumente: {a.documentsCount || 0}
            </p>
            <button onClick={(e) => remove(a.id, e)} className="text-red-600 text-xs mt-3">löschen</button>
          </div>
        ))}
      </div>
    </div>
  );
}

function AppDetail({ appId, onBack }) {
  const [bundle, setBundle] = useState(null);
  const [tab, setTab] = useState('overview');

  async function load() {
    setBundle(await api.get('/api/apps/' + appId));
  }

  useEffect(() => { load(); }, [appId]);

  if (!bundle) return <div>Lade App...</div>;

  return (
    <div className="space-y-6">
      <button onClick={onBack} className="text-sm hover:underline">← Zurück zu Apps</button>

      <div className="card p-6">
        <h2 className="text-2xl font-bold">{bundle.app.title}</h2>
        <p className="text-gray-600">v{bundle.app.currentVersion} · {bundle.app.status} · {bundle.app.category}</p>
      </div>

      <div className="bg-white border rounded p-2 flex gap-2 overflow-x-auto">
        {[
          ['overview','Übersicht'],
          ['edit','Stammdaten'],
          ['guides','Anleitungen'],
          ['documents','Dokumente'],
          ['versions','Versionen'],
          ['code','Codes'],
          ['export','Export']
        ].map(([k, label]) => (
          <button key={k} onClick={() => setTab(k)} className={`px-3 py-2 rounded ${tab === k ? 'aok-green text-white' : 'hover:bg-gray-100'}`}>
            {label}
          </button>
        ))}
      </div>

      {tab === 'overview' && <Overview bundle={bundle} />}
      {tab === 'edit' && <EditApp appItem={bundle.app} onChange={load} />}
      {tab === 'guides' && <GuideEditor appItem={bundle.app} onChange={load} />}
      {tab === 'documents' && <Documents appId={appId} documents={bundle.documents || []} onChange={load} />}
      {tab === 'versions' && <Versions appId={appId} versions={bundle.versions} onChange={load} />}
      {tab === 'code' && <CodeBlocks appId={appId} codeBlocks={bundle.codeBlocks} onChange={load} />}
      {tab === 'export' && <ExportDoc appId={appId} />}
    </div>
  );
}

function Overview({ bundle }) {
  const a = bundle.app;
  return (
    <div className="grid lg:grid-cols-2 gap-4">
      <div className="card p-6">
        <h3 className="font-bold mb-4">App-Informationen</h3>
        <p><strong>Titel:</strong> {a.title}</p>
        <p><strong>Version:</strong> {a.currentVersion}</p>
        <p><strong>Status:</strong> {a.status}</p>
        <p><strong>Port:</strong> {a.port}</p>
        <p><strong>Docker-Pfad:</strong> {a.dockerPath}</p>
        <p><strong>Interne URL:</strong> {a.internalUrl && <a className="underline aok-green-text" href={a.internalUrl} target="_blank">{a.internalUrl}</a>}</p>
        <p><strong>Externe URL:</strong> {a.externalUrl && <a className="underline aok-green-text" href={a.externalUrl} target="_blank">{a.externalUrl}</a>}</p>
      </div>

      <div className="card p-6">
        <h3 className="font-bold mb-4">Beschreibung</h3>
        <p className="whitespace-pre-wrap">{a.longDescription || a.shortDescription}</p>
      </div>

      <div className="card p-6 lg:col-span-2">
        <h3 className="font-bold mb-4">Timeline</h3>
        <div className="space-y-2 text-sm">
          {bundle.events.slice(0, 15).map(e => (
            <div key={e.id} className="border-b pb-2">
              <span className="text-gray-500">{new Date(e.createdAt).toLocaleString('de-DE')}</span><br />
              {e.message}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function EditApp({ appItem, onChange }) {
  const [form, setForm] = useState(appItem);

  async function save() {
    await api.put('/api/apps/' + appItem.id, form);
    onChange();
    alert('App gespeichert.');
  }

  return (
    <div className="card p-6 space-y-4">
      <h3 className="font-bold text-lg">Stammdaten</h3>
      <div className="grid md:grid-cols-3 gap-4">
        <Input label="Titel" value={form.title} onChange={v => setForm({...form, title:v})} />
        <Input label="Slug" value={form.slug} onChange={v => setForm({...form, slug:v})} />
        <Input label="Aktuelle Version" value={form.currentVersion} onChange={v => setForm({...form, currentVersion:v})} />
        <Select label="Status" value={form.status} onChange={v => setForm({...form, status:v})}
          options={['Idee','In Entwicklung','Test','Produktiv','Archiviert'].map(x => [x,x])} />
        <Input label="Kategorie" value={form.category} onChange={v => setForm({...form, category:v})} />
        <Input label="Port" value={form.port} onChange={v => setForm({...form, port:v})} />
        <Input label="Interne URL" value={form.internalUrl} onChange={v => setForm({...form, internalUrl:v})} />
        <Input label="Externe URL" value={form.externalUrl} onChange={v => setForm({...form, externalUrl:v})} />
        <Input label="Nginx-Domain" value={form.nginxDomain} onChange={v => setForm({...form, nginxDomain:v})} />
        <Input label="Dashy URL" value={form.dashyUrl} onChange={v => setForm({...form, dashyUrl:v})} />
        <Input label="Docker-Pfad" value={form.dockerPath} onChange={v => setForm({...form, dockerPath:v})} />
        <Input label="Repository URL" value={form.repositoryUrl} onChange={v => setForm({...form, repositoryUrl:v})} />
      </div>
      <Textarea label="Kurzbeschreibung" value={form.shortDescription} onChange={v => setForm({...form, shortDescription:v})} />
      <Textarea label="Ausführliche Beschreibung" value={form.longDescription} onChange={v => setForm({...form, longDescription:v})} />
      <Textarea label="Tech Stack" value={form.techStack} onChange={v => setForm({...form, techStack:v})} />
      <Textarea label="Notizen" value={form.notes} onChange={v => setForm({...form, notes:v})} />
      <button onClick={save} className="aok-green text-white px-4 py-2 rounded">Speichern</button>
    </div>
  );
}

function GuideEditor({ appItem, onChange }) {
  const [form, setForm] = useState(appItem);

  async function save() {
    await api.put('/api/apps/' + appItem.id, form);
    onChange();
    alert('Anleitungen gespeichert.');
  }

  return (
    <div className="card p-6 space-y-4">
      <h3 className="font-bold text-lg">Anleitungen</h3>
      <Textarea label="Anleitung zum Gebrauch" value={form.usageGuide} onChange={v => setForm({...form, usageGuide:v})} />
      <Textarea label="Installationsanleitung" value={form.installGuide} onChange={v => setForm({...form, installGuide:v})} />
      <Textarea label="Backup-Anleitung" value={form.backupGuide} onChange={v => setForm({...form, backupGuide:v})} />
      <Textarea label="Troubleshooting" value={form.troubleshooting} onChange={v => setForm({...form, troubleshooting:v})} />
      <button onClick={save} className="aok-green text-white px-4 py-2 rounded">Speichern</button>
    </div>
  );
}

function Documents({ appId, documents, onChange }) {
  const [file, setFile] = useState(null);
  const [form, setForm] = useState({
    title: '',
    category: 'Beschreibung',
    version: '1.0.0',
    note: ''
  });

  async function uploadDocument() {
    if (!file) {
      alert('Bitte eine Datei auswählen.');
      return;
    }

    await api.upload(`/api/apps/${appId}/documents`, file, form);

    setFile(null);
    setForm({ title: '', category: 'Beschreibung', version: '1.0.0', note: '' });
    onChange();
  }

  async function remove(id) {
    if (!confirm('Dokument wirklich löschen?')) return;
    await api.del('/api/documents/' + id);
    onChange();
  }

  return (
    <div className="space-y-4">
      <div className="card p-6">
        <h3 className="font-bold mb-4">Word- oder Dokumentationsdatei hochladen</h3>

        <div className="grid md:grid-cols-4 gap-4">
          <label className="block">
            <span className="text-sm font-semibold">Datei</span>
            <input
              type="file"
              accept=".docx,.doc,.pdf,.txt,.md"
              onChange={e => setFile(e.target.files[0] || null)}
              className="border rounded px-3 py-2 w-full mt-1"
            />
          </label>

          <Input label="Titel" value={form.title} onChange={v => setForm({...form, title:v})} />

          <Select label="Kategorie" value={form.category} onChange={v => setForm({...form, category:v})}
            options={[
              ['Beschreibung','Beschreibung'],
              ['Bedienungsanleitung','Bedienungsanleitung'],
              ['Installationsanleitung','Installationsanleitung'],
              ['Codes','Codes'],
              ['Backup','Backup'],
              ['Troubleshooting','Troubleshooting'],
              ['Sonstiges','Sonstiges']
            ]} />

          <Input label="Version" value={form.version} onChange={v => setForm({...form, version:v})} />
        </div>

        <Textarea label="Notiz" value={form.note} onChange={v => setForm({...form, note:v})} />

        <button onClick={uploadDocument} className="aok-green text-white px-4 py-2 rounded mt-4">
          Dokument hochladen
        </button>
      </div>

      <div className="card p-6 overflow-auto">
        <h3 className="font-bold mb-4">Hochgeladene Dokumente</h3>

        <table className="w-full text-sm">
          <thead>
            <tr className="text-left border-b">
              <th className="py-2">Kategorie</th>
              <th>Titel</th>
              <th>Version</th>
              <th>Datei</th>
              <th>Upload</th>
              <th>Aktion</th>
            </tr>
          </thead>
          <tbody>
            {documents.map(d => (
              <tr key={d.id} className="border-b">
                <td className="py-2">{d.category}</td>
                <td>{d.title}</td>
                <td>{d.version}</td>
                <td><a href={d.path} target="_blank" className="aok-green-text underline">{d.originalName}</a></td>
                <td>{new Date(d.createdAt).toLocaleString('de-DE')}</td>
                <td>
                  <button onClick={() => remove(d.id)} className="text-red-600 text-xs">löschen</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>

        {documents.length === 0 && (
          <p className="text-gray-500">Noch keine Dokumente hochgeladen.</p>
        )}
      </div>
    </div>
  );
}

function Versions({ appId, versions, onChange }) {
  const [form, setForm] = useState({
    version: '',
    date: new Date().toISOString().slice(0, 10),
    changeType: 'update',
    summary: '',
    details: ''
  });

  async function save() {
    await api.post(`/api/apps/${appId}/versions`, form);
    setForm({ version: '', date: new Date().toISOString().slice(0, 10), changeType: 'update', summary: '', details: '' });
    onChange();
  }

  return (
    <div className="space-y-4">
      <div className="card p-6">
        <h3 className="font-bold mb-4">Neue Version dokumentieren</h3>
        <div className="grid md:grid-cols-3 gap-4">
          <Input label="Version" value={form.version} onChange={v => setForm({...form, version:v})} />
          <Input label="Datum" type="date" value={form.date} onChange={v => setForm({...form, date:v})} />
          <Select label="Typ" value={form.changeType} onChange={v => setForm({...form, changeType:v})}
            options={['initial','update','bugfix','feature','security','docs'].map(x => [x,x])} />
        </div>
        <Textarea label="Kurzbeschreibung" value={form.summary} onChange={v => setForm({...form, summary:v})} />
        <Textarea label="Details" value={form.details} onChange={v => setForm({...form, details:v})} />
        <button onClick={save} className="aok-green text-white px-4 py-2 rounded">Speichern</button>
      </div>

      <div className="card p-6">
        <h3 className="font-bold mb-4">Versionshistorie</h3>
        {versions.map(v => (
          <div key={v.id} className="border-b py-3">
            <div className="font-bold">{v.version} <span className="text-xs text-gray-500">· {v.date} · {v.changeType}</span></div>
            <div>{v.summary}</div>
            {v.details && <div className="text-sm text-gray-600 whitespace-pre-wrap mt-1">{v.details}</div>}
          </div>
        ))}
      </div>
    </div>
  );
}

function CodeBlocks({ appId, codeBlocks, onChange }) {
  const [form, setForm] = useState({
    title: '',
    type: 'bash',
    filePath: '',
    description: '',
    code: ''
  });

  async function save() {
    await api.post(`/api/apps/${appId}/code-blocks`, form);
    setForm({ title: '', type: 'bash', filePath: '', description: '', code: '' });
    onChange();
  }

  return (
    <div className="space-y-4">
      <div className="card p-6">
        <h3 className="font-bold mb-4">Codeblock hinzufügen</h3>
        <div className="grid md:grid-cols-3 gap-4">
          <Input label="Titel" value={form.title} onChange={v => setForm({...form, title:v})} />
          <Select label="Typ" value={form.type} onChange={v => setForm({...form, type:v})}
            options={['bash','yaml','javascript','json','dockerfile','text'].map(x => [x,x])} />
          <Input label="Pfad / Datei" value={form.filePath} onChange={v => setForm({...form, filePath:v})} />
        </div>
        <Textarea label="Beschreibung" value={form.description} onChange={v => setForm({...form, description:v})} />
        <label className="block">
          <span className="text-sm font-semibold">Code</span>
          <textarea
            value={form.code || ''}
            onChange={e => setForm({...form, code:e.target.value})}
            className="code border rounded px-3 py-2 w-full mt-1 min-h-64"
          />
        </label>
        <button onClick={save} className="aok-green text-white px-4 py-2 rounded mt-4">Codeblock speichern</button>
      </div>

      <div className="space-y-4">
        {codeBlocks.map(c => (
          <div key={c.id} className="card p-6">
            <h3 className="font-bold">{c.title}</h3>
            <p className="text-xs text-gray-500">{c.type} · {c.filePath}</p>
            <p className="text-sm my-2 whitespace-pre-wrap">{c.description}</p>
            <pre className="bg-gray-100 p-3 rounded overflow-auto text-xs whitespace-pre-wrap">{c.code}</pre>
          </div>
        ))}
      </div>
    </div>
  );
}

function ExportDoc({ appId }) {
  const [result, setResult] = useState(null);

  async function create() {
    const r = await api.post(`/api/apps/${appId}/export-doc`, {});
    setResult(r);
  }

  return (
    <div className="card p-6">
      <h3 className="font-bold mb-4">Dokumentation exportieren</h3>
      <p className="text-sm text-gray-600 mb-4">
        Erstellt eine HTML-Dokumentation mit App-Daten, Versionen, Anleitungen, hochgeladenen Dokumenten und Codeblöcken.
      </p>
      <button onClick={create} className="aok-green text-white px-4 py-2 rounded">Dokumentation erstellen</button>

      {result && (
        <div className="mt-4 bg-green-50 border-l-4 border-green-600 p-4">
          <p className="font-bold">Export erstellt</p>
          <a className="underline aok-green-text" href={result.downloadUrl} target="_blank">Dokumentation öffnen</a>
        </div>
      )}
    </div>
  );
}

function Input({ label, value, onChange, type = 'text' }) {
  return (
    <label className="block">
      <span className="text-sm font-semibold">{label}</span>
      <input
        type={type}
        value={value || ''}
        onChange={e => onChange(e.target.value)}
        className="border rounded px-3 py-2 w-full mt-1"
      />
    </label>
  );
}

function Textarea({ label, value, onChange }) {
  return (
    <label className="block mt-4">
      <span className="text-sm font-semibold">{label}</span>
      <textarea
        value={value || ''}
        onChange={e => onChange(e.target.value)}
        className="border rounded px-3 py-2 w-full mt-1 min-h-32"
      />
    </label>
  );
}

function Select({ label, value, onChange, options }) {
  return (
    <label className="block">
      <span className="text-sm font-semibold">{label}</span>
      <select value={value || ''} onChange={e => onChange(e.target.value)} className="border rounded px-3 py-2 w-full mt-1">
        {options.map(([v, l]) => <option key={v} value={v}>{l}</option>)}
      </select>
    </label>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
