import { type FC, Suspense, useCallback, useEffect, useState } from 'react';
import { useMutation, useQuery } from 'react-query';

import {
  IconPlayerPlay,
  IconSquare,
  IconUsersPlus,
} from '@material-hu/icons/tabler';
import { type AppBarProps } from '@material-hu/mui/AppBar';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import HuHomeHeader from '@material-hu/components/design-system/Header/Home';
import { type HomeHeaderProps as HuHomeHeaderProps } from '@material-hu/components/design-system/Header/Home/types';
import HuSpinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';

import { logEvent } from 'src/config/amplitude';
import { queryClient } from 'src/config/react-query';
import { isProd } from 'src/constants/env';
import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import usePermissions from 'src/hooks/usePermissions';
import { useVoiceflowChatbot } from 'src/hooks/useVoiceflowChatbot';
import { useNotificationsBellOpenState } from 'src/pages/dashboard/notifications/hooks';
import { notificationCenterKeys } from 'src/pages/dashboard/notifications/queries';
import {
  clearNotificationsBuble,
  getCountNotifications,
} from 'src/pages/dashboard/notifications/services';
import { type NotificationsStatsData } from 'src/pages/dashboard/notifications/types';
import {
  hasUnreadNotifications,
  updateTitleAndBadgeFromCount,
} from 'src/pages/dashboard/notifications/utils';
import GlobalSearch from 'src/pages/dashboard/search/components/global-search';
import { Destination, EventName } from 'src/types/amplitude';
import { EntryType } from 'src/types/timeTracking';
import { instanceHidesSupport } from 'src/utils/instance';
import { lazyRetry } from 'src/utils/lazyRetry';
import {
  UserBackOfficePermissions,
  UserPermissions,
} from 'src/utils/permissions';
import { getFullName, getInitials } from 'src/utils/userUtils';

import { useClockingInfo } from '../hooks/timeTracking';
import { useTranslation } from '../i18n';
import { markingClockSx } from '../MarkingClock/constants';
import { useMarkingClockDrawer } from '../MarkingClock/useMarkingClock';

const AccountPopoverContent = lazyRetry(
  () => import('src/components/dashboard/navbar/AccountPopoverContent'),
);
const LanguageMenu = lazyRetry(
  () => import('src/components/dashboard/navbar/LanguageMenu'),
);
const NotificationsSidePanelAdapter = lazyRetry(
  () =>
    import(
      'src/pages/dashboard/notifications/sidepanel/NotificationsSidePanelAdapter'
    ),
);
const AddPeopleDialog = lazyRetry(
  () => import('src/components/dashboard/navbar/NewPeopleButton'),
);
const { INVITE_USERS } = UserPermissions;

const LazyFallback = () => <HuSpinner />;

const helpCenterUrl = {
  es: 'https://help.humand.co/hc/es-419?utm_source=platform&utm_medium=humandweb',
  en: 'https://help.humand.co/hc/en-us?utm_source=platform&utm_medium=humandwebEN',
  bg: 'https://help.humand.co/hc/bg-bg?utm_source=platform&utm_medium=humandwebBG',
  pt: 'https://help.humand.co/hc/pt?utm_medium=humandwebPT&utm_source=platform',
  'pt-br':
    'https://help.humand.co/hc/pt?utm_medium=humandwebPT&utm_source=platform',
};

const getHelpUrl = (language: string) => {
  const normalized = language.toLowerCase();
  const baseLanguage = normalized.split('-')[0];
  return (
    helpCenterUrl[normalized as keyof typeof helpCenterUrl] ||
    helpCenterUrl[baseLanguage as keyof typeof helpCenterUrl] ||
    helpCenterUrl.en
  );
};

export type DashboardNavbarProps = AppBarProps & {
  onSidebarInteraction: () => void;
  sidebarDisabled?: boolean;
  hidden: boolean;
  isSidebarCollapsed: boolean;
};

const DashboardNavbar: FC<DashboardNavbarProps> = props => {
  const {
    onSidebarInteraction,
    sidebarDisabled = false,
    hidden,
    isSidebarCollapsed,
  } = props;
  const { instance, user } = useAuth();
  const { t, i18n } = useTranslation();
  const [openAddPeopleDialog, setOpenAddPeopleDialog] = useState(false);
  const theme = useTheme();
  const [languageAnchorEl, setLanguageAnchorEl] =
    useState<HTMLButtonElement | null>(null);
  const [avatarPopoverOpen, setAvatarPopoverOpen] = useState(false);

  const socket = useSocket();

  const { hasAny: hasBackOfficePermissions } = usePermissions(
    Object.values(UserBackOfficePermissions),
  );

  const { hasAll: canInviteUsers } = usePermissions([INVITE_USERS]);
  const hideSupport = instanceHidesSupport(instance?.id);

  const { data: unreadNotificationsCount } = useQuery(
    notificationCenterKeys.stats(),
    () => getCountNotifications(),
    {
      select: res => res.data.newSinceLastSeen,
      refetchOnWindowFocus: false,
    },
  );

  const {
    mutate: clearNotificationsBubleMutation,
    isLoading: isClearingBubble,
  } = useMutation(() => clearNotificationsBuble(), {
    onSuccess: () => {
      queryClient.invalidateQueries(notificationCenterKeys.stats());
    },
  });

  const clearBubbleIfUnread = useCallback(() => {
    if (isClearingBubble) return;
    if (hasUnreadNotifications(unreadNotificationsCount)) {
      clearNotificationsBubleMutation();
    }
  }, [
    isClearingBubble,
    unreadNotificationsCount,
    clearNotificationsBubleMutation,
  ]);

  const [
    isNotificationsOpen,
    handleNotificationsBellClick,
    setNotificationsOpen,
  ] = useNotificationsBellOpenState(false, {
    onBeforeToggle: () => {
      setAvatarPopoverOpen(false);
      setLanguageAnchorEl(null);
      clearBubbleIfUnread();
    },
  });

  useVoiceflowChatbot();

  const handleOpenAddPeople = () => {
    setOpenAddPeopleDialog(true);
  };

  const handleOpenLanguageMenu = (
    event: React.MouseEvent<HTMLButtonElement>,
  ) => {
    setAvatarPopoverOpen(false);
    setNotificationsOpen(false);
    setLanguageAnchorEl(event.currentTarget);
  };

  const handleCloseLanguageMenu = () => {
    setLanguageAnchorEl(null);
  };

  const handleCloseNotificationsMenu = () => {
    setNotificationsOpen(false);
  };

  const handleOpenAvatarMenu = () => {
    setLanguageAnchorEl(null);
    setNotificationsOpen(false);
    setAvatarPopoverOpen(true);
  };

  const helpUrl = getHelpUrl(i18n.language);

  const {
    clockTime,
    isClockRunning,
    isFetchingClockingInfo,
    isFetchingUserTrackingSites,
    isLoadingToggleClock,
    lastEntryStart,
    timeTrackingClockIsEnabled,
    toggleClockMutation,
    userTrackingSites,
  } = useClockingInfo();

  const userHasMultipleSites =
    userTrackingSites && userTrackingSites?.length > 1;

  const { drawer: MarkingClockDrawer, showMarkingClockDrawer } =
    useMarkingClockDrawer({
      toggleClockMutation,
      isLoadingToggleClock,
      entryType: isClockRunning ? EntryType.END : EntryType.START,
    });

  const handleStopClock = () => {
    logEvent(EventName.TIME_TRACKING_CLOCK_OPENED, {});
    if (userHasMultipleSites) {
      showMarkingClockDrawer({
        lastEntrySite:
          userTrackingSites.find(site => site.id === lastEntryStart?.siteId) ||
          null,
      });
    } else {
      toggleClockMutation({
        type: EntryType.END,
        siteId: lastEntryStart?.siteId ?? null,
        location: lastEntryStart?.location ?? null,
      });
    }
  };

  const handleStartClock = () => {
    logEvent(EventName.TIME_TRACKING_CLOCK_OPENED, {});
    if (userHasMultipleSites) {
      showMarkingClockDrawer({ lastEntrySite: null });
    } else {
      toggleClockMutation({
        type: EntryType.START,
        siteId: userTrackingSites?.[0]?.id ?? null,
        location: userTrackingSites?.[0]?.location ?? null,
      });
    }
  };

  useEffect(() => {
    if (!socket) {
      return;
    }

    const handleNotificationCreated = () => {
      queryClient.invalidateQueries(notificationCenterKeys.stats());
      queryClient
        .refetchQueries({ queryKey: notificationCenterKeys.stats() })
        .then(() => {
          const data = queryClient.getQueryData<{
            data?: NotificationsStatsData;
          }>(notificationCenterKeys.stats())?.data;
          updateTitleAndBadgeFromCount(
            data?.newSinceLastSeen ?? 0,
            data?.capped ?? false,
          );
        })
        .catch(() => undefined);
    };

    socket.listenEvent(
      EVENTS_SOCKETS.NEW_NOTIFICATION_CREATED,
      handleNotificationCreated,
    );

    return () => {
      socket.closeEvent(
        EVENTS_SOCKETS.NEW_NOTIFICATION_CREATED,
        handleNotificationCreated,
      );
    };
  }, [socket]);

  const isLoadingClock =
    isFetchingClockingInfo ||
    isFetchingUserTrackingSites ||
    isLoadingToggleClock;

  return (
    <Stack>
      {MarkingClockDrawer}
      <HuHomeHeader
        id="dashboard-navbar"
        onOpenMenu={onSidebarInteraction}
        logoSrc={instance?.logo || ''}
        logoAlt={t('COMPANY_LOGO_ALT', { companyName: instance?.name })}
        centerContent={
          //TODO: check globalSearch community feature flag and remove isProd check
          !isProd && (
            <Stack
              sx={{
                // Offset the search to visually compensate for the sidebar's
                // expanded/collapsed width. min() caps the offset by a theme
                // spacing step while still scaling with the viewport — a
                // responsive expression that unitless theme spacing alone
                // can't capture.
                pr: theme =>
                  isSidebarCollapsed ? `min(${theme.spacing(3)}, 10%)` : 0,
                pl: theme =>
                  isSidebarCollapsed ? 0 : `min(${theme.spacing(23)}, 20%)`,
                width: '100%',
                alignItems: 'center',
              }}
            >
              <GlobalSearch />
            </Stack>
          )
        }
        extraOptions={
          [
            canInviteUsers && {
              key: 'add-people',
              children: t('NEW_PEOPLE'),
              startIcon: <IconUsersPlus size={16} />,
              onClick: handleOpenAddPeople,
            },
            hasBackOfficePermissions && {
              key: 'admin',
              children: t('ADMIN'),
              href: import.meta.env.VITE_ADMIN_URL,
              target: '_blank',
              rel: 'noreferrer',
            },
            timeTrackingClockIsEnabled && {
              key: 'time-tracking-clock',
              children: isClockRunning ? (
                <Stack
                  direction="row"
                  sx={{ alignItems: 'center', gap: 0.5 }}
                >
                  <Typography
                    variant="globalXS"
                    sx={{ fontWeight: 'fontWeightSemiBold' }}
                  >
                    {`${clockTime.hours} ${clockTime.minutes}`}
                  </Typography>
                  <Typography variant="globalXS">
                    {`${clockTime.seconds}`}
                  </Typography>
                </Stack>
              ) : (
                t('START')
              ),
              startIcon: isClockRunning ? (
                <IconSquare color="error" />
              ) : (
                <IconPlayerPlay />
              ),
              color: isClockRunning ? 'error' : 'primary',
              onClick: isClockRunning ? handleStopClock : handleStartClock,
              disabled: isLoadingClock,
              sx: markingClockSx(isClockRunning),
            },
          ].filter(Boolean) as HuHomeHeaderProps['extraOptions']
        }
        hideSupportButton={hideSupport}
        avatarPopoverContent={
          <Suspense fallback={<LazyFallback />}>
            <AccountPopoverContent />
          </Suspense>
        }
        onOpenAvatarMenu={handleOpenAvatarMenu}
        avatarPopoverOpen={avatarPopoverOpen}
        onAvatarPopoverOpenChange={setAvatarPopoverOpen}
        hideLanguageButton
        onOpenLanguageMenu={handleOpenLanguageMenu}
        onOpenNotificationsMenu={handleNotificationsBellClick}
        notificationsCount={unreadNotificationsCount}
        hasUnreadNotifications={hasUnreadNotifications(
          unreadNotificationsCount,
        )}
        hideMenuButton={hidden}
        disabledMenuButton={sidebarDisabled}
        supportButtonProps={{
          href: helpUrl,
          target: '_blank',
          onClick: () => {
            logEvent(EventName.SUPPORT_APP_CONTACTED, {
              destination: Destination.HELP_CENTER,
            });
            return true;
          },
        }}
        avatarProps={{
          src: user?.profilePicture || undefined,
          alt: t('PROFILE_PICTURE_ALT', { userName: user?.firstName }),
          text: getInitials(getFullName(user)),
        }}
        sx={{
          zIndex: theme.zIndex.drawer + 100,
        }}
      />
      {languageAnchorEl && (
        <Suspense fallback={<LazyFallback />}>
          <LanguageMenu
            anchorEl={languageAnchorEl}
            onClose={handleCloseLanguageMenu}
          />
        </Suspense>
      )}
      {isNotificationsOpen && (
        <Suspense fallback={<LazyFallback />}>
          <NotificationsSidePanelAdapter
            open={isNotificationsOpen}
            onClose={handleCloseNotificationsMenu}
          />
        </Suspense>
      )}
      {canInviteUsers && openAddPeopleDialog && (
        <Suspense fallback={<LazyFallback />}>
          <AddPeopleDialog
            open={openAddPeopleDialog}
            onOpenChange={setOpenAddPeopleDialog}
          />
        </Suspense>
      )}
    </Stack>
  );
};

export default DashboardNavbar;
