import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
import axios from 'axios';
import './styles.css';

const displayKey = (prefix) => prefix ? `${prefix}••••••••` : '••••••••••••';

function authHeaders(token) {
  return { Authorization: `Bearer ${token}` };
}

const fmtK = (n) => { const k = n / 1000; return k % 1 === 0 ? `${k}k` : `${k.toFixed(1)}k`; };

function QuotaBar({ used, limit, isToken = false, since = null }) {
  const fmt = isToken ? fmtK : (n) => n.toLocaleString('de-DE');
  const sinceLabel = since
    ? new Date(since).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' })
    : null;

  if (limit == null) return (
    <div className="quota-cell">
      <span className="quota-unlimited">∞</span>
      {sinceLabel && <span className="quota-since">seit {sinceLabel}</span>}
    </div>
  );

  const pct = Math.min(100, (used / limit) * 100);
  const color = pct >= 90 ? '#e74c3c' : pct >= 70 ? '#e67e22' : '#27ae60';
  return (
    <div className="quota-cell">
      <span className="quota-label">{fmt(used)} / {fmt(limit)}</span>
      <div className="progress-bar">
        <div className="progress-fill" style={{ width: `${pct}%`, backgroundColor: color }} />
      </div>
      {sinceLabel && <span className="quota-since">seit {sinceLabel}</span>}
    </div>
  );
}

function Login({ onLogin }) {
  const [password, setPassword] = useState('');
  const [error, setError] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError(null);
    try {
      await axios.get('/api/api-keys', { headers: authHeaders(password) });
      sessionStorage.setItem('admin_password', password);
      onLogin(password);
    } catch {
      setError('Ungültiges Passwort.');
    }
  };

  return (
    <div className="container">
      <h1>Ollama Proxy Admin</h1>
      <form onSubmit={handleSubmit} className="login-form">
        <label>Passwort</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="Admin-Passwort eingeben"
          autoFocus
        />
        {error && <div className="error">{error}</div>}
        <button type="submit">Anmelden</button>
      </form>
    </div>
  );
}

const EMPTY_KEY_FORM = {
  name: '', expires_at: '', daily_tokens: '', monthly_tokens: '', daily_requests: '', monthly_requests: '',
};

function SettingsSection({ password }) {
  const [settings, setSettings] = useState(null);
  const [availableModels, setAvailableModels] = useState([]);
  const [modelsLoading, setModelsLoading] = useState(false);
  const [ollamaReachable, setOllamaReachable] = useState(true);
  const [proxyEndpoint, setProxyEndpoint] = useState(null);
  const [saved, setSaved] = useState(false);
  const [error, setError] = useState(null);

  const fetchModels = async (url, currentModel) => {
    setModelsLoading(true);
    try {
      const res = await axios.get('/api/ollama-models', {
        headers: authHeaders(password),
        params: url ? { url } : {},
      });
      const { models, reachable } = res.data;
      setOllamaReachable(reachable);
      setAvailableModels(models);
      if (models.length > 0 && !models.includes(currentModel)) {
        setSettings(s => ({ ...s, default_model: models[0] }));
      }
    } catch {
      setOllamaReachable(false);
      setAvailableModels([]);
    } finally {
      setModelsLoading(false);
    }
  };

  useEffect(() => {
    const headers = authHeaders(password);
    Promise.all([
      axios.get('/api/settings', { headers }),
      axios.get('/api/proxy-info', { headers }),
    ]).then(([settingsRes, proxyRes]) => {
      const s = settingsRes.data;
      setSettings(s);
      setProxyEndpoint(proxyRes.data.endpoint);
      fetchModels(s.ollama_url, s.default_model);
    }).catch(() => setError('Einstellungen konnten nicht geladen werden.'));
  }, []);

  const handleSave = async (e) => {
    e.preventDefault();
    setError(null);
    setSaved(false);
    try {
      await axios.put('/api/settings', settings, { headers: authHeaders(password) });
      setSaved(true);
      setTimeout(() => setSaved(false), 3000);
    } catch {
      setError('Fehler beim Speichern.');
    }
  };

  if (!settings) return <div>Laden...</div>;

  return (
    <section>
      <h2>Einstellungen</h2>
      <form onSubmit={handleSave} className="settings-form">
        <div className="settings-row">
          <label>Proxy-Endpunkt</label>
          <span className="settings-value">
            {proxyEndpoint ?? '…'}
            <small> (Änderung erfordert Neustart)</small>
          </span>
        </div>
        <div className="settings-row">
          <label>Ollama-Endpunkt</label>
          <div className="settings-input-wrap">
            <input
              type="url"
              value={settings.ollama_url}
              onChange={(e) => setSettings({ ...settings, ollama_url: e.target.value })}
              onBlur={(e) => fetchModels(e.target.value, settings.default_model)}
              placeholder="http://localhost:11434"
              required
            />
            {!ollamaReachable && !modelsLoading && (
              <div className="warning">⚠ Ollama nicht erreichbar unter {settings.ollama_url}</div>
            )}
          </div>
        </div>
        <div className="settings-row">
          <label>Standard-Modell</label>
          {modelsLoading ? (
            <span className="settings-value">Lade Modelle…</span>
          ) : availableModels.length > 0 ? (
            <select
              value={settings.default_model}
              onChange={(e) => setSettings({ ...settings, default_model: e.target.value })}
            >
              {availableModels.map(m => <option key={m} value={m}>{m}</option>)}
            </select>
          ) : (
            <input
              type="text"
              value={settings.default_model}
              onChange={(e) => setSettings({ ...settings, default_model: e.target.value })}
              placeholder="llama3"
              required
            />
          )}
        </div>
        {error && <div className="error">{error}</div>}
        {saved && <div className="success">Gespeichert.</div>}
        <button type="submit">Speichern</button>
      </form>
    </section>
  );
}

function App() {
  const [password, setPassword] = useState(() => sessionStorage.getItem('admin_password'));
  const [apiKeys, setApiKeys] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [newKey, setNewKey] = useState(null);
  const [form, setForm] = useState(EMPTY_KEY_FORM);
  const [creating, setCreating] = useState(false);
  const [editKey, setEditKey] = useState(null);
  const [editForm, setEditForm] = useState({});

  useEffect(() => {
    if (!password) { setLoading(false); return; }
    fetchApiKeys().finally(() => setLoading(false));
  }, [password]);

  const fetchApiKeys = async () => {
    try {
      const res = await axios.get('/api/api-keys', { headers: authHeaders(password) });
      setApiKeys(res.data);
    } catch {
      setError('API-Keys konnten nicht geladen werden.');
    }
  };

  const handleCreate = async (e) => {
    e.preventDefault();
    setCreating(true);
    try {
      const payload = { name: form.name };
      if (form.expires_at)       payload.expires_at       = new Date(form.expires_at).toISOString();
      if (form.daily_tokens)     payload.daily_tokens     = Number(form.daily_tokens) * 1000;
      if (form.monthly_tokens)   payload.monthly_tokens   = Number(form.monthly_tokens) * 1000;
      if (form.daily_requests)   payload.daily_requests   = Number(form.daily_requests);
      if (form.monthly_requests) payload.monthly_requests = Number(form.monthly_requests);

      const res = await axios.post('/api/api-keys', payload, { headers: authHeaders(password) });
      setNewKey(res.data.plaintext_key);
      setForm(EMPTY_KEY_FORM);
      await fetchApiKeys();
    } catch {
      setError('Fehler beim Erstellen des API-Keys.');
    } finally {
      setCreating(false);
    }
  };

  const handleDeactivate = async (id) => {
    try {
      await axios.put(`/api/api-keys/${id}/deactivate`, {}, { headers: authHeaders(password) });
      await fetchApiKeys();
    } catch {
      setError('Fehler beim Deaktivieren.');
    }
  };

  const handleActivate = async (id) => {
    try {
      await axios.put(`/api/api-keys/${id}/activate`, {}, { headers: authHeaders(password) });
      await fetchApiKeys();
    } catch {
      setError('Fehler beim Aktivieren.');
    }
  };

  const handleDelete = async (id, name) => {
    if (!window.confirm(`API-Key "${name}" wirklich löschen?`)) return;
    try {
      await axios.delete(`/api/api-keys/${id}`, { headers: authHeaders(password) });
      if (editKey?.id === id) setEditKey(null);
      await fetchApiKeys();
    } catch {
      setError('Fehler beim Löschen.');
    }
  };

  const handleEdit = (key) => {
    setEditKey(key);
    setEditForm({
      daily_tokens:     key.daily_tokens    != null ? key.daily_tokens / 1000    : '',
      monthly_tokens:   key.monthly_tokens  != null ? key.monthly_tokens / 1000  : '',
      daily_requests:   key.daily_requests  ?? '',
      monthly_requests: key.monthly_requests ?? '',
    });
  };

  const handleSaveEdit = async (e) => {
    e.preventDefault();
    try {
      const payload = {
        daily_tokens:     editForm.daily_tokens     !== '' ? Number(editForm.daily_tokens) * 1000     : null,
        monthly_tokens:   editForm.monthly_tokens   !== '' ? Number(editForm.monthly_tokens) * 1000   : null,
        daily_requests:   editForm.daily_requests   !== '' ? Number(editForm.daily_requests)   : null,
        monthly_requests: editForm.monthly_requests !== '' ? Number(editForm.monthly_requests) : null,
      };
      await axios.patch(`/api/api-keys/${editKey.id}/quota`, payload, { headers: authHeaders(password) });
      setEditKey(null);
      await fetchApiKeys();
    } catch {
      setError('Fehler beim Speichern der Limits.');
    }
  };

  const logout = () => {
    sessionStorage.removeItem('admin_password');
    setPassword(null);
  };

  if (!password) return <Login onLogin={setPassword} />;
  if (loading) return <div>Laden...</div>;
  if (error) return <div className="error">{error}</div>;

  return (
    <div className="container">
      <div className="header">
        <h1>Ollama Proxy Admin</h1>
        <button onClick={logout}>Abmelden</button>
      </div>

      <SettingsSection password={password} />

      <section>
        <h2>Neuer API-Key</h2>
        <form onSubmit={handleCreate} className="create-form">
          <div className="edit-form">
            <label className="create-name">
              Name
              <small>&nbsp;</small>
              <input
                value={form.name}
                onChange={(e) => setForm({ ...form, name: e.target.value })}
                required
                placeholder="z. B. alice"
              />
            </label>
            <label className="create-date">
              Ablaufdatum
              <small>leer = unbegrenzt</small>
              <input
                type="date"
                value={form.expires_at}
                onChange={(e) => setForm({ ...form, expires_at: e.target.value })}
              />
            </label>
            <div className="create-btn-wrap">
              <button type="submit" disabled={creating} className="btn-save">Erstellen</button>
            </div>
          </div>
          <div className="edit-form">
            <label>
              Tokens/Tag (k)
              <small>leer = unbegrenzt</small>
              <input
                type="number"
                min="0"
                placeholder="∞"
                value={form.daily_tokens}
                onChange={(e) => setForm({ ...form, daily_tokens: e.target.value })}
              />
            </label>
            <label>
              Tokens/Monat (k)
              <small>leer = unbegrenzt</small>
              <input
                type="number"
                min="0"
                placeholder="∞"
                value={form.monthly_tokens}
                onChange={(e) => setForm({ ...form, monthly_tokens: e.target.value })}
              />
            </label>
            <label>
              Requests/Tag
              <small>leer = unbegrenzt</small>
              <input
                type="number"
                min="0"
                placeholder="∞"
                value={form.daily_requests}
                onChange={(e) => setForm({ ...form, daily_requests: e.target.value })}
              />
            </label>
            <label>
              Requests/Monat
              <small>leer = unbegrenzt</small>
              <input
                type="number"
                min="0"
                placeholder="∞"
                value={form.monthly_requests}
                onChange={(e) => setForm({ ...form, monthly_requests: e.target.value })}
              />
            </label>
          </div>
        </form>
        {newKey && (
          <div className="new-key-box">
            <strong>Neuer Key (nur einmal sichtbar):</strong>
            <code>{newKey}</code>
            <button onClick={() => setNewKey(null)}>✕</button>
          </div>
        )}
      </section>

      <section>
        <h2>API Keys</h2>
        <table>
          <thead>
            <tr>
              <th></th>
              <th>Name</th>
              <th>Key</th>
              <th>Läuft ab</th>
              <th className="th-quota">Tokens/Tag</th>
              <th className="th-quota">Tokens/Monat</th>
              <th className="th-quota">Req/Tag</th>
              <th className="th-quota">Req/Monat</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {apiKeys.map(key => (
              <tr key={key.id} className={editKey?.id === key.id ? 'row-editing' : ''}>
                <td className="td-status">
                  <span className={key.is_active ? 'status-active' : 'status-inactive'} title={key.is_active ? 'Aktiv' : 'Inaktiv'}>●</span>
                </td>
                <td>{key.name}</td>
                <td>{displayKey(key.key_prefix)}</td>
                <td>{key.expires_at ? new Date(key.expires_at).toLocaleDateString('de-DE', { timeZone: 'Europe/Berlin' }) : '∞'}</td>
                <td><QuotaBar used={key.tokens_used_today} limit={key.daily_tokens} isToken since={key.daily_reset_at} /></td>
                <td><QuotaBar used={key.tokens_used_month} limit={key.monthly_tokens} isToken since={key.monthly_reset_at} /></td>
                <td><QuotaBar used={key.requests_today} limit={key.daily_requests} since={key.daily_reset_at} /></td>
                <td><QuotaBar used={key.requests_month} limit={key.monthly_requests} since={key.monthly_reset_at} /></td>
                <td className="action-cell">
                  <button className="btn-icon btn-icon-edit" data-tooltip="Bearbeiten" onClick={() => handleEdit(key)}>✏</button>
                  {key.is_active ? (
                    <button className="btn-icon btn-icon-warn" data-tooltip="Deaktivieren" onClick={() => handleDeactivate(key.id)}>⏸</button>
                  ) : (
                    <button className="btn-icon btn-icon-ok" data-tooltip="Aktivieren" onClick={() => handleActivate(key.id)}>▶</button>
                  )}
                  <button className="btn-icon btn-icon-danger" data-tooltip="Löschen" onClick={() => handleDelete(key.id, key.name)}>✕</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>

        {editKey && (
          <div className="edit-section">
            <h3>Limits bearbeiten: <em>{editKey.name}</em></h3>
            <form onSubmit={handleSaveEdit} className="edit-form">
              <label>
                Tokens/Tag (k)
                <small>leer = unbegrenzt</small>
                <input
                  type="number"
                  min="0"
                  value={editForm.daily_tokens}
                  onChange={(e) => setEditForm({ ...editForm, daily_tokens: e.target.value })}
                  placeholder="∞"
                />
              </label>
              <label>
                Tokens/Monat (k)
                <small>leer = unbegrenzt</small>
                <input
                  type="number"
                  min="0"
                  value={editForm.monthly_tokens}
                  onChange={(e) => setEditForm({ ...editForm, monthly_tokens: e.target.value })}
                  placeholder="∞"
                />
              </label>
              <label>
                Requests/Tag
                <small>leer = unbegrenzt</small>
                <input
                  type="number"
                  min="0"
                  value={editForm.daily_requests}
                  onChange={(e) => setEditForm({ ...editForm, daily_requests: e.target.value })}
                  placeholder="∞"
                />
              </label>
              <label>
                Requests/Monat
                <small>leer = unbegrenzt</small>
                <input
                  type="number"
                  min="0"
                  value={editForm.monthly_requests}
                  onChange={(e) => setEditForm({ ...editForm, monthly_requests: e.target.value })}
                  placeholder="∞"
                />
              </label>
              <div className="edit-actions">
                <button type="submit" className="btn-save">Speichern</button>
                <button type="button" className="btn-cancel" onClick={() => setEditKey(null)}>Abbrechen</button>
              </div>
            </form>
          </div>
        )}
      </section>
    </div>
  );
}

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