import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';

import {
  useContentCatalogPayload,
  useManagedContentCatalog,
} from '@/business/content-catalog/hooks';
import {
  filterEsaFaqsByAudience,
  isEsaExternalAudience,
  normalizeEsaFundingContent,
  toggleEsaFaq,
} from '@/business/esa-funding/selectors';
import type { EsaFundingPage } from '@/business/esa-funding/types';
import { CONTENT_CATALOG_TYPES } from '@/shared/constants/contentCatalog';
import type { EsaFundingContent } from '@/shared/types/esaFunding';
import { useAuth } from '@/shared/app/useAuth';
import { useScopeContext } from '@/shared/app/scope-context';
import { usePermissions } from '@/shared/app/usePermissions';
import {
  useAcknowledgePolicy,
  useEsaFundingPolicyDocument,
  usePolicyAcknowledgments,
} from '@/business/policies/hooks';
import { isPolicyDocumentAcknowledged } from '@/business/policies/selectors';
import {
  createManagedContentCatalog,
  updateManagedContentCatalog,
} from '@/shared/api/contentCatalog';
import { CONTENT_CATALOG_QUERY_KEYS } from '@/shared/constants/contentCatalog';
import { POLICY_QUERY_KEYS } from '@/shared/constants/policies';

interface EsaFundingSaveInput {
  readonly content: EsaFundingContent;
  readonly sectionName: string;
}

export const EMPTY_ESA_FUNDING_CONTENT: EsaFundingContent = {
  schoolImpactItems: [],
  staffRoleItems: [],
  faqs: [],
  parentConversationReferences: [],
  resources: [],
};

export function useEsaFundingPage(): EsaFundingPage {
  const { user } = useAuth();
  const { effectiveTenant } = useScopeContext();
  const permissions = usePermissions();
  const queryClient = useQueryClient();
  const canManage = permissions.has('MANAGE_ESA_FUNDING_CONTENT')
    && effectiveTenant?.level === 'campus';
  const externalAudience = isEsaExternalAudience(user);
  const hasCampusContentScope = effectiveTenant?.level === 'campus'
    || effectiveTenant?.level === 'class'
    || Boolean(user?.campusId);
  const contentQuery = useContentCatalogPayload<EsaFundingContent>(
    CONTENT_CATALOG_TYPES.esaFundingContent,
    EMPTY_ESA_FUNDING_CONTENT,
    { enabled: hasCampusContentScope },
  );
  const managedQuery = useManagedContentCatalog<EsaFundingContent>(
    CONTENT_CATALOG_TYPES.esaFundingContent,
    { enabled: canManage },
  );
  const saveContentMutation = useMutation({
    mutationFn: ({ content: nextContent, sectionName }: EsaFundingSaveInput) => (
      managedQuery.data
        ? updateManagedContentCatalog(CONTENT_CATALOG_TYPES.esaFundingContent, {
            payload: nextContent,
            changeSummary: sectionName,
          })
        : createManagedContentCatalog({
            content_type: CONTENT_CATALOG_TYPES.esaFundingContent,
            payload: nextContent,
            changeSummary: sectionName,
          })
    ),
    onSuccess: async (response) => {
      const normalizedPayload = normalizeEsaFundingContent(response.payload);

      queryClient.setQueryData(
        [...CONTENT_CATALOG_QUERY_KEYS.content, CONTENT_CATALOG_TYPES.esaFundingContent],
        normalizedPayload,
      );
      queryClient.setQueryData(
        [...CONTENT_CATALOG_QUERY_KEYS.content, 'managed', CONTENT_CATALOG_TYPES.esaFundingContent],
        {
          ...response,
          payload: normalizedPayload,
        },
      );

      await Promise.all([
        queryClient.invalidateQueries({
          queryKey: [...CONTENT_CATALOG_QUERY_KEYS.content, CONTENT_CATALOG_TYPES.esaFundingContent],
        }),
        queryClient.invalidateQueries({
          queryKey: [...CONTENT_CATALOG_QUERY_KEYS.content, 'managed', CONTENT_CATALOG_TYPES.esaFundingContent],
        }),
        queryClient.invalidateQueries({ queryKey: POLICY_QUERY_KEYS.esaDocuments }),
        queryClient.invalidateQueries({ queryKey: POLICY_QUERY_KEYS.acknowledgments }),
      ]);
    },
  });
  const canAcknowledge = !externalAudience && permissions.has('ACK_POLICY');
  const policyDocumentQuery = useEsaFundingPolicyDocument(canAcknowledge);
  const acknowledgmentsQuery = usePolicyAcknowledgments(canAcknowledge);
  const acknowledgePolicy = useAcknowledgePolicy();
  const [expandedFAQ, setExpandedFAQ] = useState<number | null>(0);
  const normalizedContent = normalizeEsaFundingContent(contentQuery.payload);
  const content = externalAudience
    ? {
        ...normalizedContent,
        staffRoleItems: [],
        parentConversationReferences: [],
      }
    : normalizedContent;
  const policyDocument = policyDocumentQuery.data ?? null;
  const acknowledged = canAcknowledge && policyDocument
    ? isPolicyDocumentAcknowledged(
        acknowledgmentsQuery.data ?? [],
        policyDocument.id,
        policyDocument.version,
      )
    : false;

  return {
    content,
    faqs: filterEsaFaqsByAudience(content.faqs, externalAudience),
    expandedFAQ,
    acknowledged,
    canManage,
    canAcknowledge,
    isSaving: saveContentMutation.isPending || managedQuery.isLoading,
    isLoading: contentQuery.isLoading,
    error: contentQuery.error
      ?? managedQuery.error
      ?? saveContentMutation.error
      ?? acknowledgePolicy.error,
    toggleFAQ: (index) => setExpandedFAQ((currentIndex) => toggleEsaFaq(currentIndex, index)),
    toggleAcknowledged: () => {
      if (canAcknowledge && policyDocument && !acknowledged) {
        acknowledgePolicy.mutate(policyDocument.id);
      }
    },
    saveContent: async (nextContent, sectionName) => {
      await saveContentMutation.mutateAsync({
        content: normalizeEsaFundingContent(nextContent),
        sectionName,
      });
    },
  };
}
