import { useMemo, useState } from 'react';

import { useContentCatalogPayload } from '@/business/content-catalog/hooks';
import {
  buildSignLanguageCategories,
  filterSignLanguageItems,
  getSignLanguageProgressPercent,
} from '@/business/sign-language/selectors';
import { canPersistPersonalScopeResults } from '@/business/scope/selectors';
import type {
  SignLanguagePage,
  SignLanguageVideoModalState,
} from '@/business/sign-language/types';
import { useLearnedSignsProgress } from '@/business/user-progress/hooks';
import { useScopeContext } from '@/shared/app/scope-context';
import { CONTENT_CATALOG_TYPES } from '@/shared/constants/contentCatalog';
import type {
  SignLanguageCategoryFilter,
  SignLanguageViewMode,
} from '@/shared/constants/signLanguage';
import { getOptionalErrorMessage } from '@/shared/errors/errorMessages';
import type {
  SignItem,
  SignLanguagePageContent,
} from '@/shared/types/app';

const EMPTY_SIGN_LANGUAGE_PAGE_CONTENT: SignLanguagePageContent = {
  rememberTitle: '',
  rememberDescription: '',
};
const EMPTY_LEARNED_SIGN_IDS = new Set<string>();

export function useSignLanguagePage(): SignLanguagePage {
  const { ownTenant, selectedTenant } = useScopeContext();
  const canPersistProgress = canPersistPersonalScopeResults(ownTenant, selectedTenant);
  const signsQuery = useContentCatalogPayload<readonly SignItem[]>(
    CONTENT_CATALOG_TYPES.signLanguageItems,
    [],
  );
  const pageContentQuery = useContentCatalogPayload<SignLanguagePageContent>(
    CONTENT_CATALOG_TYPES.signLanguagePageContent,
    EMPTY_SIGN_LANGUAGE_PAGE_CONTENT,
  );
  const progress = useLearnedSignsProgress({ enabled: canPersistProgress });
  const [searchQuery, setSearchQuery] = useState('');
  const [categoryFilter, setCategoryFilter] = useState<SignLanguageCategoryFilter>('all');
  const [selectedSignId, setSelectedSignId] = useState<string | null>(null);
  const signs = signsQuery.payload;
  const filters = useMemo(
    () => ({
      searchQuery,
      categoryFilter,
    }),
    [categoryFilter, searchQuery],
  );
  const categories = useMemo(
    () => buildSignLanguageCategories(signs),
    [signs],
  );
  const filteredSigns = useMemo(
    () => filterSignLanguageItems(signs, filters),
    [filters, signs],
  );
  const selectedSign = useMemo(
    () => signs.find((sign) => sign.id === selectedSignId) ?? null,
    [selectedSignId, signs],
  );
  const learnedSignIds = canPersistProgress ? progress.learnedSignIds : EMPTY_LEARNED_SIGN_IDS;
  const progressPercent = useMemo(
    () => getSignLanguageProgressPercent(signs, learnedSignIds),
    [learnedSignIds, signs],
  );

  async function toggleLearned(id: string) {
    if (!canPersistProgress) {
      return;
    }

    const sign = signs.find((item) => item.id === id);

    if (!sign) {
      return;
    }

    await progress.toggleLearnedSign(id, sign.word);
  }

  return {
    signs,
    filteredSigns,
    categories,
    filters,
    learnedSignIds,
    learnedCount: learnedSignIds.size,
    progressPercent,
    canPersistProgress,
    selectedSign,
    pageContent: pageContentQuery.payload,
    isLoading: signsQuery.isLoading || pageContentQuery.isLoading || (canPersistProgress && progress.isLoading),
    isSaving: canPersistProgress && progress.isSaving,
    signsError: signsQuery.error,
    pageContentError: pageContentQuery.error,
    progressErrorMessage: getOptionalErrorMessage(progress.error),
    setSearchQuery,
    clearSearch: () => setSearchQuery(''),
    setCategoryFilter,
    selectSign: setSelectedSignId,
    closeSign: () => setSelectedSignId(null),
    toggleLearned,
  };
}

export function useSignLanguageVideoModalState(): SignLanguageVideoModalState {
  const [showSteps, setShowSteps] = useState(false);
  const [viewMode, setViewMode] = useState<SignLanguageViewMode>('gif');
  const [gifLoaded, setGifLoaded] = useState(false);
  const [gifError, setGifError] = useState(false);

  return {
    showSteps,
    viewMode,
    gifLoaded,
    gifError,
    showStepGuide: () => setShowSteps(true),
    hideStepGuide: () => setShowSteps(false),
    toggleStepGuide: () => setShowSteps((current) => !current),
    setViewMode,
    markGifLoaded: () => setGifLoaded(true),
    markGifFailed: () => {
      setGifError(true);
      setGifLoaded(true);
    },
  };
}
