import { useMemo, useState } from 'react';

import { useCommunicationEvents } from '@/business/communications/hooks';
import { useContentCatalogPayload } from '@/business/content-catalog/hooks';
import {
  getDashboardGreeting,
  selectDashboardActiveZone,
  selectDashboardQuickActions,
  selectDashboardQuote,
  selectDashboardUpcomingEvents,
} from '@/business/dashboard/selectors';
import {
  normalizeSignLanguageItems,
  selectSignLanguageSignOfWeek,
} from '@/business/sign-language/selectors';
import type {
  DashboardPage,
  DashboardProps,
} from '@/business/dashboard/types';
import { useFrameEntries } from '@/business/frame/hooks';
import { getScopedModules } from '@/business/app-shell/selectors';
import { canPersistPersonalScopeResults } from '@/business/scope/selectors';
import { useTodayZoneCheckIn } from '@/business/zone-checkin/hooks';
import { canZoneCheckIn, shouldNudgeZoneCheckIn } from '@/business/zone-checkin/selectors';
import { useScopeContext } from '@/shared/app/scope-context';
import { useAuth } from '@/shared/app/useAuth';
import { MODULES } from '@/shared/constants/appData';
import { CONTENT_CATALOG_TYPES } from '@/shared/constants/contentCatalog';
import { DASHBOARD_ZONE_OPTIONS } from '@/shared/constants/dashboard';
import { getOptionalErrorMessage } from '@/shared/errors/errorMessages';
import type {
  SignItem,
  ZoneColor,
} from '@/shared/types/app';
import type {
  DashboardComplianceItem,
  DashboardEncouragingQuote,
  DashboardSignOfWeek,
} from '@/shared/types/dashboard';

export function useDashboardPage({
  userRole,
  userName,
  setCurrentModule,
  zoneCheckIn,
  setZoneCheckIn,
}: DashboardProps): DashboardPage {
  const { user } = useAuth();
  const { tier, ownTenant, selectedTenant } = useScopeContext();
  const [dashboardDate] = useState(() => new Date());
  const quotesQuery = useContentCatalogPayload<readonly DashboardEncouragingQuote[]>(
    CONTENT_CATALOG_TYPES.dashboardEncouragingQuotes,
    [],
  );
  const complianceItemsQuery = useContentCatalogPayload<readonly DashboardComplianceItem[]>(
    CONTENT_CATALOG_TYPES.dashboardComplianceItems,
    [],
  );
  const signOfWeekQuery = useContentCatalogPayload<DashboardSignOfWeek | null>(
    CONTENT_CATALOG_TYPES.dashboardSignOfWeek,
    null,
  );
  const signsQuery = useContentCatalogPayload<readonly SignItem[]>(
    CONTENT_CATALOG_TYPES.signLanguageItems,
    [],
  );
  const frameEntriesQuery = useFrameEntries();
  const canUseZoneCheckIn = canPersistPersonalScopeResults(ownTenant, selectedTenant) && canZoneCheckIn(user);
  const zoneCheckInState = useTodayZoneCheckIn({ enabled: canUseZoneCheckIn });
  const communicationEventsQuery = useCommunicationEvents();
  const upcomingEvents = useMemo(
    () => selectDashboardUpcomingEvents(communicationEventsQuery.data ?? []),
    [communicationEventsQuery.data],
  );
  const activeZone = selectDashboardActiveZone(zoneCheckIn, zoneCheckInState.todayZone);
  const needsZoneCheckIn = shouldNudgeZoneCheckIn(
    canUseZoneCheckIn ? user : null,
    zoneCheckInState.isLoading,
    zoneCheckInState.isCheckedInToday,
  );
  const todayQuote = useMemo(
    () => selectDashboardQuote(quotesQuery.payload, dashboardDate),
    [dashboardDate, quotesQuery.payload],
  );
  const signs = useMemo(
    () => normalizeSignLanguageItems(signsQuery.payload),
    [signsQuery.payload],
  );
  const signOfWeek = useMemo(
    () => selectSignLanguageSignOfWeek(signs, signOfWeekQuery.payload),
    [signOfWeekQuery.payload, signs],
  );
  const effectiveTier = selectedTenant ? selectedTenant.level : tier;
  const scopedModuleIds = useMemo(
    () => new Set(
      getScopedModules(MODULES, user, effectiveTier, selectedTenant !== null)
        .map((module) => module.id),
    ),
    [effectiveTier, selectedTenant, user],
  );

  async function checkInZone(zone: ZoneColor) {
    await zoneCheckInState.setZone(zone);
    setZoneCheckIn(zone);
  }

  async function resetZone() {
    await zoneCheckInState.clearToday();
    setZoneCheckIn(null);
  }

  return {
    userRole,
    userName,
    greeting: getDashboardGreeting(dashboardDate),
    latestFrame: frameEntriesQuery.data?.[0] ?? null,
    todayQuote,
    quoteState: {
      isLoading: quotesQuery.isLoading,
      isError: Boolean(quotesQuery.error),
    },
    zoneOptions: DASHBOARD_ZONE_OPTIONS,
    showZoneCheckIn: canUseZoneCheckIn,
    activeZone,
    needsZoneCheckIn,
    isZoneSaving: zoneCheckInState.isSaving,
    zoneErrorMessage: getOptionalErrorMessage(zoneCheckInState.error),
    upcomingEvents,
    eventsState: {
      isLoading: communicationEventsQuery.isLoading,
      isError: communicationEventsQuery.isError,
    },
    complianceItems: complianceItemsQuery.payload,
    complianceState: {
      isLoading: complianceItemsQuery.isLoading,
      isError: Boolean(complianceItemsQuery.error),
    },
    signOfWeek,
    signOfWeekState: {
      isLoading: signOfWeekQuery.isLoading || signsQuery.isLoading,
      isError: Boolean(signOfWeekQuery.error || signsQuery.error),
    },
    quickActions: selectDashboardQuickActions(scopedModuleIds),
    goToModule: setCurrentModule,
    checkInZone,
    resetZone,
  };
}
