"use client";

import { useState, useCallback, useEffect } from "react";
import {
  StemeDBClient,
  type GetPatternsResponse,
  ApiError,
} from "@/lib/api";
import type { PanelState } from "@/lib/types";
import { CORPUS_FETCH_LIMIT, DEFAULT_MIN_PROJECTS } from "./constants";
import { ErrorState } from "@/components/shared/error-state";
import { CorpusFilters } from "./corpus-filters";
import { CorpusList } from "./corpus-list";
import { CorpusLoadingSkeleton } from "./corpus-loading-skeleton";
import { CorpusEmptyState } from "./corpus-empty-state";

export function CorpusPanel() {
  const [state, setState] = useState<PanelState<GetPatternsResponse>>({
    status: "idle",
  });
  const [subjectPrefix, setSubjectPrefix] = useState("");
  const [minProjects, setMinProjects] = useState(DEFAULT_MIN_PROJECTS);

  // Debounced filter values for API calls
  const [debouncedPrefix, setDebouncedPrefix] = useState("");

  // Debounce the subject prefix
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedPrefix(subjectPrefix);
    }, 300);
    return () => clearTimeout(timer);
  }, [subjectPrefix]);

  const fetchData = useCallback(async () => {
    setState({ status: "loading" });
    try {
      const client = new StemeDBClient();
      const data = await client.getPatterns({
        subjectPrefix: debouncedPrefix || undefined,
        minProjects,
        limit: CORPUS_FETCH_LIMIT,
      });
      setState({ status: "success", data });
    } catch (err) {
      // 404 means no patterns - treat as empty success
      if (err instanceof ApiError && err.status === 404) {
        setState({
          status: "success",
          data: { patterns: [], total_matching: 0 },
        });
        return;
      }
      const message =
        err instanceof ApiError
          ? err.userMessage
          : err instanceof Error
            ? err.message
            : "Unknown error";
      setState({ status: "error", error: message });
    }
  }, [debouncedPrefix, minProjects]);

  // Fetch on mount and when filters change
  useEffect(() => {
    fetchData();
  }, [fetchData]);

  // Patterns from successful state (filtering done server-side)
  const patterns = state.status === "success" ? state.data.patterns : [];

  const handleClearFilter = useCallback(() => {
    setSubjectPrefix("");
    setMinProjects(DEFAULT_MIN_PROJECTS);
  }, []);

  const hasFilter = subjectPrefix !== "" || minProjects > DEFAULT_MIN_PROJECTS;

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="rounded-lg border border-border bg-card p-6">
        <h2 className="text-lg font-medium text-card-foreground mb-2">
          Community Corpus
        </h2>
        <p className="text-sm text-muted-foreground">
          Explore patterns discovered across projects using Aphoria. These anonymized
          observations help establish community consensus on configurations and practices.
        </p>
      </div>

      {/* Content */}
      <div className="rounded-lg border border-border bg-card p-6">
        {state.status === "idle" && <CorpusLoadingSkeleton />}
        {state.status === "loading" && <CorpusLoadingSkeleton />}

        {state.status === "error" && (
          <ErrorState
            title="Failed to Load Patterns"
            error={state.error}
            onRetry={fetchData}
          />
        )}

        {state.status === "success" && (
          <div className="space-y-6">
            <CorpusFilters
              subjectPrefix={subjectPrefix}
              minProjects={minProjects}
              onSubjectPrefixChange={setSubjectPrefix}
              onMinProjectsChange={setMinProjects}
              totalCount={state.data.total_matching}
              filteredCount={patterns.length}
            />

            {patterns.length === 0 ? (
              <CorpusEmptyState
                hasFilter={hasFilter}
                onClearFilter={handleClearFilter}
              />
            ) : (
              <CorpusList patterns={patterns} />
            )}
          </div>
        )}
      </div>
    </div>
  );
}
