"use client";

import { useState, useCallback, useEffect } from "react";
import {
  StemeDBClient,
  type ListScansResponse,
  type FindingDto,
  ApiError,
} from "@/lib/api";
import type { PanelState } from "@/lib/types";
import { ErrorState } from "@/components/shared/error-state";
import { ScanForm } from "./scan-form";
import { ScansList } from "./scans-list";
import { ScansLoadingSkeleton } from "./scans-loading-skeleton";
import { ScansEmptyState } from "./scans-empty-state";
import { FindingDetailSheet } from "./finding-detail-sheet";

export function ScansPanel() {
  const [state, setState] = useState<PanelState<ListScansResponse>>({
    status: "idle",
  });
  const [isScanning, setIsScanning] = useState(false);
  const [scanError, setScanError] = useState<string | null>(null);
  const [selectedFinding, setSelectedFinding] = useState<FindingDto | null>(null);

  const fetchData = useCallback(async () => {
    setState({ status: "loading" });
    try {
      const client = new StemeDBClient();
      const data = await client.listScans();
      setState({ status: "success", data });
    } catch (err) {
      // 404 means no scans - treat as empty success
      if (err instanceof ApiError && err.status === 404) {
        setState({
          status: "success",
          data: { scans: [] },
        });
        return;
      }
      const message =
        err instanceof ApiError
          ? err.userMessage
          : err instanceof Error
            ? err.message
            : "Unknown error";
      setState({ status: "error", error: message });
    }
  }, []);

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

  const handleScan = useCallback(async (targetPath: string) => {
    setIsScanning(true);
    setScanError(null);
    try {
      const client = new StemeDBClient();
      await client.runScan({ target_path: targetPath });
      // Refresh the list to show the new scan
      await fetchData();
    } catch (err) {
      const message =
        err instanceof ApiError
          ? err.userMessage
          : err instanceof Error
            ? err.message
            : "Scan failed";
      setScanError(message);
    } finally {
      setIsScanning(false);
    }
  }, [fetchData]);

  const handleFindingClick = useCallback((finding: FindingDto) => {
    setSelectedFinding(finding);
  }, []);

  const handleCloseSheet = useCallback(() => {
    setSelectedFinding(null);
  }, []);

  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">
          Aphoria Scans
        </h2>
        <p className="text-sm text-muted-foreground">
          Run scans to check your code for conflicts against authoritative sources.
          View scan history and drill into findings for details.
        </p>
      </div>

      {/* Scan Form */}
      <div className="rounded-lg border border-border bg-card p-6">
        <ScanForm onScan={handleScan} isScanning={isScanning} />
        {scanError && (
          <div className="mt-4 p-3 rounded-md bg-red-500/10 border border-red-500/20 text-sm text-red-600 dark:text-red-400">
            {scanError}
          </div>
        )}
      </div>

      {/* Content */}
      <div className="rounded-lg border border-border bg-card p-6">
        <h3 className="text-sm font-medium text-foreground mb-4">Recent Scans</h3>

        {state.status === "idle" && <ScansLoadingSkeleton />}
        {state.status === "loading" && <ScansLoadingSkeleton />}

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

        {state.status === "success" && (
          state.data.scans.length === 0 ? (
            <ScansEmptyState />
          ) : (
            <ScansList scans={state.data.scans} onFindingClick={handleFindingClick} />
          )
        )}
      </div>

      {/* Finding Detail Sheet */}
      <FindingDetailSheet
        finding={selectedFinding}
        isOpen={selectedFinding !== null}
        onClose={handleCloseSheet}
      />
    </div>
  );
}
