import React, { useEffect, useMemo, useState } from "react";
import { testProvider } from "../utils/api";

const PROVIDERS = ["ollabridge", "openai", "claude", "watsonx", "ollama"];

const PROVIDER_LABELS = {
  ollabridge: "OllaBridge Cloud",
  openai: "OpenAI",
  claude: "Claude",
  watsonx: "Watsonx",
  ollama: "Ollama",
};

const AUTH_MODES = [
  { id: "device", label: "Device Pairing", icon: "📱" },
  { id: "apikey", label: "API Key", icon: "🔑" },
  { id: "local", label: "Local Trust", icon: "🏠" },
];

function LoadingState({ loadingMessage, loadingSlow, onRetry }) {
  return (
    <div className="settings-loading-shell">
      <div className="settings-loading-card">
        <div className="settings-loading-spinner" aria-hidden="true" />
        <h1>AI Providers</h1>
        <div className="settings-loading-subtitle">Admin / LLM Settings</div>
        <p className="settings-loading-text">{loadingMessage}</p>

        {loadingSlow && (
          <div className="settings-loading-slow">
            <p>
              This is taking longer than expected. The backend may still be
              starting or the settings endpoint may be slow.
            </p>
            <button
              type="button"
              className="settings-secondary-btn"
              onClick={onRetry}
            >
              Retry
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

export default function LlmSettings() {
  const [settings, setSettings] = useState(null);
  const [initialLoading, setInitialLoading] = useState(true);
  const [loadingSlow, setLoadingSlow] = useState(false);

  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  const [savedMsg, setSavedMsg] = useState("");

  const [modelsByProvider, setModelsByProvider] = useState({});
  const [modelsError, setModelsError] = useState("");
  const [loadingModelsFor, setLoadingModelsFor] = useState("");

  const [testResult, setTestResult] = useState(null);
  const [testing, setTesting] = useState(false);

  const [authMode, setAuthMode] = useState("local");
  const [pairCode, setPairCode] = useState("");
  const [pairing, setPairing] = useState(false);
  const [pairResult, setPairResult] = useState(null);

  const loadingMessage = useMemo(() => {
    if (loadingSlow) {
      return "Still loading provider configuration…";
    }
    return "Loading current configuration…";
  }, [loadingSlow]);

  const loadSettings = async () => {
    setInitialLoading(true);
    setError("");
    setLoadingSlow(false);

    let slowTimer;
    try {
      slowTimer = window.setTimeout(() => {
        setLoadingSlow(true);
      }, 1500);

      const res = await fetch("/api/settings");
      const data = await res.json();

      if (!res.ok) {
        throw new Error(data.error || "Failed to load settings");
      }

      setSettings(data);
    } catch (e) {
      console.error(e);
      setError(e.message || "Failed to load settings");
    } finally {
      window.clearTimeout(slowTimer);
      setInitialLoading(false);
    }
  };

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

  const updateField = (section, field, value) => {
    setSettings((prev) => ({
      ...prev,
      [section]: {
        ...prev[section],
        [field]: value,
      },
    }));
  };

  const handleSave = async () => {
    setSaving(true);
    setError("");
    setSavedMsg("");

    try {
      const res = await fetch("/api/settings/llm", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(settings),
      });

      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Failed to save settings");

      setSettings(data);
      setSavedMsg("Settings saved successfully!");
      setTimeout(() => setSavedMsg(""), 3000);
    } catch (e) {
      console.error(e);
      setError(e.message || "Failed to save settings");
    } finally {
      setSaving(false);
    }
  };

  const loadModelsForProvider = async (provider) => {
    setModelsError("");
    setLoadingModelsFor(provider);

    try {
      const res = await fetch(`/api/settings/models?provider=${provider}`);
      const data = await res.json();

      if (!res.ok || data.error) {
        throw new Error(data.error || "Failed to load models");
      }

      setModelsByProvider((prev) => ({
        ...prev,
        [provider]: data.models || [],
      }));
    } catch (e) {
      console.error(e);
      setModelsError(e.message || "Failed to load models");
    } finally {
      setLoadingModelsFor("");
    }
  };

  const handlePair = async () => {
    if (!pairCode.trim()) return;

    setPairing(true);
    setPairResult(null);

    try {
      const baseUrl =
        settings?.ollabridge?.base_url || "https://ruslanmv-ollabridge.hf.space";

      const res = await fetch("/api/ollabridge/pair", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ base_url: baseUrl, code: pairCode.trim() }),
      });

      const data = await res.json();

      if (data.success) {
        setPairResult({ ok: true, message: "Paired successfully!" });
        if (data.token) {
          updateField("ollabridge", "api_key", data.token);
        }
      } else {
        setPairResult({
          ok: false,
          message: data.error || "Pairing failed",
        });
      }
    } catch (e) {
      setPairResult({ ok: false, message: e.message || "Pairing failed" });
    } finally {
      setPairing(false);
    }
  };

  const handleTestConnection = async () => {
    setTesting(true);
    setTestResult(null);

    try {
      const activeProvider = settings?.provider || "ollama";
      const config = { provider: activeProvider };

      if (activeProvider === "openai" && settings?.openai) {
        config.openai = {
          api_key: settings.openai.api_key,
          base_url: settings.openai.base_url,
          model: settings.openai.model,
        };
      } else if (activeProvider === "claude" && settings?.claude) {
        config.claude = {
          api_key: settings.claude.api_key,
          base_url: settings.claude.base_url,
          model: settings.claude.model,
        };
      } else if (activeProvider === "watsonx" && settings?.watsonx) {
        config.watsonx = {
          api_key: settings.watsonx.api_key,
          project_id: settings.watsonx.project_id,
          base_url: settings.watsonx.base_url,
          model_id: settings.watsonx.model_id,
        };
      } else if (activeProvider === "ollama" && settings?.ollama) {
        config.ollama = {
          base_url: settings.ollama.base_url,
          model: settings.ollama.model,
        };
      } else if (activeProvider === "ollabridge" && settings?.ollabridge) {
        config.ollabridge = {
          base_url: settings.ollabridge.base_url,
          model: settings.ollabridge.model,
          api_key: settings.ollabridge.api_key,
        };
      }

      const result = await testProvider(config);
      setTestResult(result);
    } catch (err) {
      setTestResult({
        health: "error",
        warning: err.message || "Test failed",
      });
    } finally {
      setTesting(false);
    }
  };

  if (initialLoading) {
    return (
      <LoadingState
        loadingMessage={loadingMessage}
        loadingSlow={loadingSlow}
        onRetry={loadSettings}
      />
    );
  }

  if (!settings) {
    return (
      <div className="settings-root">
        <div className="settings-inline-error-card">
          <h1>AI Providers</h1>
          <div className="settings-loading-subtitle">Admin / LLM Settings</div>
          <p className="settings-error-text">
            {error || "Unable to load current configuration."}
          </p>
          <button
            type="button"
            className="settings-secondary-btn"
            onClick={loadSettings}
          >
            Retry
          </button>
        </div>
      </div>
    );
  }

  const { provider } = settings;
  const availableModels = modelsByProvider[provider] || [];

  return (
    <div className="settings-root">
      <h1>AI Providers</h1>
      <p className="settings-muted">
        Choose which LLM provider GitPilot should use for planning and agent
        workflows. Provider settings are stored on the server.
      </p>

      {error && <div className="settings-error-banner">{error}</div>}
      {savedMsg && <div className="settings-success-banner">{savedMsg}</div>}

      <div className="settings-card">
        <label className="settings-label">Active provider</label>
        <div className="settings-provider-tabs">
          {PROVIDERS.map((p) => (
            <button
              key={p}
              type="button"
              className={
                "settings-provider-tab" +
                (provider === p ? " settings-provider-tab-active" : "")
              }
              onClick={() => setSettings((prev) => ({ ...prev, provider: p }))}
            >
              {PROVIDER_LABELS[p] || p}
            </button>
          ))}
        </div>
      </div>

      {provider === "ollabridge" && (
        <div className="settings-card">
          <div className="settings-title">OllaBridge Cloud Configuration</div>
          <div className="settings-hint" style={{ marginBottom: 12 }}>
            Connect to OllaBridge Cloud or any OllaBridge instance for LLM
            inference. No API key required for public endpoints.
          </div>

          <label className="settings-label">Authentication Mode</label>
          <div className="ob-auth-tabs">
            {AUTH_MODES.map((m) => (
              <button
                key={m.id}
                type="button"
                className={
                  "ob-auth-tab" +
                  (authMode === m.id ? " ob-auth-tab-active" : "")
                }
                onClick={() => setAuthMode(m.id)}
              >
                <span className="ob-auth-tab-icon">{m.icon}</span>
                <span>{m.label}</span>
              </button>
            ))}
          </div>

          {authMode === "device" && (
            <div className="ob-auth-panel">
              <div className="ob-auth-desc">
                Enter the pairing code from your OllaBridge console and click
                Pair.
              </div>
              <div className="ob-pair-row">
                <input
                  className="settings-input ob-pair-input"
                  type="text"
                  maxLength={9}
                  placeholder="ABCD-1234"
                  value={pairCode}
                  onChange={(e) => setPairCode(e.target.value.toUpperCase())}
                  onKeyDown={(e) => e.key === "Enter" && handlePair()}
                />
                <button
                  type="button"
                  className="ob-pair-btn"
                  onClick={handlePair}
                  disabled={pairing || !pairCode.trim()}
                >
                  {pairing ? "Pairing…" : "Pair"}
                </button>
              </div>
              {pairResult && (
                <div
                  className={
                    pairResult.ok ? "settings-success-banner" : "settings-error-banner"
                  }
                >
                  {pairResult.message}
                </div>
              )}
            </div>
          )}

          <label className="settings-label">Base URL</label>
          <input
            className="settings-input"
            value={settings.ollabridge?.base_url || ""}
            onChange={(e) =>
              updateField("ollabridge", "base_url", e.target.value)
            }
            placeholder="https://your-ollabridge-endpoint"
          />

          {(authMode === "apikey" || authMode === "local") && (
            <>
              <label className="settings-label">API Key</label>
              <input
                className="settings-input"
                type="password"
                value={settings.ollabridge?.api_key || ""}
                onChange={(e) =>
                  updateField("ollabridge", "api_key", e.target.value)
                }
                placeholder="Optional API key"
              />
            </>
          )}

          <label className="settings-label">Model</label>
          <div className="settings-inline-row">
            <input
              className="settings-input"
              value={settings.ollabridge?.model || ""}
              onChange={(e) =>
                updateField("ollabridge", "model", e.target.value)
              }
              placeholder="qwen2.5:1.5b"
            />
            <button
              type="button"
              className="settings-secondary-btn"
              onClick={() => loadModelsForProvider("ollabridge")}
              disabled={loadingModelsFor === "ollabridge"}
            >
              {loadingModelsFor === "ollabridge" ? "Loading…" : "Load Models"}
            </button>
          </div>
        </div>
      )}

      {provider === "openai" && (
        <div className="settings-card">
          <div className="settings-title">OpenAI Configuration</div>

          <label className="settings-label">API Key</label>
          <input
            className="settings-input"
            type="password"
            value={settings.openai?.api_key || ""}
            onChange={(e) => updateField("openai", "api_key", e.target.value)}
            placeholder="sk-..."
          />

          <label className="settings-label">Base URL</label>
          <input
            className="settings-input"
            value={settings.openai?.base_url || ""}
            onChange={(e) => updateField("openai", "base_url", e.target.value)}
            placeholder="Optional custom base URL"
          />

          <label className="settings-label">Model</label>
          <input
            className="settings-input"
            value={settings.openai?.model || ""}
            onChange={(e) => updateField("openai", "model", e.target.value)}
            placeholder="gpt-4o-mini"
          />
        </div>
      )}

      {provider === "claude" && (
        <div className="settings-card">
          <div className="settings-title">Claude Configuration</div>

          <label className="settings-label">API Key</label>
          <input
            className="settings-input"
            type="password"
            value={settings.claude?.api_key || ""}
            onChange={(e) => updateField("claude", "api_key", e.target.value)}
            placeholder="Anthropic API key"
          />

          <label className="settings-label">Base URL</label>
          <input
            className="settings-input"
            value={settings.claude?.base_url || ""}
            onChange={(e) => updateField("claude", "base_url", e.target.value)}
            placeholder="Optional custom base URL"
          />

          <label className="settings-label">Model</label>
          <input
            className="settings-input"
            value={settings.claude?.model || ""}
            onChange={(e) => updateField("claude", "model", e.target.value)}
            placeholder="claude-sonnet-4-5"
          />
        </div>
      )}

      {provider === "watsonx" && (
        <div className="settings-card">
          <div className="settings-title">Watsonx Configuration</div>

          <label className="settings-label">API Key</label>
          <input
            className="settings-input"
            type="password"
            value={settings.watsonx?.api_key || ""}
            onChange={(e) => updateField("watsonx", "api_key", e.target.value)}
            placeholder="Watsonx API key"
          />

          <label className="settings-label">Project ID</label>
          <input
            className="settings-input"
            value={settings.watsonx?.project_id || ""}
            onChange={(e) =>
              updateField("watsonx", "project_id", e.target.value)
            }
            placeholder="Watsonx project ID"
          />

          <label className="settings-label">Base URL</label>
          <input
            className="settings-input"
            value={settings.watsonx?.base_url || ""}
            onChange={(e) => updateField("watsonx", "base_url", e.target.value)}
            placeholder="https://api.watsonx.ai/v1"
          />

          <label className="settings-label">Model</label>
          <input
            className="settings-input"
            value={settings.watsonx?.model_id || ""}
            onChange={(e) =>
              updateField("watsonx", "model_id", e.target.value)
            }
            placeholder="meta-llama/llama-3-3-70b-instruct"
          />
        </div>
      )}

      {provider === "ollama" && (
        <div className="settings-card">
          <div className="settings-title">Ollama Configuration</div>

          <label className="settings-label">Base URL</label>
          <input
            className="settings-input"
            value={settings.ollama?.base_url || ""}
            onChange={(e) => updateField("ollama", "base_url", e.target.value)}
            placeholder="http://localhost:11434"
          />

          <label className="settings-label">Model</label>
          <div className="settings-inline-row">
            <input
              className="settings-input"
              value={settings.ollama?.model || ""}
              onChange={(e) => updateField("ollama", "model", e.target.value)}
              placeholder="llama3"
            />
            <button
              type="button"
              className="settings-secondary-btn"
              onClick={() => loadModelsForProvider("ollama")}
              disabled={loadingModelsFor === "ollama"}
            >
              {loadingModelsFor === "ollama" ? "Loading…" : "Load Models"}
            </button>
          </div>
        </div>
      )}

      {availableModels.length > 0 && (
        <div className="settings-card">
          <div className="settings-title">Available Models</div>
          <div className="settings-model-list">
            {availableModels.map((model) => (
              <button
                key={model}
                type="button"
                className="settings-model-chip"
                onClick={() => updateField(provider, "model", model)}
              >
                {model}
              </button>
            ))}
          </div>
        </div>
      )}

      {modelsError && <div className="settings-error-banner">{modelsError}</div>}

      {testResult && (
        <div
          className={
            testResult.health === "ok"
              ? "settings-success-banner"
              : "settings-error-banner"
          }
        >
          {testResult.health === "ok"
            ? testResult.details || "Provider connection successful."
            : testResult.warning || "Provider connection failed."}
        </div>
      )}

      <div className="settings-actions">
        <button
          type="button"
          className="settings-save-btn"
          onClick={handleSave}
          disabled={saving}
        >
          {saving ? "Saving…" : "Save Settings"}
        </button>

        <button
          type="button"
          className="settings-secondary-btn"
          onClick={handleTestConnection}
          disabled={testing}
        >
          {testing ? "Testing…" : "Test Connection"}
        </button>
      </div>
    </div>
  );
}