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

function App() {
  const [view, setView] = useState('dashboard');
  const [selectedBookId, setSelectedBookId] = useState(null);
  const [health, setHealth] = useState({ ollama: false, models: [] });

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

  function openBook(id) {
    setSelectedBookId(id);
    setView('book');
  }

  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">✍️ BookWriter</h1>
          <div className="text-sm opacity-80">Bücher lokal mit Ollama planen, schreiben und exportieren</div>
        </div>
        <div className={`px-3 py-1 rounded text-xs ${health.ollama ? 'bg-green-700' : 'bg-red-700'}`}>
          Ollama: {health.ollama ? '✓ verbunden' : '✗ nicht erreichbar'}
        </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 === 'books'} onClick={() => setView('books')}>Bücher</NavButton>
        {selectedBookId && <NavButton active={view === 'book'} onClick={() => setView('book')}>Buchprojekt</NavButton>}
      </nav>

      <main className="container mx-auto max-w-7xl p-6">
        {view === 'dashboard' && <Dashboard onOpen={openBook} />}
        {view === 'books' && <Books onOpen={openBook} health={health} />}
        {view === 'book' && selectedBookId && <BookDetail bookId={selectedBookId} onBack={() => setView('books')} health={health} />}
      </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 [books, setBooks] = useState([]);

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

  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-3 gap-4">
        <Stat title="Bücher" value={data.counts.books} />
        <Stat title="Kapitel" value={data.counts.chapters} />
        <Stat title="Wörter" value={Number(data.counts.words || 0).toLocaleString('de-DE')} />
      </div>

      <div className="grid lg:grid-cols-2 gap-4">
        <div className="card p-6">
          <h3 className="font-bold mb-4">Buchprojekte</h3>
          <div className="space-y-2">
            {books.slice(0, 10).map(b => (
              <div key={b.id} onClick={() => onOpen(b.id)} className="border-b pb-2 cursor-pointer hover:bg-gray-50 p-2 rounded">
                <div className="font-semibold">{b.title}</div>
                <div className="text-xs text-gray-500">{b.genre} · {b.chaptersCount} Kapitel · {Number(b.words || 0).toLocaleString('de-DE')} Wörter</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 Books({ onOpen, health }) {
  const [books, setBooks] = useState([]);
  const [show, setShow] = useState(false);
  const [form, setForm] = useState({
    title: '',
    genre: '',
    targetAudience: '',
    perspective: 'Dritte Person',
    style: '',
    targetLength: '',
    chapterLength: 'mittel',
    idea: '',
    model: ''
  });

  async function load() {
    setBooks(await api.get('/api/books'));
  }

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

  useEffect(() => {
    if (!form.model && health.models && health.models.length > 0) {
      setForm(f => ({ ...f, model: health.models.includes('llama3.1:8b') ? 'llama3.1:8b' : health.models[0] }));
    }
  }, [health]);

  async function create() {
    await api.post('/api/books', form);
    setForm({
      title: '',
      genre: '',
      targetAudience: '',
      perspective: 'Dritte Person',
      style: '',
      targetLength: '',
      chapterLength: 'mittel',
      idea: '',
      model: health.models?.includes('llama3.1:8b') ? 'llama3.1:8b' : ''
    });
    setShow(false);
    load();
  }

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

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

      {show && (
        <div className="card p-6">
          <h3 className="font-bold mb-4">Neues Buchprojekt</h3>

          <div className="grid md:grid-cols-3 gap-4">
            <Input label="Titel / Arbeitstitel" value={form.title} onChange={v => setForm({...form, title:v})} />
            <Input label="Genre" value={form.genre} onChange={v => setForm({...form, genre:v})} />
            <Input label="Zielgruppe" value={form.targetAudience} onChange={v => setForm({...form, targetAudience:v})} />
            <Select label="Perspektive" value={form.perspective} onChange={v => setForm({...form, perspective:v})}
              options={['Dritte Person','Ich-Perspektive','Auktorial','Personal','Sachbuch-Stimme'].map(x => [x,x])} />
            <Input label="Stil / Ton" value={form.style} onChange={v => setForm({...form, style:v})} />
            <Input label="Umfangsziel" value={form.targetLength} onChange={v => setForm({...form, targetLength:v})} />
            <Select label="Kapitellänge" value={form.chapterLength} onChange={v => setForm({...form, chapterLength:v})}
              options={['kurz','mittel','lang'].map(x => [x,x])} />
            <Select label="Ollama-Modell" value={form.model} onChange={v => setForm({...form, model:v})}
              options={(health.models || ['llama3.1:8b']).map(x => [x,x])} />
          </div>

          <Textarea label="Buchidee / Briefing" value={form.idea} onChange={v => setForm({...form, idea: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">
        {books.map(b => (
          <div key={b.id} onClick={() => onOpen(b.id)} className="card p-4 cursor-pointer hover:shadow-lg transition">
            <div className="flex justify-between gap-2">
              <h3 className="font-bold text-lg">{b.title}</h3>
              <span className="text-xs bg-gray-100 px-2 py-1 rounded h-fit">{b.status}</span>
            </div>
            <p className="text-sm text-gray-600">{b.genre || 'ohne Genre'}</p>
            <p className="text-xs text-gray-500 mt-2">{b.chaptersCount} Kapitel · {Number(b.words || 0).toLocaleString('de-DE')} Wörter</p>
            <button onClick={(e) => remove(b.id, e)} className="text-red-600 text-xs mt-3">löschen</button>
          </div>
        ))}
      </div>
    </div>
  );
}

function BookDetail({ bookId, onBack, health }) {
  const [bundle, setBundle] = useState(null);
  const [tab, setTab] = useState('overview');
  const [job, setJob] = useState(null);
  const [busy, setBusy] = useState(false);
  const [exportResult, setExportResult] = useState(null);
  const [error, setError] = useState('');

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

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

  async function poll(jobId) {
    try {
      const status = await api.get('/api/jobs/' + jobId);
      setJob(status);

      if (status.status === 'done') {
        setBusy(false);
        load();
        return;
      }

      if (status.status === 'error') {
        setError(status.error || 'Job fehlgeschlagen.');
        setBusy(false);
        return;
      }

      setTimeout(() => poll(jobId), 4000);
    } catch (e) {
      setError(e.message);
      setBusy(false);
    }
  }

  async function startOutline() {
    setError('');
    setBusy(true);
    const model = bundle.book.model || 'llama3.1:8b';
    const started = await api.post(`/api/books/${bookId}/generate-outline-job`, { model });
    setJob(started);
    setTimeout(() => poll(started.jobId), 2000);
  }

  async function startAll() {
    setError('');
    setBusy(true);
    const model = bundle.book.model || 'llama3.1:8b';
    const started = await api.post(`/api/books/${bookId}/generate-all-job`, { model, onlyEmpty: true });
    setJob(started);
    setTimeout(() => poll(started.jobId), 2000);
  }

  async function exportDoc() {
    const result = await api.post(`/api/books/${bookId}/export-doc`, {});
    setExportResult(result);
  }

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

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

      <div className="card p-6">
        <h2 className="text-2xl font-bold">{bundle.book.title}</h2>
        <p className="text-gray-600">{bundle.book.genre} · {bundle.chapters.length} Kapitel</p>
      </div>

      {job && (
        <div className="card p-6 border-l-4 border-blue-600">
          <h3 className="font-bold mb-2">Job-Fortschritt</h3>
          <p className="text-sm text-gray-700 mb-2">
            Status: {job.status} · {job.current} von {job.total} · {job.progress}%
          </p>
          <div className="w-full bg-gray-200 rounded h-4 overflow-hidden">
            <div className="aok-green h-4" style={{ width: `${job.progress || 0}%` }}></div>
          </div>
          <p className="text-xs text-gray-500 mt-2">{job.message}</p>
        </div>
      )}

      {error && (
        <div className="bg-red-50 border-l-4 border-red-500 p-4 text-red-800">
          {error}
        </div>
      )}

      <div className="bg-white border rounded p-2 flex gap-2 overflow-x-auto">
        {[
          ['overview','Übersicht'],
          ['edit','Briefing'],
          ['outline','Gliederung'],
          ['chapters','Kapitel'],
          ['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} startOutline={startOutline} startAll={startAll} busy={busy} />}
      {tab === 'edit' && <EditBook book={bundle.book} health={health} onChange={load} />}
      {tab === 'outline' && <Outline book={bundle.book} startOutline={startOutline} busy={busy} onChange={load} />}
      {tab === 'chapters' && <Chapters bundle={bundle} onChange={load} setJob={setJob} setBusy={setBusy} setError={setError} poll={poll} />}
      {tab === 'export' && <ExportBook exportDoc={exportDoc} result={exportResult} />}
    </div>
  );
}

function Overview({ bundle, startOutline, startAll, busy }) {
  const words = bundle.chapters.reduce((sum, c) => sum + Number(c.stats?.words || 0), 0);

  return (
    <div className="grid lg:grid-cols-2 gap-4">
      <div className="card p-6">
        <h3 className="font-bold mb-3">Projekt</h3>
        <p><strong>Genre:</strong> {bundle.book.genre}</p>
        <p><strong>Zielgruppe:</strong> {bundle.book.targetAudience}</p>
        <p><strong>Perspektive:</strong> {bundle.book.perspective}</p>
        <p><strong>Stil:</strong> {bundle.book.style}</p>
        <p><strong>Modell:</strong> {bundle.book.model}</p>
        <p><strong>Wörter:</strong> {words.toLocaleString('de-DE')}</p>
      </div>

      <div className="card p-6">
        <h3 className="font-bold mb-3">Aktionen</h3>
        <div className="space-y-3">
          <button onClick={startOutline} disabled={busy} className="aok-green text-white px-4 py-2 rounded w-full disabled:opacity-50">
            Gliederung mit Ollama erstellen
          </button>
          <button onClick={startAll} disabled={busy} className="bg-gray-800 text-white px-4 py-2 rounded w-full disabled:opacity-50">
            Alle leeren Kapitel schreiben lassen
          </button>
        </div>
      </div>

      <div className="card p-6 lg:col-span-2">
        <h3 className="font-bold mb-3">Buchidee</h3>
        <p className="whitespace-pre-wrap">{bundle.book.idea}</p>
      </div>
    </div>
  );
}

function EditBook({ book, health, onChange }) {
  const [form, setForm] = useState(book);

  async function save() {
    await api.put('/api/books/' + book.id, form);
    onChange();
    alert('Buchprojekt gespeichert.');
  }

  return (
    <div className="card p-6 space-y-4">
      <h3 className="font-bold text-lg">Briefing bearbeiten</h3>

      <div className="grid md:grid-cols-3 gap-4">
        <Input label="Titel" value={form.title} onChange={v => setForm({...form, title:v})} />
        <Input label="Genre" value={form.genre} onChange={v => setForm({...form, genre:v})} />
        <Input label="Zielgruppe" value={form.targetAudience} onChange={v => setForm({...form, targetAudience:v})} />
        <Input label="Perspektive" value={form.perspective} onChange={v => setForm({...form, perspective:v})} />
        <Input label="Stil" value={form.style} onChange={v => setForm({...form, style:v})} />
        <Input label="Umfangsziel" value={form.targetLength} onChange={v => setForm({...form, targetLength:v})} />
        <Input label="Kapitellänge" value={form.chapterLength} onChange={v => setForm({...form, chapterLength:v})} />
        <Select label="Ollama-Modell" value={form.model} onChange={v => setForm({...form, model:v})}
          options={(health.models || ['llama3.1:8b']).map(x => [x,x])} />
      </div>

      <Textarea label="Buchidee / Briefing" value={form.idea} onChange={v => setForm({...form, idea:v})} />
      <Textarea label="Gliederung" value={form.outline} onChange={v => setForm({...form, outline: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 Outline({ book, startOutline, busy, onChange }) {
  const [outline, setOutline] = useState(book.outline || '');

  useEffect(() => setOutline(book.outline || ''), [book.outline]);

  async function save() {
    await api.put('/api/books/' + book.id, { outline });
    onChange();
    alert('Gliederung gespeichert.');
  }

  return (
    <div className="card p-6">
      <h3 className="font-bold text-lg mb-4">Gliederung</h3>
      <button onClick={startOutline} disabled={busy} className="aok-green text-white px-4 py-2 rounded mb-4 disabled:opacity-50">
        Gliederung mit Ollama erstellen
      </button>
      <textarea value={outline} onChange={e => setOutline(e.target.value)} className="border rounded p-3 w-full min-h-96 mono" />
      <button onClick={save} className="aok-green text-white px-4 py-2 rounded mt-4">Gliederung speichern</button>
    </div>
  );
}

function Chapters({ bundle, onChange, setJob, setBusy, setError, poll }) {
  const [form, setForm] = useState({
    number: bundle.chapters.length + 1,
    title: '',
    note: ''
  });
  const [selected, setSelected] = useState(null);

  async function create() {
    await api.post(`/api/books/${bundle.book.id}/chapters`, form);
    setForm({ number: bundle.chapters.length + 2, title: '', note: '' });
    onChange();
  }

  async function generate(chapter) {
    setError('');
    setBusy(true);

    const localJob = {
      jobId: '',
      status: 'queued',
      current: 0,
      total: 2,
      progress: 0,
      message: `Kapitel wird vorbereitet: ${chapter.title}`
    };

    setJob(localJob);

    try {
      const started = await api.post(`/api/chapters/${chapter.id}/generate-job`, {
        model: bundle.book.model
      });

      setJob(started);
      setTimeout(() => poll(started.jobId), 2000);
    } catch (e) {
      setError(e.message);
      setBusy(false);
      setJob(null);
    }
  }

  async function saveChapter(chapter) {
    await api.put('/api/chapters/' + chapter.id, chapter);
    onChange();
    alert('Kapitel gespeichert.');
  }

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

  return (
    <div className="space-y-4">
      <div className="card p-6">
        <h3 className="font-bold mb-4">Kapitel anlegen</h3>
        <div className="grid md:grid-cols-3 gap-4">
          <Input label="Nummer" type="number" value={form.number} onChange={v => setForm({...form, number:v})} />
          <Input label="Titel" value={form.title} onChange={v => setForm({...form, title:v})} />
          <Input label="Notiz / Kapitelbriefing" value={form.note} onChange={v => setForm({...form, note:v})} />
        </div>
        <button onClick={create} className="aok-green text-white px-4 py-2 rounded mt-4">Kapitel anlegen</button>
      </div>

      <div className="grid lg:grid-cols-3 gap-4">
        <div className="card p-4 lg:col-span-1">
          <h3 className="font-bold mb-3">Kapitel</h3>
          {bundle.chapters.map(c => (
            <div key={c.id} onClick={() => setSelected({...c})} className="border-b py-2 cursor-pointer hover:bg-gray-50">
              <div className="font-semibold">Kapitel {c.number}: {c.title}</div>
              <div className="text-xs text-gray-500">{c.status} · {Number(c.stats?.words || 0).toLocaleString('de-DE')} Wörter</div>
              <button onClick={(e) => { e.stopPropagation(); generate(c); }} className="text-xs aok-green-text underline mr-3">schreiben lassen</button>
              <button onClick={(e) => { e.stopPropagation(); remove(c.id); }} className="text-xs text-red-600 underline">löschen</button>
            </div>
          ))}
        </div>

        <div className="card p-4 lg:col-span-2">
          {!selected && <p className="text-gray-500">Kapitel auswählen.</p>}

          {selected && (
            <div>
              <div className="grid md:grid-cols-2 gap-4">
                <Input label="Kapitelnummer" type="number" value={selected.number} onChange={v => setSelected({...selected, number:v})} />
                <Input label="Titel" value={selected.title} onChange={v => setSelected({...selected, title:v})} />
              </div>
              <Textarea label="Kapitelnotiz" value={selected.note} onChange={v => setSelected({...selected, note:v})} />
              <Textarea label="Kapiteltext" value={selected.content} onChange={v => setSelected({...selected, content:v})} />
              <Textarea label="Zusammenfassung" value={selected.summary} onChange={v => setSelected({...selected, summary:v})} />
              <button onClick={() => saveChapter(selected)} className="aok-green text-white px-4 py-2 rounded mt-4">Kapitel speichern</button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function ExportBook({ exportDoc, result }) {
  return (
    <div className="card p-6">
      <h3 className="font-bold mb-4">Buch exportieren</h3>
      <p className="text-sm text-gray-600 mb-4">
        Exportiert alle Kapitel als Word-kompatibles .doc-Dokument.
      </p>
      <button onClick={exportDoc} className="aok-green text-white px-4 py-2 rounded">Buch als .doc exportieren</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 href={result.downloadUrl} target="_blank" className="underline aok-green-text">Dokument herunterladen</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 />);
