import { useRef, useState, useEffect } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import Nav from "../components/Nav";
import {
  listDocuments,
  uploadDocument,
  deleteDocument,
  downloadDocument,
  getDocumentStatus,
  listCategories,
  createCategory,
  assignCategory,
  removeCategory,
  type DocumentOut,
  type CategoryOut,
} from "../api/client";

function StatusBadge({ status }: { status: DocumentOut["status"] }) {
  const colors: Record<DocumentOut["status"], string> = {
    pending: "#f4a261",
    processing: "#2196f3",
    done: "#2a9d8f",
    failed: "#e63946",
  };
  return (
    <span style={{
      fontSize: 12,
      fontWeight: 600,
      padding: "2px 8px",
      borderRadius: 4,
      background: colors[status],
      color: "#fff",
    }}>
      {status}
    </span>
  );
}

function DocumentRow({
  doc,
  categories,
  onDelete,
}: {
  doc: DocumentOut;
  categories: CategoryOut[];
  onDelete: (id: string) => void;
}) {
  const [expanded, setExpanded] = useState(false);
  const qc = useQueryClient();

  // Poll status while pending/processing
  const { data: liveStatus } = useQuery({
    queryKey: ["docStatus", doc.id],
    queryFn: () => getDocumentStatus(doc.id),
    // v5: refetchInterval receives the Query object; data lives in query.state.data
    refetchInterval: (query) => {
      const s = query.state.data?.status;
      return s === "pending" || s === "processing" ? 3000 : false;
    },
    enabled: doc.status === "pending" || doc.status === "processing",
  });

  useEffect(() => {
    if (liveStatus?.status === "done" || liveStatus?.status === "failed") {
      qc.invalidateQueries({ queryKey: ["documents"] });
    }
  }, [liveStatus?.status, qc]);

  const assignMut = useMutation({
    mutationFn: ({ catId }: { catId: string }) => assignCategory(doc.id, catId),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["documents"] }),
  });

  const removeCatMut = useMutation({
    mutationFn: ({ catId }: { catId: string }) => removeCategory(doc.id, catId),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["documents"] }),
  });

  const assignedIds = new Set(doc.categories.map((c) => c.id));
  const unassigned = categories.filter((c) => !assignedIds.has(c.id));

  let extractedData: Record<string, unknown> | null = null;
  if (doc.extracted_data) {
    try {
      extractedData = JSON.parse(doc.extracted_data);
    } catch {
      // ignore
    }
  }

  const tags: string[] = [];
  if (doc.tags) {
    try {
      const parsed = JSON.parse(doc.tags);
      if (Array.isArray(parsed)) tags.push(...parsed);
    } catch {
      // ignore
    }
  }

  return (
    <div style={{ border: "1px solid #ddd", borderRadius: 6, marginBottom: 12 }}>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 12,
          padding: "12px 16px",
          cursor: "pointer",
        }}
        onClick={() => setExpanded((e) => !e)}
      >
        <span style={{ flex: 1, fontWeight: 500 }}>{doc.filename}</span>
        <StatusBadge status={doc.status} />
        {doc.document_type && (
          <span style={{ fontSize: 12, color: "#555" }}>{doc.document_type}</span>
        )}
        <span style={{ fontSize: 12, color: "#999" }}>
          {(doc.file_size / 1024).toFixed(0)} KB
        </span>
        <button
          onClick={(e) => {
            e.stopPropagation();
            downloadDocument(doc.id, doc.filename);
          }}
          style={{ fontSize: 12, cursor: "pointer" }}
        >
          Download
        </button>
        <button
          onClick={(e) => {
            e.stopPropagation();
            if (confirm(`Delete "${doc.filename}"?`)) onDelete(doc.id);
          }}
          style={{ fontSize: 12, color: "#c00", cursor: "pointer" }}
        >
          Delete
        </button>
      </div>

      {expanded && (
        <div style={{ padding: "0 16px 16px", borderTop: "1px solid #eee" }}>
          {tags.length > 0 && (
            <div style={{ marginTop: 10 }}>
              <strong>Tags:</strong>{" "}
              {tags.map((t) => (
                <span
                  key={t}
                  style={{
                    fontSize: 12,
                    background: "#eee",
                    borderRadius: 3,
                    padding: "2px 6px",
                    marginRight: 4,
                  }}
                >
                  {t}
                </span>
              ))}
            </div>
          )}

          {extractedData && (
            <div style={{ marginTop: 10 }}>
              <strong>Extracted data:</strong>
              <table style={{ marginTop: 6, fontSize: 13, borderCollapse: "collapse" }}>
                <tbody>
                  {Object.entries(extractedData)
                    .filter(([k]) => k !== "tags")
                    .map(([k, v]) => (
                      <tr key={k}>
                        <td style={{ paddingRight: 16, color: "#666", verticalAlign: "top" }}>{k}</td>
                        <td>
                          {Array.isArray(v)
                            ? v.length === 0
                              ? "—"
                              : JSON.stringify(v, null, 2)
                            : v !== null && v !== undefined && v !== ""
                            ? String(v)
                            : "—"}
                        </td>
                      </tr>
                    ))}
                </tbody>
              </table>
            </div>
          )}

          {doc.error_message && (
            <div style={{ marginTop: 10, color: "#c00", fontSize: 13 }}>
              Error: {doc.error_message}
            </div>
          )}

          <div style={{ marginTop: 12 }}>
            <strong style={{ fontSize: 13 }}>Categories:</strong>{" "}
            {doc.categories.map((c) => (
              <span
                key={c.id}
                style={{
                  fontSize: 12,
                  background: "#dce8ff",
                  borderRadius: 3,
                  padding: "2px 6px",
                  marginRight: 4,
                }}
              >
                {c.name}{" "}
                <button
                  onClick={() => removeCatMut.mutate({ catId: c.id })}
                  style={{ fontSize: 10, cursor: "pointer", color: "#555", background: "none", border: "none" }}
                >
                  x
                </button>
              </span>
            ))}
            {unassigned.length > 0 && (
              <select
                defaultValue=""
                onChange={(e) => {
                  if (e.target.value) assignMut.mutate({ catId: e.target.value });
                  e.target.value = "";
                }}
                style={{ fontSize: 12, marginLeft: 4 }}
              >
                <option value="">+ add category</option>
                {unassigned.map((c) => (
                  <option key={c.id} value={c.id}>{c.name}</option>
                ))}
              </select>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

export default function DocumentsPage() {
  const qc = useQueryClient();
  const fileRef = useRef<HTMLInputElement>(null);
  const [newCatName, setNewCatName] = useState("");
  const [uploadError, setUploadError] = useState<string | null>(null);

  const { data: documents = [], isLoading } = useQuery({
    queryKey: ["documents"],
    queryFn: listDocuments,
  });

  const { data: categories = [] } = useQuery({
    queryKey: ["categories"],
    queryFn: listCategories,
  });

  const uploadMut = useMutation({
    mutationFn: uploadDocument,
    onSuccess: () => {
      setUploadError(null);
      qc.invalidateQueries({ queryKey: ["documents"] });
    },
    onError: (err: unknown) => {
      const msg =
        (err as { response?: { data?: { detail?: string } } })?.response?.data?.detail ??
        "Upload failed";
      setUploadError(msg);
    },
  });

  const deleteMut = useMutation({
    mutationFn: deleteDocument,
    onSuccess: () => qc.invalidateQueries({ queryKey: ["documents"] }),
  });

  const createCatMut = useMutation({
    mutationFn: createCategory,
    onSuccess: () => {
      setNewCatName("");
      qc.invalidateQueries({ queryKey: ["categories"] });
    },
  });

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) uploadMut.mutate(file);
    e.target.value = "";
  };

  return (
    <>
      <Nav />
      <div style={{ padding: 32, maxWidth: 900, margin: "0 auto" }}>
        <h1>Documents</h1>

        {/* Upload */}
        <div style={{ marginBottom: 24 }}>
          <input
            ref={fileRef}
            type="file"
            accept="application/pdf"
            style={{ display: "none" }}
            onChange={handleFileChange}
          />
          <button
            onClick={() => fileRef.current?.click()}
            disabled={uploadMut.isPending}
            style={{ padding: "8px 16px", cursor: "pointer" }}
          >
            {uploadMut.isPending ? "Uploading…" : "Upload PDF"}
          </button>
          {uploadError && (
            <span style={{ marginLeft: 12, color: "#c00", fontSize: 13 }}>{uploadError}</span>
          )}
        </div>

        {/* Category management */}
        <details style={{ marginBottom: 24 }}>
          <summary style={{ cursor: "pointer", fontWeight: 500 }}>Manage categories</summary>
          <div style={{ marginTop: 10, display: "flex", gap: 8, flexWrap: "wrap" }}>
            {categories.map((c) => (
              <span
                key={c.id}
                style={{
                  fontSize: 13,
                  background: "#eee",
                  borderRadius: 4,
                  padding: "4px 10px",
                }}
              >
                {c.name}
              </span>
            ))}
          </div>
          <form
            style={{ marginTop: 10, display: "flex", gap: 8 }}
            onSubmit={(e) => {
              e.preventDefault();
              if (newCatName.trim()) createCatMut.mutate(newCatName.trim());
            }}
          >
            <input
              value={newCatName}
              onChange={(e) => setNewCatName(e.target.value)}
              placeholder="New category name"
              style={{ padding: "6px 10px", fontSize: 13 }}
            />
            <button type="submit" disabled={createCatMut.isPending} style={{ cursor: "pointer" }}>
              Add
            </button>
          </form>
        </details>

        {/* Document list */}
        {isLoading ? (
          <p>Loading…</p>
        ) : documents.length === 0 ? (
          <p style={{ color: "#666" }}>No documents yet. Upload a PDF to get started.</p>
        ) : (
          documents.map((doc) => (
            <DocumentRow
              key={doc.id}
              doc={doc}
              categories={categories}
              onDelete={(id) => deleteMut.mutate(id)}
            />
          ))
        )}
      </div>
    </>
  );
}
