import { useCallback, useState } from 'react';

import { useInfiniteScroll } from '@/hooks/common/use-infinite-scroll';
import { useTranslation } from '@/lib/i18n';
import type { PullJobResponse, UseModelCatalogPageReturn } from '@/types';

import { useCancelPullJob } from './use-cancel-pull-job';
import { useDeleteModel } from './use-delete-model';
import { useDownloadStats } from './use-download-stats';
import { useModelCatalog } from './use-model-catalog';
import { usePullFromCatalog } from './use-pull-from-catalog';
import { usePullJobs } from './use-pull-jobs';

export function useModelCatalogPage(): UseModelCatalogPageReturn {
  const [category, setCategory] = useState<string | undefined>();
  const [capability, setCapability] = useState<string | undefined>();
  const [search, setSearch] = useState('');
  const { t } = useTranslation();

  const { entries, meta, isLoading, isError, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useModelCatalog({ category, capability, search: search || undefined });

  const sentinelRef = useInfiniteScroll(fetchNextPage, hasNextPage && !isFetchingNextPage);

  const { pullFromCatalog, isPending: isPullPending } = usePullFromCatalog();
  const { pullJobs, isLoading: isPullJobsLoading, hasActiveJobs } = usePullJobs();
  const { cancelJob, isPending: isCancelPending } = useCancelPullJob();
  const { deleteModel, isPending: isDeletePending } = useDeleteModel();
  const downloadStatsMap = useDownloadStats(pullJobs);

  const handleCategoryChange = useCallback((value: string | undefined): void => {
    setCategory(value);
  }, []);

  const handleCapabilityChange = useCallback((value: string | undefined): void => {
    setCapability(value);
  }, []);

  const handleSearchChange = useCallback((value: string): void => {
    setSearch(value);
  }, []);

  const handlePull = useCallback(
    (catalogId: string): void => {
      pullFromCatalog(catalogId);
    },
    [pullFromCatalog],
  );

  const handleCancelJob = useCallback(
    (jobId: string): void => {
      cancelJob(jobId);
    },
    [cancelJob],
  );

  const handleDelete = useCallback(
    (modelId: string): void => {
      deleteModel(modelId);
    },
    [deleteModel],
  );

  const getJobForModel = useCallback(
    (modelName: string): PullJobResponse | undefined => {
      return pullJobs.find((j) => j.modelName === modelName);
    },
    [pullJobs],
  );

  return {
    t,
    entries,
    meta,
    isLoading,
    isError,
    isFetchingNextPage,
    hasNextPage,
    sentinelRef,
    category,
    capability,
    search,
    pullJobs,
    isPullJobsLoading,
    hasActiveJobs,
    downloadStatsMap,
    handleCategoryChange,
    handleCapabilityChange,
    handleSearchChange,
    handlePull,
    handleCancelJob,
    handleDelete,
    isPullPending,
    isCancelPending,
    isDeletePending,
    getJobForModel,
  };
}
