import { useState, useCallback, useEffect } from "react";
import {
  listChains,
  getChain,
  createChain,
  updateChain,
  archiveChain,
  getChainGraph,
  type ChainSummary,
  type ChainWithContracts,
  type ChainGraphResponse,
  type ChainStatus,
  type CreateChainRequest,
  type UpdateChainRequest,
} from "../lib/api";

interface UseChainsResult {
  chains: ChainSummary[];
  loading: boolean;
  error: string | null;
  refresh: () => Promise<void>;
  createNewChain: (req: CreateChainRequest) => Promise<ChainWithContracts | null>;
  updateExistingChain: (
    chainId: string,
    req: UpdateChainRequest
  ) => Promise<ChainWithContracts | null>;
  archiveExistingChain: (chainId: string) => Promise<boolean>;
  getChainById: (chainId: string) => Promise<ChainWithContracts | null>;
  getGraph: (chainId: string) => Promise<ChainGraphResponse | null>;
}

export function useChains(statusFilter?: ChainStatus): UseChainsResult {
  const [chains, setChains] = useState<ChainSummary[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchChains = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await listChains(statusFilter);
      setChains(response.chains);
    } catch (err) {
      console.error("Failed to fetch chains:", err);
      setError(err instanceof Error ? err.message : "Failed to fetch chains");
    } finally {
      setLoading(false);
    }
  }, [statusFilter]);

  useEffect(() => {
    fetchChains();
  }, [fetchChains]);

  const createNewChain = useCallback(
    async (req: CreateChainRequest): Promise<ChainWithContracts | null> => {
      try {
        const chain = await createChain(req);
        // Refresh the list
        await fetchChains();
        // Return the full chain with contracts
        return await getChain(chain.id);
      } catch (err) {
        console.error("Failed to create chain:", err);
        setError(err instanceof Error ? err.message : "Failed to create chain");
        return null;
      }
    },
    [fetchChains]
  );

  const updateExistingChain = useCallback(
    async (
      chainId: string,
      req: UpdateChainRequest
    ): Promise<ChainWithContracts | null> => {
      try {
        await updateChain(chainId, req);
        // Refresh the list
        await fetchChains();
        // Return the updated chain
        return await getChain(chainId);
      } catch (err) {
        console.error("Failed to update chain:", err);
        setError(err instanceof Error ? err.message : "Failed to update chain");
        return null;
      }
    },
    [fetchChains]
  );

  const archiveExistingChain = useCallback(
    async (chainId: string): Promise<boolean> => {
      try {
        await archiveChain(chainId);
        // Refresh the list
        await fetchChains();
        return true;
      } catch (err) {
        console.error("Failed to archive chain:", err);
        setError(err instanceof Error ? err.message : "Failed to archive chain");
        return false;
      }
    },
    [fetchChains]
  );

  const getChainById = useCallback(
    async (chainId: string): Promise<ChainWithContracts | null> => {
      try {
        return await getChain(chainId);
      } catch (err) {
        console.error("Failed to get chain:", err);
        setError(err instanceof Error ? err.message : "Failed to get chain");
        return null;
      }
    },
    []
  );

  const getGraph = useCallback(
    async (chainId: string): Promise<ChainGraphResponse | null> => {
      try {
        return await getChainGraph(chainId);
      } catch (err) {
        console.error("Failed to get chain graph:", err);
        setError(err instanceof Error ? err.message : "Failed to get chain graph");
        return null;
      }
    },
    []
  );

  return {
    chains,
    loading,
    error,
    refresh: fetchChains,
    createNewChain,
    updateExistingChain,
    archiveExistingChain,
    getChainById,
    getGraph,
  };
}
