import { useCallback, useEffect, useState } from "react";
import { API_BASE } from "./config";

export function Models({ onPullStateChange }) {
  const [models, setModels] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [pulling, setPulling] = useState(false);
  const [modelName, setModelName] = useState("");
  const [pullProgress, setPullProgress] = useState("");
  const [recommended, setRecommended] = useState(null); // {hardware, models}

  const checkOllamaStatus = useCallback(async () => {
    try {
      const response = await fetch(`${API_BASE}/ollama/status`);
      const data = await response.json();
      return data.status === "running";
    } catch {
      return false;
    }
  }, []);

  const loadModels = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const isRunning = await checkOllamaStatus();
      if (!isRunning) {
        setError("Ollama service is not running");
        setModels([]);
        return;
      }
      const response = await fetch(`${API_BASE}/models/details`);
      if (!response.ok) throw new Error("Failed to fetch models");
      const data = await response.json();
      // Embedding models (nomic-embed-text) are infrastructure — hide them.
      setModels((data.models || []).filter((m) => !m.name.toLowerCase().includes("embed")));
    } catch (err) {
      setError(`Error loading models: ${err.message}`);
      setModels([]);
    } finally {
      setLoading(false);
    }
  }, [checkOllamaStatus]);

  const pullModel = async (nameArg) => {
    const name = (typeof nameArg === "string" ? nameArg : modelName).trim();
    if (!name) {
      setError("Please enter a model name");
      return;
    }

    setPulling(true);
    onPullStateChange?.(true);
    setError("");
    setPullProgress(`Pulling ${name}…`);

    try {
      const response = await fetch(`${API_BASE}/models/pull`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name }),
      });

      if (!response.ok) throw new Error("Failed to pull model");

      const reader = response.body.getReader();
      const decoder = new TextDecoder();

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        const chunk = decoder.decode(value);
        const lines = chunk.split("\n");

        for (const line of lines) {
          if (line.trim()) {
            try {
              const json = JSON.parse(line);
              if (json.error) {
                setError(`Pull error: ${json.error}`);
              } else if (json.status) {
                setPullProgress(json.completed && json.total
                  ? `${json.status} — ${Math.round((json.completed / json.total) * 100)}%`
                  : json.status
                );
              }
            } catch {
              // ignore incomplete JSON lines
            }
          }
        }
      }

      setModelName("");
      setPullProgress("");
      await loadModels();
    } catch (err) {
      setError(`Error pulling model: ${err.message}`);
    } finally {
      setPulling(false);
      onPullStateChange?.(false);
    }
  };

  const deleteModel = async (modelId) => {
    if (!confirm(`Are you sure you want to delete ${modelId}?`)) return;

    setError("");
    try {
      const response = await fetch(`${API_BASE}/models/${encodeURIComponent(modelId)}`, {
        method: "DELETE",
      });
      if (!response.ok) {
        const text = await response.text().catch(() => "");
        throw new Error(text || response.statusText);
      }
      await loadModels();
    } catch (err) {
      setError(`Error deleting model: ${err.message}`);
    }
  };

  useEffect(() => {
    loadModels();
    fetch(`${API_BASE}/models/recommended`).then(r => r.ok ? r.json() : null).then(setRecommended).catch(() => {});
    const interval = setInterval(loadModels, 30000);

    return () => clearInterval(interval);
  }, [loadModels]);

  const installedNames = new Set(models.map(m => m.name.toLowerCase()));
  const FIT = {
    gpu: { label: "🟢 fits GPU", color: "#8aff8a" },
    ram: { label: "🟡 runs on RAM (CPU)", color: "#e8c65a" },
    no: { label: "🔴 too big", color: "#ff8a80" },
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", flexGrow: 1 }}>
      {error && (
        <div style={{
          padding: "0.75rem 1rem",
          background: "#3d2d2d",
          border: "1px solid #ff6b6b",
          borderRadius: "8px",
          color: "#ff8888",
          marginBottom: "1rem",
          fontSize: "0.9rem"
        }}>
          {error}
        </div>
      )}

      <div style={{
        flexGrow: 1,
        background: "#161616",
        border: "1px solid #333",
        borderRadius: "12px",
        padding: "1rem",
        display: "flex",
        flexDirection: "column",
        overflow: "hidden"
      }}>
        {/* Pull Model Section */}
        <div style={{ marginBottom: "1.5rem", paddingBottom: "1rem", borderBottom: "1px solid #333" }}>
          <h3 style={{ margin: "0 0 0.75rem 0", fontSize: "0.95rem", color: "#bbb" }}>Pull Model from Registry</h3>
          <div style={{ display: "flex", gap: "0.5rem" }}>
            <input
              type="text"
              placeholder="e.g., llama3, mistral, gemma"
              value={modelName}
              onChange={(e) => setModelName(e.target.value)}
              onKeyPress={(e) => e.key === "Enter" && !pulling && pullModel()}
              disabled={pulling}
              style={{
                flex: 1,
                padding: "0.6rem 0.75rem",
                background: "#0a0a0a",
                color: "#eee",
                border: "1px solid #333",
                borderRadius: "6px",
                fontSize: "0.9rem"
              }}
            />
            <button
              onClick={pullModel}
              disabled={pulling}
              style={{
                padding: "0.6rem 1.25rem",
                background: pulling ? "#666" : "#28a745",
                color: "#fff",
                border: "none",
                borderRadius: "6px",
                cursor: pulling ? "not-allowed" : "pointer",
                fontSize: "0.9rem",
                whiteSpace: "nowrap"
              }}
            >
              {pulling ? "Pulling..." : "Pull"}
            </button>
            <button
              onClick={loadModels}
              disabled={loading}
              style={{
                padding: "0.6rem 1.25rem",
                background: "#007acc",
                color: "#fff",
                border: "none",
                borderRadius: "6px",
                cursor: loading ? "not-allowed" : "pointer",
                opacity: loading ? 0.6 : 1,
                fontSize: "0.9rem",
                whiteSpace: "nowrap"
              }}
            >
              {loading ? "Refreshing..." : "Refresh"}
            </button>
          </div>
          {pullProgress && (
            <div style={{ marginTop: "0.75rem", fontSize: "0.85rem", color: "#999" }}>
              {pullProgress}
            </div>
          )}
        </div>

        {/* Recommended for your hardware */}
        {recommended && (
          <div style={{ marginBottom: "1.5rem", paddingBottom: "1rem", borderBottom: "1px solid #333" }}>
            <h3 style={{ margin: "0 0 0.25rem 0", fontSize: "0.95rem", color: "#bbb" }}>Recommended for your hardware</h3>
            <div style={{ fontSize: "0.78rem", color: "#777", marginBottom: "0.75rem" }}>
              {recommended.hardware.ram_gb ? `${recommended.hardware.ram_gb} GB RAM` : "RAM unknown"}
              {" · "}
              {recommended.hardware.vram_gb ? `${recommended.hardware.vram_gb} GB GPU` : "GPU VRAM unknown — sized by RAM"}
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: "0.35rem" }}>
              {recommended.models.map((m) => {
                const installed = installedNames.has(m.name.toLowerCase());
                const fit = FIT[m.fit] || FIT.no;
                return (
                  <div key={m.name} style={{ display: "flex", alignItems: "center", gap: "0.6rem", padding: "0.4rem 0.6rem", background: "#0f0f0f", border: "1px solid #262626", borderRadius: "8px" }}>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <span style={{ color: "#eee", fontSize: "0.85rem" }}>{m.name}</span>
                      <span style={{ color: "#666", fontSize: "0.75rem" }}> · {m.params} · {m.size_gb} GB · {m.role}</span>
                      <div style={{ color: "#777", fontSize: "0.72rem" }}>{m.note}</div>
                    </div>
                    <span style={{ color: fit.color, fontSize: "0.75rem", whiteSpace: "nowrap" }}>{fit.label}</span>
                    {installed
                      ? <span style={{ color: "#8aff8a", fontSize: "0.75rem", whiteSpace: "nowrap" }}>✓ installed</span>
                      : <button onClick={() => pullModel(m.name)} disabled={pulling}
                          style={{ padding: "0.3rem 0.7rem", background: pulling ? "#555" : "#28a745", color: "#fff", border: "none", borderRadius: "6px", cursor: pulling ? "not-allowed" : "pointer", fontSize: "0.75rem", whiteSpace: "nowrap" }}>
                          Pull
                        </button>}
                  </div>
                );
              })}
            </div>
          </div>
        )}

        {/* Local Models List */}
        <div style={{ flexGrow: 1, overflowY: "auto", paddingRight: "0.5rem" }}>
          <h3 style={{ margin: "0 0 1rem 0", fontSize: "0.95rem", color: "#bbb" }}>
            Available Models ({models.length})
          </h3>
          {models.length === 0 ? (
            <div style={{ padding: "2rem", textAlign: "center", color: "#666" }}>
              {loading ? "Loading models..." : "No models available. Pull a model to get started."}
            </div>
          ) : (
            <div style={{ display: "grid", gap: "0.75rem" }}>
              {models.map((model) => (
                <div
                  key={model.name}
                  style={{
                    padding: "0.9rem",
                    background: "#1b1b1b",
                    borderRadius: "8px",
                    border: "1px solid #2a2a2a",
                    display: "flex",
                    justifyContent: "space-between",
                    alignItems: "center"
                  }}
                >
                  <div>
                    <div style={{ fontWeight: "500", marginBottom: "0.3rem", color: "#ddd" }}>
                      {model.name}
                    </div>
                    <div style={{ fontSize: "0.85rem", color: "#aaa" }}>
                      {(model.size / (1024 * 1024 * 1024)).toFixed(2)} GB
                    </div>
                    {model.modified_at && (
                      <div style={{ fontSize: "0.85rem", color: "#888" }}>
                        Modified: {new Date(model.modified_at).toLocaleDateString()}
                      </div>
                    )}
                  </div>
                  <button
                    onClick={() => deleteModel(model.name)}
                    style={{
                      padding: "0.5rem 1rem",
                      background: "#d63031",
                      color: "#fff",
                      border: "none",
                      borderRadius: "6px",
                      cursor: "pointer",
                      fontSize: "0.85rem",
                      whiteSpace: "nowrap"
                    }}
                  >
                    Delete
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
