"use client";

import { useState, useRef } from "react";
import Link from "next/link";

type SearchResult = {
  text: string;
  similarity?: number;
  relevance?: number;
};

type SourceType = "raw_text" | "url" | "pdf" | "docx" | "txt" | "markdown";

const API_BASE =
  process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, "") || "http://localhost:8000";

export function KnowledgeBasePanel() {
  const [tenantId, setTenantId] = useState("tenant123");
  const [searchQuery, setSearchQuery] = useState("");
  const [searchResults, setSearchResults] = useState<SearchResult[]>([]);
  const [isSearching, setIsSearching] = useState(false);
  const [ingestContent, setIngestContent] = useState("");
  const [sourceType, setSourceType] = useState<SourceType>("raw_text");
  const [filename, setFilename] = useState("");
  const [url, setUrl] = useState("");
  const [isIngesting, setIsIngesting] = useState(false);
  const [ingestStatus, setIngestStatus] = useState<string | null>(null);
  const [searchError, setSearchError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  async function handleSearch() {
    if (!searchQuery.trim() || isSearching) return;
    setIsSearching(true);
    setSearchError(null);
    setSearchResults([]);

    try {
      const response = await fetch(`${API_BASE}/rag/search`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-tenant-id": tenantId,
        },
        body: JSON.stringify({ query: searchQuery }),
      });

      if (!response.ok) {
        throw new Error(`Search failed: ${response.status}`);
      }

      const data = await response.json();
      setSearchResults(data.results || []);
    } catch (err) {
      console.error(err);
      setSearchError(
        err instanceof Error
          ? err.message
          : "Failed to search knowledge base. Is the RAG MCP server running?",
      );
    } finally {
      setIsSearching(false);
    }
  }

  async function handleFileUpload(event: React.ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (!file) return;

    // Detect file type from extension
    const ext = file.name.split('.').pop()?.toLowerCase();
    let detectedType: SourceType = "raw_text";
    if (ext === "pdf") detectedType = "pdf";
    else if (ext === "docx" || ext === "doc") detectedType = "docx";
    else if (ext === "txt" || ext === "text") detectedType = "txt";
    else if (ext === "md" || ext === "markdown") detectedType = "markdown";

    setSourceType(detectedType);
    setFilename(file.name);

    // For binary files (PDF, DOCX), upload directly to server
    if (detectedType === "pdf" || detectedType === "docx") {
      await handleFileIngest(file);
      return;
    }

    // For text files, read and show in textarea
    const reader = new FileReader();
    reader.onload = async (e) => {
      const text = e.target?.result as string;
      setIngestContent(text);
    };
    reader.readAsText(file);
  }

  async function handleFileIngest(file: File) {
    setIsIngesting(true);
    setIngestStatus(null);

    try {
      const formData = new FormData();
      formData.append("file", file);

      const response = await fetch(`${API_BASE}/rag/ingest-file`, {
        method: "POST",
        headers: {
          "x-tenant-id": tenantId,
        },
        body: formData,
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(
          errorData.detail || `File ingestion failed: ${response.status}`,
        );
      }

      const data = await response.json();
      setIngestStatus(
        `✅ ${data.message || `Successfully ingested ${data.chunks_stored || 0} chunk(s)`}`,
      );
      setFilename("");
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    } catch (err) {
      console.error(err);
      setIngestStatus(
        err instanceof Error
          ? `❌ Error: ${err.message}`
          : "Failed to ingest file. Is the RAG MCP server running?",
      );
    } finally {
      setIsIngesting(false);
    }
  }

  async function handleIngest() {
    if (!ingestContent.trim() || isIngesting) return;
    setIsIngesting(true);
    setIngestStatus(null);

    try {
      // Prepare metadata
      const metadata: Record<string, string> = {};
      if (filename) metadata.filename = filename;
      if (url || sourceType === "url") {
        const ingestUrl = url || ingestContent.trim();
        metadata.url = ingestUrl;
      }
      if (filename) {
        // Generate doc_id from filename
        metadata.doc_id = filename.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
      }

      // Use the new enhanced endpoint
      const response = await fetch(`${API_BASE}/rag/ingest-document`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-tenant-id": tenantId,
        },
        body: JSON.stringify({
          action: "ingest_document",
          tenant_id: tenantId,
          source_type: sourceType,
          content: sourceType === "url" ? (url || ingestContent.trim()) : ingestContent,
          metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
        }),
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(
          errorData.detail || `Ingestion failed: ${response.status}`,
        );
      }

      const data = await response.json();
      setIngestStatus(
        `✅ ${data.message || `Successfully ingested ${data.chunks_stored || 0} chunk(s)`}`,
      );
      setIngestContent("");
      setFilename("");
      setUrl("");
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    } catch (err) {
      console.error(err);
      setIngestStatus(
        err instanceof Error
          ? `❌ Error: ${err.message}`
          : "Failed to ingest content. Is the RAG MCP server running?",
      );
    } finally {
      setIsIngesting(false);
    }
  }

  return (
    <section
      id="knowledge-base"
      className="gradient-border relative rounded-[28px] p-1 text-white"
    >
      <div className="glass-panel relative rounded-[26px] p-6">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div>
            <p className="text-sm uppercase tracking-[0.5em] text-cyan-200/70">
              Knowledge Base
            </p>
            <h2 className="mt-2 text-3xl font-semibold">
              Search & ingest documents
            </h2>
          </div>
          <Link
            href="/knowledge-base"
            className="rounded-full border border-cyan-500/50 bg-cyan-500/10 px-5 py-2.5 text-sm font-semibold text-cyan-300 transition hover:bg-cyan-500/20"
          >
            View All Documents →
          </Link>
          <div className="flex flex-col gap-2 text-sm text-slate-200">
            <label className="text-xs uppercase tracking-widest text-slate-400">
              Tenant ID
            </label>
            <input
              value={tenantId}
              onChange={(e) => setTenantId(e.target.value)}
              className="rounded-full border border-white/15 bg-white/10 px-4 py-1.5 text-sm text-white outline-none focus:border-cyan-300"
            />
          </div>
        </div>

        {/* Search Section */}
        <div className="mt-6">
          <div className="flex flex-col gap-3 md:flex-row">
            <input
              type="text"
              placeholder="Search knowledge base (e.g., 'HR policy', 'refund procedure')..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && handleSearch()}
              className="flex-1 rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white outline-none focus:border-cyan-200/80"
            />
            <button
              onClick={handleSearch}
              disabled={isSearching}
              className="min-w-[140px] rounded-2xl bg-gradient-to-r from-sky-400 to-cyan-500 px-6 py-3 font-semibold text-slate-950 shadow-lg shadow-cyan-500/30 transition hover:-translate-y-0.5 disabled:cursor-not-allowed disabled:opacity-60"
            >
              {isSearching ? "Searching…" : "Search"}
            </button>
          </div>

          {searchError && (
            <p className="mt-3 rounded-2xl border border-red-500/40 bg-red-500/10 px-4 py-3 text-sm text-red-200">
              {searchError}
            </p>
          )}

          {searchResults.length > 0 && (
            <div className="mt-4 space-y-3">
              <p className="text-sm uppercase tracking-widest text-slate-400">
                Found {searchResults.length} result(s)
              </p>
              {searchResults.map((result, idx) => (
                <div
                  key={idx}
                  className="rounded-2xl border border-white/10 bg-slate-950/40 p-4"
                >
                  <div className="flex items-start justify-between gap-3">
                    <p className="flex-1 text-sm text-slate-200">
                      {result.text}
                    </p>
                    {(result.similarity !== undefined ||
                      result.relevance !== undefined) && (
                      <span className="text-xs text-cyan-300">
                        {(
                          result.similarity ?? result.relevance ?? 0
                        ).toFixed(2)}
                      </span>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* Ingest Section */}
        <div className="mt-8 rounded-2xl border border-white/10 bg-slate-950/40 p-4">
          <p className="text-sm uppercase tracking-[0.5em] text-slate-400">
            Add to Knowledge Base
          </p>
          <p className="mt-2 text-sm text-slate-300">
            Upload files (PDF, DOCX, TXT, MD), paste text, or provide URLs. Content will be chunked, embedded, and stored.
          </p>

          {/* Source Type Selector */}
          <div className="mt-4 flex flex-wrap gap-2">
            {(["raw_text", "url", "pdf", "docx", "txt", "markdown"] as SourceType[]).map((type) => (
              <button
                key={type}
                onClick={() => {
                  setSourceType(type);
                  if (type !== "url") setUrl("");
                }}
                className={`rounded-full px-4 py-2 text-xs font-semibold uppercase tracking-wider transition ${
                  sourceType === type
                    ? "bg-cyan-500 text-slate-950"
                    : "bg-white/5 text-slate-300 hover:bg-white/10"
                }`}
              >
                {type.replace("_", " ")}
              </button>
            ))}
          </div>

          {/* File Upload */}
          <div className="mt-4">
            <input
              ref={fileInputRef}
              type="file"
              accept=".pdf,.docx,.doc,.txt,.md,.markdown"
              onChange={handleFileUpload}
              className="hidden"
              id="file-upload"
            />
            <label
              htmlFor="file-upload"
              className="inline-flex cursor-pointer items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm text-slate-300 transition hover:bg-white/10"
            >
              📄 Upload File (PDF, DOCX, TXT, MD)
            </label>
            {filename && (
              <span className="ml-3 text-sm text-cyan-300">{filename}</span>
            )}
          </div>

          {/* URL Input (when source type is URL) */}
          {sourceType === "url" && (
            <input
              type="url"
              placeholder="Enter URL to fetch content from..."
              value={url}
              onChange={(e) => setUrl(e.target.value)}
              className="mt-4 w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white outline-none focus:border-cyan-200/80"
            />
          )}

          {/* Content Textarea */}
          <textarea
            placeholder={
              sourceType === "url"
                ? "Or paste URL here..."
                : "Paste document content here (e.g., policy text, procedures, documentation, FAQs)..."
            }
            value={ingestContent}
            onChange={(e) => setIngestContent(e.target.value)}
            className="mt-4 w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white outline-none focus:border-cyan-200/80"
            rows={6}
          />

          {/* Filename Input (optional) */}
          {sourceType !== "url" && (
            <input
              type="text"
              placeholder="Filename (optional, e.g., policy.pdf)"
              value={filename}
              onChange={(e) => setFilename(e.target.value)}
              className="mt-3 w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white outline-none focus:border-cyan-200/80"
            />
          )}

          <div className="mt-4 flex items-center gap-3">
            <button
              onClick={handleIngest}
              disabled={
                isIngesting ||
                (!ingestContent.trim() && !url.trim() && sourceType === "url")
              }
              className="rounded-2xl bg-gradient-to-r from-emerald-400 to-teal-500 px-6 py-2.5 font-semibold text-slate-950 shadow-lg shadow-emerald-500/30 transition hover:-translate-y-0.5 disabled:cursor-not-allowed disabled:opacity-60"
            >
              {isIngesting ? "Ingesting…" : `Ingest as ${sourceType.replace("_", " ")}`}
            </button>
            {ingestStatus && (
              <p className="text-sm text-slate-300">{ingestStatus}</p>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}

