"use client";

import { useCallback, useMemo, useState } from "react";
import {
  searchDatasetsAPI,
  searchDatasetSourceAPI,
  importDatasetEntriesAPI,
} from "@/lib/api";
import type { Artifact, DatasetSearchResult } from "@/lib/types";

type SourceFilter = "all" | "sabdab" | "oas" | "imgt";

const SOURCE_LABELS: Record<string, string> = {
  sabdab: "SAbDab",
  oas: "OAS",
  imgt: "IMGT",
  fc: "Fc",
};

const DATA_TYPE_COLORS: Record<string, string> = {
  structure: "bg-blue-100 text-blue-700",
  sequence: "bg-emerald-100 text-emerald-700",
  gene: "bg-purple-100 text-purple-700",
};

interface Props {
  open: boolean;
  onClose: () => void;
  onImport: (artifacts: Artifact[]) => void;
}

export default function DatasetSearchPanel({ open, onClose, onImport }: Props) {
  const [query, setQuery] = useState("");
  const [source, setSource] = useState<SourceFilter>("all");
  const [results, setResults] = useState<Record<string, DatasetSearchResult[]>>(
    {},
  );
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [importing, setImporting] = useState(false);
  const [collapsed, setCollapsed] = useState<Set<string>>(new Set());

  const search = useCallback(async () => {
    if (!query.trim()) return;
    setLoading(true);
    setError(null);
    setResults({});
    setSelected(new Set());
    try {
      if (source === "all") {
        const res = await searchDatasetsAPI({ query: query.trim() });
        setResults(res.results);
      } else {
        const res = await searchDatasetSourceAPI(source, {
          query: query.trim(),
        });
        setResults({ [source]: res });
      }
    } catch (e) {
      setError(e instanceof Error ? e.message : "Search failed");
    } finally {
      setLoading(false);
    }
  }, [query, source]);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === "Enter") {
        e.preventDefault();
        search();
      }
    },
    [search],
  );

  const toggleSelect = useCallback((id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }, []);

  const toggleCollapse = useCallback((src: string) => {
    setCollapsed((prev) => {
      const next = new Set(prev);
      if (next.has(src)) next.delete(src);
      else next.add(src);
      return next;
    });
  }, []);

  const allResults = useMemo(() => {
    const flat: DatasetSearchResult[] = [];
    for (const items of Object.values(results)) {
      flat.push(...items);
    }
    return flat;
  }, [results]);

  const handleImport = useCallback(async () => {
    const entries = allResults
      .filter((r) => selected.has(r.id))
      .map((r) => ({ source: r.source, entry_id: r.id }));
    if (entries.length === 0) return;
    setImporting(true);
    try {
      const res = await importDatasetEntriesAPI(entries);
      onImport(res.artifacts);
    } catch (e) {
      setError(e instanceof Error ? e.message : "Import failed");
    } finally {
      setImporting(false);
    }
  }, [allResults, selected, onImport]);

  if (!open) return null;

  const sourceKeys = Object.keys(results).filter(
    (k) => results[k].length > 0,
  );
  const hasResults = sourceKeys.length > 0;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-label="Search datasets"
      data-testid="dataset-search-panel"
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/30 backdrop-blur-sm"
      onClick={onClose}
    >
      <div
        className="w-[640px] max-w-[94vw] max-h-[85vh] bg-white rounded-xl border border-border shadow-xl flex flex-col"
        onClick={(e) => e.stopPropagation()}
      >
        {/* Header */}
        <div className="px-4 py-3 border-b border-border flex items-center gap-3">
          <div>
            <p className="text-xs font-semibold text-foreground">
              Search Databases
            </p>
            <p className="text-[10px] text-muted-fg">
              Query SAbDab, OAS, and IMGT for antibody data
            </p>
          </div>
          <div className="flex-1" />
          <button
            onClick={onClose}
            className="text-[11px] text-muted-fg hover:text-foreground"
            aria-label="Close"
          >
            ✕
          </button>
        </div>

        {/* Search bar */}
        <div className="px-4 py-2 border-b border-border flex gap-2">
          <input
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="Search antibody databases..."
            data-testid="dataset-search-input"
            className="flex-1 rounded-md border border-border bg-white px-3 py-1.5 text-xs focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent/20"
          />
          <select
            value={source}
            onChange={(e) => setSource(e.target.value as SourceFilter)}
            data-testid="dataset-source-filter"
            className="rounded-md border border-border bg-white px-2 py-1.5 text-xs focus:outline-none focus:border-accent"
          >
            <option value="all">All Sources</option>
            <option value="sabdab">SAbDab</option>
            <option value="oas">OAS</option>
            <option value="imgt">IMGT</option>
          </select>
          <button
            onClick={search}
            disabled={loading || !query.trim()}
            className="px-3 py-1.5 rounded-md bg-accent text-white text-xs font-medium hover:bg-accent-hover disabled:opacity-30 transition-colors"
          >
            Search
          </button>
        </div>

        {/* Results */}
        <div className="flex-1 overflow-y-auto px-2 py-2">
          {loading && (
            <p className="text-[11px] text-muted-fg px-2 py-6 text-center">
              Searching...
            </p>
          )}
          {error && (
            <p className="text-[11px] text-red-600 px-2 py-6 text-center">
              {error}
            </p>
          )}
          {!loading && !error && !hasResults && query && (
            <p className="text-[11px] text-muted-fg px-2 py-6 text-center">
              No results found.
            </p>
          )}
          {!loading && !error && !query && !hasResults && (
            <p className="text-[11px] text-muted-fg px-2 py-6 text-center">
              Enter a query to search antibody databases.
            </p>
          )}

          {sourceKeys.map((src) => (
            <div key={src} className="mb-2">
              <button
                onClick={() => toggleCollapse(src)}
                className="w-full flex items-center gap-2 px-3 py-1.5 text-left"
              >
                <svg
                  className={`w-3 h-3 text-muted-fg transition-transform ${
                    collapsed.has(src) ? "" : "rotate-90"
                  }`}
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth={2}
                >
                  <polyline points="9 18 15 12 9 6" />
                </svg>
                <span className="text-[10px] font-bold uppercase tracking-widest text-muted-fg">
                  {SOURCE_LABELS[src] ?? src}
                </span>
                <span className="text-[10px] text-muted-fg">
                  ({results[src].length})
                </span>
              </button>

              {!collapsed.has(src) && (
                <ul className="space-y-0.5 px-1">
                  {results[src].map((r) => (
                    <li
                      key={r.id}
                      data-testid="dataset-result-row"
                      className="rounded-lg border border-border-subtle bg-white hover:border-accent/30 transition-colors"
                    >
                      <div className="flex items-start gap-2 px-3 py-2">
                        <input
                          type="checkbox"
                          checked={selected.has(r.id)}
                          onChange={() => toggleSelect(r.id)}
                          className="mt-0.5 shrink-0 accent-accent"
                          aria-label={`Select ${r.title}`}
                        />
                        <div className="flex-1 min-w-0">
                          <div className="flex items-baseline gap-2">
                            <span className="text-xs font-medium text-foreground truncate">
                              {r.title}
                            </span>
                            <span
                              className={`text-[9px] px-1.5 py-0.5 rounded-full font-medium ${
                                DATA_TYPE_COLORS[r.data_type] ??
                                "bg-gray-100 text-gray-600"
                              }`}
                            >
                              {r.data_type}
                            </span>
                          </div>
                          <p className="text-[11px] text-foreground-dim mt-0.5 leading-relaxed line-clamp-2">
                            {r.summary}
                          </p>
                          {r.organism && (
                            <p className="text-[10px] text-muted-fg mt-0.5">
                              {r.organism}
                            </p>
                          )}
                        </div>
                      </div>
                    </li>
                  ))}
                </ul>
              )}
            </div>
          ))}
        </div>

        {/* Footer with import */}
        {hasResults && (
          <div className="px-4 py-2 border-t border-border flex items-center justify-between">
            <p className="text-[10px] text-muted-fg">
              {selected.size} of {allResults.length} selected
            </p>
            <button
              onClick={handleImport}
              disabled={selected.size === 0 || importing}
              data-testid="dataset-import-button"
              className="px-3 py-1.5 rounded-md bg-accent text-white text-xs font-medium hover:bg-accent-hover disabled:opacity-30 transition-colors"
            >
              {importing ? "Importing..." : "Import Selected"}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}
