'use client';

import { useCallback, useEffect, useState } from 'react';

interface Settings {
  provider: 'openai' | 'anthropic' | 'ollama';
  apiKeys: { openai: string; anthropic: string };
  ollamaBase: string;
  models: { openai: string; anthropic: string; ollama: string };
  synthesisPrompt: string;
}

interface KeySource {
  openai: boolean;
  anthropic: boolean;
  ollama: boolean;
}

export default function SettingsForm() {
  const [settings, setSettings] = useState<Settings | null>(null);
  const [keyFromDb, setKeyFromDb] = useState<KeySource | null>(null);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [saveMsg, setSaveMsg] = useState<{ ok: boolean; text: string } | null>(null);
  const [testMsg, setTestMsg] = useState<{ ok: boolean; text: string } | null>(null);
  const [testing, setTesting] = useState(false);

  const adminHeaders = useCallback(
    () => ({
      'x-admin-key': sessionStorage.getItem('mb_admin_key') ?? '',
      'Content-Type': 'application/json',
    }),
    [],
  );

  useEffect(() => {
    (async () => {
      try {
        const res = await fetch('/api/settings', {
          headers: { 'x-admin-key': sessionStorage.getItem('mb_admin_key') ?? '' },
        });
        const data = await res.json();
        if (!res.ok) throw new Error(data.error ?? 'load failed');
        setSettings(data.settings as Settings);
        setKeyFromDb(data.keySources as KeySource);
      } catch (e) {
        setLoadError(e instanceof Error ? e.message : 'load failed');
      }
    })();
  }, []);

  if (loadError) {
    return <p className="text-sm text-red-700">Could not load settings: {loadError}</p>;
  }
  if (!settings || !keyFromDb) {
    return <p className="text-sm text-ink-500">Loading…</p>;
  }

  const prompt: Settings = {
    provider: settings.provider,
    apiKeys: { ...settings.apiKeys },
    ollamaBase: settings.ollamaBase ?? 'http://localhost:11434',
    models: { ...settings.models },
    synthesisPrompt: settings.synthesisPrompt,
  };

  function patch<K extends keyof Settings>(key: K, value: Settings[K]) {
    setSettings((s) => (s ? { ...s, [key]: value } : s));
    setSaveMsg(null);
  }

  async function save(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    setSaveMsg(null);
    setTestMsg(null);
    try {
      const res = await fetch('/api/settings', {
        method: 'PUT',
        headers: adminHeaders(),
        body: JSON.stringify(prompt),
      });
      const data = await res.json();
      setSaveMsg({ ok: res.ok, text: res.ok ? 'Settings saved.' : (data.error ?? 'save failed') });
      if (res.ok) {
        setKeyFromDb(data.keySources as KeySource);
      }
    } catch {
      setSaveMsg({ ok: false, text: 'Network error' });
    } finally {
      setSaving(false);
    }
  }

  async function test() {
    setTesting(true);
    setTestMsg(null);
    try {
      const res = await fetch('/api/settings/test', {
        method: 'POST',
        headers: adminHeaders(),
      });
      const data = await res.json();
      setTestMsg(
        data.ok
          ? { ok: true, text: data.message ?? 'Connection OK.' }
          : { ok: false, text: data.error ?? 'Test failed' },
      );
    } catch {
      setTestMsg({ ok: false, text: 'Network error' });
    } finally {
      setTesting(false);
    }
  }

  return (
    <form onSubmit={save} className="space-y-8">
      {/* Provider selection */}
      <section className="rounded-xl border border-ink-200 bg-white p-6">
        <h2 className="font-semibold text-ink-900">Active provider</h2>
        <div className="mt-4 grid grid-cols-3 gap-3">
          {(['openai', 'anthropic', 'ollama'] as const).map((p) => (
            <label
              key={p}
              className={`cursor-pointer rounded-lg border p-4 text-center transition ${
                prompt.provider === p
                  ? 'border-maple-600 bg-maple-50 ring-1 ring-maple-600'
                  : 'border-ink-200 hover:border-ink-300'
              }`}
            >
              <input
                type="radio"
                name="provider"
                value={p}
                checked={prompt.provider === p}
                onChange={() => patch('provider', p)}
                className="sr-only"
              />
              <span className="block text-sm font-semibold capitalize text-ink-900">{p}</span>
              <span className="mt-1 block text-xs text-ink-500">
                {p === 'openai' && 'GPT-4o / 4o-mini · cloud'}
                {p === 'anthropic' && 'Claude 3.5 Sonnet / Haiku · cloud'}
                {p === 'ollama' && 'Local · zero cost'}
              </span>
            </label>
          ))}
        </div>

        {/* Model */}
        <label className="mt-5 block text-sm">
          <span className="font-medium text-ink-800">Model</span>
          <input
            type="text"
            value={prompt.models[prompt.provider]}
            onChange={(e) =>
              patch('models', { ...prompt.models, [prompt.provider]: e.target.value })
            }
            list="model-suggestions"
            className="mt-1 w-full rounded-lg border border-ink-300 px-3 py-2 font-mono text-sm focus:border-maple-600 focus:outline-none"
          />
          <datalist id="model-suggestions">
            {prompt.provider === 'openai' && (
              <>
                <option value="gpt-4o-mini" />
                <option value="gpt-4o" />
              </>
            )}
            {prompt.provider === 'anthropic' && (
              <>
                <option value="claude-3-5-sonnet-latest" />
                <option value="claude-3-5-haiku-latest" />
              </>
            )}
            {prompt.provider === 'ollama' && (
              <>
                <option value="llama3.1:8b" />
                <option value="mistral:latest" />
                <option value="qwen2.5:14b" />
              </>
            )}
          </datalist>
        </label>

        {/* API key — only cloud providers */}
        {prompt.provider !== 'ollama' ? (
          <label className="mt-5 block text-sm">
            <span className="font-medium text-ink-800">
              {prompt.provider === 'openai' ? 'OpenAI' : 'Anthropic'} API key
              <span className="ml-2 rounded bg-ink-100 px-1.5 py-0.5 text-[11px] font-normal text-ink-500">
                {keyFromDb[prompt.provider] ? 'stored in database' : 'coming from env vars'}
              </span>
            </span>
            <input
              type="password"
              value={prompt.apiKeys[prompt.provider]}
              onChange={(e) =>
                patch('apiKeys', { ...prompt.apiKeys, [prompt.provider]: e.target.value })
              }
              placeholder={keyFromDb[prompt.provider] ? 'Enter to update (current is saved)' : 'sk-…'}
              className="mt-1 w-full rounded-lg border border-ink-300 px-3 py-2 font-mono text-sm focus:border-maple-600 focus:outline-none"
            />
            {!keyFromDb[prompt.provider] && (
              <span className="mt-1 block text-xs text-ink-400">
                Blank means &ldquo;use the env var&rdquo; (OPENAI_API_KEY /
                ANTHROPIC_API_KEY). Saving a value stores it encrypted-at-rest in
                SQLite (phone-in-BE BYO; see README on secret handling).
              </span>
            )}
          </label>
        ) : (
          <label className="mt-5 block text-sm">
            <span className="font-medium text-ink-800">Ollama base URL</span>
            <input
              type="url"
              value={prompt.ollamaBase}
              onChange={(e) => patch('ollamaBase', e.target.value)}
              placeholder="http://localhost:11434"
              className="mt-1 w-full rounded-lg border border-ink-300 px-3 py-2 font-mono text-sm focus:border-maple-600 focus:outline-none"
            />
            <span className="mt-1 block text-xs text-ink-400">
              For &ldquo;localhost&rdquo; you must also set OLLAMA_CORS=true on the
              Ollama host (see README).
            </span>
          </label>
        )}
      </section>

      {/* Synthesis prompt */}
      <section className="rounded-xl border border-ink-200 bg-white p-6">
        <h2 className="font-semibold text-ink-900">Synthesis system prompt</h2>
        <p className="mt-1 text-xs text-ink-500">
          This is the standing instruction the LLM receives on every
          synthesis. Edit to change tone, length, or structure — keep the
          &ldquo;strict JSON only&rdquo; contract so parsing stays reliable.
        </p>
        <textarea
          rows={12}
          value={prompt.synthesisPrompt}
          onChange={(e) => patch('synthesisPrompt', e.target.value)}
          className="mt-3 w-full rounded-lg border border-ink-300 px-3 py-2 font-mono text-[13px] leading-relaxed focus:border-maple-600 focus:outline-none"
        />
      </section>

      {/* Actions */}
      <section className="flex flex-wrap items-center gap-3">
        <button
          type="submit"
          disabled={saving}
          className="rounded-lg bg-maple-600 px-5 py-2.5 text-sm font-semibold text-white hover:bg-maple-700 disabled:opacity-50"
        >
          {saving ? 'Saving…' : 'Save settings'}
        </button>
        <button
          type="button"
          onClick={test}
          disabled={testing || saving}
          className="rounded-lg border border-ink-300 px-5 py-2.5 text-sm font-semibold text-ink-700 hover:bg-ink-100 disabled:opacity-50"
        >
          {testing ? 'Testing…' : 'Test connection'}
        </button>
        {saveMsg && (
          <span
            className={`text-sm ${saveMsg.ok ? 'text-emerald-700' : 'text-red-700'}`}
          >
            {saveMsg.text}
          </span>
        )}
      </section>

      {testMsg && (
        <p
          className={`rounded-lg border p-4 text-sm ${
            testMsg.ok
              ? 'border-emerald-300 bg-emerald-50 text-emerald-900'
              : 'border-red-300 bg-red-50 text-red-900'
          }`}
        >
          {testMsg.text}
        </p>
      )}
    </form>
  );
}
