"use client";

import { useState, useCallback, useEffect, useMemo } from "react";
import {
  StemeDBClient,
  type GetCorpusResponse,
  type CorpusItemDto,
  ApiError,
} from "@/lib/api";
import type { PanelState } from "@/lib/types";
import { CORPUS_FETCH_LIMIT } 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<GetCorpusResponse>>({
    status: "idle",
  });

  // Input state (controlled form inputs) - doesn't trigger fetch
  const [inputSources, setInputSources] = useState<string[]>(["rfc", "owasp", "community"]);

  // Search state (actual search params) - triggers fetch
  const [searchSources, setSearchSources] = useState<string[]>(["rfc", "owasp", "community"]);

  // Client-side filter state
  const [filterCategory, setFilterCategory] = useState<string>("all");

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

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

  // Handle form submit - update search params which triggers fetch
  const handleSubmit = useCallback(() => {
    setSearchSources(inputSources);
  }, [inputSources]);

  // Handle clear - reset both input and search state
  const handleClear = useCallback(() => {
    const defaultSources = ["rfc", "owasp", "community"];
    setInputSources(defaultSources);
    setSearchSources(defaultSources);
    setFilterCategory("all");
  }, []);

  // Get raw items from server
  const rawItems = state.status === "success" ? state.data.items : [];

  // Extract available categories from items
  const availableCategories = useMemo(() => {
    const categories = new Set<string>();
    rawItems.forEach((item) => {
      if (item.category) {
        categories.add(item.category);
      }
    });
    return Array.from(categories).sort();
  }, [rawItems]);

  // Apply client-side filters
  const items = useMemo(() => {
    return rawItems.filter((item: CorpusItemDto) => {
      // Category filter
      if (filterCategory !== "all" && item.category !== filterCategory) {
        return false;
      }
      return true;
    });
  }, [rawItems, filterCategory]);

  const hasActiveFilter =
    searchSources.length !== 3 || // Default is 3 sources
    filterCategory !== "all";

  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">
          Authoritative Corpus
        </h2>
        <p className="text-sm text-muted-foreground">
          Explore best practices from RFC, OWASP, and community-validated patterns.
          These authoritative assertions represent trusted security and architecture guidelines.
        </p>
      </div>

      {/* Content */}
      <div className="rounded-lg border border-border bg-card p-6">
        <div className="space-y-6">
          {/* Filters - always visible */}
          <CorpusFilters
            sources={inputSources}
            filterCategory={filterCategory}
            availableCategories={availableCategories}
            onSourcesChange={setInputSources}
            onFilterCategoryChange={setFilterCategory}
            onSubmit={handleSubmit}
            onClear={handleClear}
            totalCount={state.status === "success" ? state.data.total_matching : 0}
            filteredCount={items.length}
            isLoading={state.status === "loading"}
            hasActiveFilter={hasActiveFilter}
          />

          {/* Loading State */}
          {state.status === "loading" && <CorpusLoadingSkeleton />}

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

          {/* Success State */}
          {state.status === "success" && (
            <>
              {items.length === 0 ? (
                <CorpusEmptyState
                  hasFilter={hasActiveFilter}
                  onClearFilter={handleClear}
                />
              ) : (
                <CorpusList items={items} />
              )}
            </>
          )}

          {/* Initial/Idle State */}
          {state.status === "idle" && <CorpusLoadingSkeleton />}
        </div>
      </div>
    </div>
  );
}
