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

// RAG document manager: upload/paste text, chunked + embedded server-side, then
// retrieved into the chat system prompt. See synapse/memory/store.py.
export function Documents() {
  const [docs, setDocs] = useState([]);
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const [busy, setBusy] = useState(false);
  const [message, setMessage] = useState("");
  const [viewing, setViewing] = useState(null); // {title, chunks} being previewed
  const [projects, setProjects] = useState([]);
  const [activeProject, setActiveProject] = useState(""); // "" = All

  const loadProjects = async () => {
    try {
      const r = await fetch(`${API_BASE}/projects`);
      if (r.ok) { const d = await r.json(); setProjects(d.projects || []); setActiveProject(d.active || ""); }
    } catch { /* offline */ }
  };

  // Switch the active workspace (persisted in settings; scopes chat RAG too).
  const setActive = async (pid) => {
    await fetch(`${API_BASE}/settings`, {
      method: "PUT", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ active_project: pid }),
    });
    setActiveProject(pid);
    load();
    loadProjects();
  };

  const newProject = async () => {
    const name = window.prompt("New project name:");
    if (!name || !name.trim()) return;
    const r = await fetch(`${API_BASE}/projects`, {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ name: name.trim() }),
    });
    if (r.ok) { const p = await r.json(); await setActive(p.id); }
  };

  const removeProject = async () => {
    if (!activeProject) return;
    if (!window.confirm("Delete this project? Its documents are kept but become unscoped.")) return;
    await fetch(`${API_BASE}/projects/${encodeURIComponent(activeProject)}`, { method: "DELETE" });
    await setActive("");
  };

  const openDoc = async (doc) => {
    try {
      const r = await fetch(`${API_BASE}/documents/${encodeURIComponent(doc.doc_id)}`);
      if (r.ok) setViewing({ title: doc.title, chunks: (await r.json()).chunks || [] });
    } catch { /* ignore */ }
  };

  const load = async () => {
    try {
      const r = await fetch(`${API_BASE}/documents`);
      if (r.ok) setDocs((await r.json()).documents || []);
    } catch { /* offline — leave list as-is */ }
  };

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

  // Files (pdf/docx/txt/md) upload straight to the server, which extracts the
  // text. Base64 in JSON — no multipart dependency.
  const onFile = (e) => {
    const file = e.target.files?.[0];
    e.target.value = ""; // allow re-selecting the same file
    if (!file) return;
    setBusy(true);
    setMessage(`Reading ${file.name}…`);
    const reader = new FileReader();
    reader.onload = async () => {
      const b64 = String(reader.result || "").split(",")[1];
      try {
        const r = await fetch(`${API_BASE}/documents/upload`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ filename: file.name, data: b64 }),
        });
        if (r.ok) {
          const d = await r.json();
          setMessage(`Indexed "${d.title}" (${d.chunks} chunk${d.chunks === 1 ? "" : "s"}).`);
          load();
        } else {
          setMessage((await r.json().catch(() => ({}))).detail || "Failed to index file.");
        }
      } catch (err) {
        setMessage(`Error: ${err.message}`);
      } finally {
        setBusy(false);
      }
    };
    reader.readAsDataURL(file);
  };

  const addDoc = async () => {
    if (!title.trim() || !content.trim()) {
      setMessage("Title and content are required.");
      return;
    }
    setBusy(true);
    setMessage("Chunking and embedding…");
    try {
      const r = await fetch(`${API_BASE}/documents`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: title.trim(), content }),
      });
      if (r.ok) {
        const d = await r.json();
        setMessage(`Indexed "${d.title}" (${d.chunks} chunk${d.chunks === 1 ? "" : "s"}).`);
        setTitle("");
        setContent("");
        load();
      } else {
        setMessage((await r.json().catch(() => ({}))).detail || "Failed to index.");
      }
    } catch (err) {
      setMessage(`Error: ${err.message}`);
    } finally {
      setBusy(false);
    }
  };

  const removeDoc = async (docId) => {
    try {
      await fetch(`${API_BASE}/documents/${encodeURIComponent(docId)}`, { method: "DELETE" });
      load();
    } catch { /* ignore */ }
  };

  const input = { padding: "0.9rem", background: "#222", color: "#eee", border: "1px solid #333", borderRadius: "10px", width: "100%", boxSizing: "border-box" };

  return (
    <div style={{ padding: "1.5rem", color: "#eee", maxWidth: "820px" }}>
      <h2 style={{ marginTop: 0 }}>📄 Documents</h2>
      <p style={{ color: "#aaa", marginTop: 0 }}>
        Upload or paste text. It's chunked, embedded, and pulled into chat as source
        material when a message is relevant.
      </p>

      <div style={{ display: "flex", alignItems: "center", gap: "0.6rem", marginBottom: "1.2rem", flexWrap: "wrap" }}>
        <span style={{ color: "#888", fontSize: "0.85rem" }}>Workspace:</span>
        <select
          value={activeProject}
          onChange={e => (e.target.value === "__new__" ? newProject() : setActive(e.target.value))}
          style={{ padding: "0.5rem 0.7rem", background: "#222", color: "#eee", border: "1px solid #333", borderRadius: "8px" }}
        >
          <option value="">All documents</option>
          {projects.map(p => (
            <option key={p.id} value={p.id}>{p.name} ({p.docs})</option>
          ))}
          <option value="__new__">＋ New project…</option>
        </select>
        {activeProject && (
          <button onClick={removeProject} title="Delete this project (documents kept)"
            style={{ padding: "0.4rem 0.7rem", background: "#2a1a1a", color: "#ff8a80", border: "1px solid #5a2a2a", borderRadius: "8px", cursor: "pointer", fontSize: "0.8rem" }}>
            Delete project
          </button>
        )}
        <span style={{ color: "#666", fontSize: "0.78rem" }}>
          {activeProject ? "Chat scopes to this project's documents." : "Chat searches all documents."}
        </span>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: "0.7rem", marginBottom: "1.5rem" }}>
        <input type="text" placeholder="Title" value={title}
          onChange={e => setTitle(e.target.value)} style={input} />
        <textarea rows={8} placeholder="Paste text here, or upload a .pdf/.docx/.txt/.md file below"
          value={content} onChange={e => setContent(e.target.value)} style={input} />
        <div style={{ display: "flex", gap: "0.7rem", alignItems: "center" }}>
          <input type="file" accept=".pdf,.docx,.txt,.md,.markdown,text/*" onChange={onFile} disabled={busy}
            title="Upload a file — text extracted server-side"
            style={{ color: "#aaa", flex: 1 }} />
          <button onClick={addDoc} disabled={busy}
            style={{ padding: "0.9rem 1.5rem", background: busy ? "#555" : "#007acc", color: "#fff", border: "none", borderRadius: "8px", cursor: busy ? "default" : "pointer" }}>
            {busy ? "Indexing…" : "Add document"}
          </button>
        </div>
        {message && <div style={{ color: "#8ab4ff" }}>{message}</div>}
      </div>

      {docs.length === 0 ? (
        <div style={{ color: "#777" }}>No documents yet.</div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
          {docs.map(d => (
            <div key={d.doc_id} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "0.8rem 1rem", background: "#1a1a1a", border: "1px solid #2a2a2a", borderRadius: "10px" }}>
              <div onClick={() => openDoc(d)} style={{ cursor: "pointer", flex: 1 }} title="View chunks">
                <div style={{ fontWeight: 600 }}>{d.title}</div>
                <div style={{ color: "#888", fontSize: "0.85rem" }}>{d.chunks} chunk{d.chunks === 1 ? "" : "s"}</div>
              </div>
              <button onClick={() => removeDoc(d.doc_id)}
                style={{ padding: "0.5rem 0.9rem", background: "#2a1a1a", color: "#ff8a80", border: "1px solid #5a2a2a", borderRadius: "8px", cursor: "pointer" }}>
                Delete
              </button>
            </div>
          ))}
        </div>
      )}

      {viewing && (
        <div onClick={() => setViewing(null)}
          style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.6)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 100, padding: "2rem" }}>
          <div onClick={e => e.stopPropagation()}
            style={{ background: "#1a1a1a", border: "1px solid #333", borderRadius: "12px", maxWidth: "700px", width: "100%", maxHeight: "80vh", display: "flex", flexDirection: "column" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "1rem 1.25rem", borderBottom: "1px solid #2a2a2a" }}>
              <strong>{viewing.title}</strong>
              <button onClick={() => setViewing(null)}
                style={{ background: "none", border: "none", color: "#aaa", fontSize: "1.2rem", cursor: "pointer" }}>✕</button>
            </div>
            <div style={{ overflowY: "auto", padding: "1rem 1.25rem" }}>
              {viewing.chunks.map(c => (
                <div key={c.chunk_idx} style={{ marginBottom: "1rem" }}>
                  <div style={{ color: "#666", fontSize: "0.75rem", marginBottom: "0.3rem" }}>chunk {c.chunk_idx + 1}</div>
                  <div style={{ whiteSpace: "pre-wrap", color: "#ddd", fontSize: "0.9rem", background: "#141414", border: "1px solid #262626", borderRadius: "8px", padding: "0.7rem" }}>{c.text}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
