import { useCallback, useEffect, useRef, useState } from 'react';
import { type InfiniteQueryObserverBaseResult } from 'react-query';
import { useNavigate } from 'react-router';

import Stack from '@material-hu/mui/Stack';

import { logEvent } from 'src/config/logging';
import { useAuth } from 'src/contexts/JWTContext';
import useCustomServerTranslation from 'src/hooks/useCustomServerTranslation';
import {
  EventName,
  TimeTrackingIncidenceNotificationSource,
} from 'src/types/amplitude';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { InfiniteList } from 'src/components/list';

import { SCROLL_LOAD_MORE_THRESHOLD_PX, SKELETON_KEYS } from '../../constants';
import { type NotificationItem } from '../../types';
import {
  formatNotificationCopetin,
  getTimeTrackingIncidenceAmplitudeType,
  translateNotificationDeepLink,
} from '../utils';

import NotificationListItem from './NotificationListItem';
import NotificationListItemSkeleton from './NotificationListItemSkeleton';
import NotificationsEmptyState from './NotificationsEmptyState';
import NotificationsErrorState from './NotificationsErrorState';

type NotificationSidePanelContentProps = {
  notifications: NotificationItem[];
  loading: boolean;
  hasNextPage: boolean | undefined;
  isFetchingNextPage: boolean;
  isMarkingRead: boolean;
  isEmpty: boolean;
  showError: boolean;
  onOpen: () => void;
  onRead: (id: string, read: boolean) => void;
  onDelete: (id: string) => void;
  onFetchNextPage: InfiniteQueryObserverBaseResult['fetchNextPage'];
};

const NotificationSidePanelContent = (
  props: NotificationSidePanelContentProps,
) => {
  const {
    notifications,
    loading,
    hasNextPage,
    isFetchingNextPage,
    isMarkingRead,
    isEmpty,
    showError,
    onFetchNextPage,
    onOpen,
    onRead,
    onDelete,
  } = props;

  const { t } = useLokaliseTranslation('notifications_center');
  const { user } = useAuth();
  const navigate = useNavigate();

  const coursesCustomName = useCustomServerTranslation({
    module: 'LEARNING',
    defaultTranslationKey: 'title_view_courses',
    namespace: 'apps',
  });

  const scrollContainerRef = useRef<HTMLDivElement>(null);
  const [optionsOpenId, setOptionsOpenId] = useState<string | null>(null);

  const handleScroll = useCallback(
    (event: Event) => {
      if (!hasNextPage || isFetchingNextPage) return;
      const target = event.target as HTMLElement;
      const remaining =
        target.scrollHeight - target.scrollTop - target.clientHeight;
      if (remaining <= SCROLL_LOAD_MORE_THRESHOLD_PX) {
        onFetchNextPage();
      }
    },
    [hasNextPage, isFetchingNextPage, onFetchNextPage],
  );

  const handleNotificationClick = useCallback(
    (notification: NotificationItem, moduleValue: string) => {
      onOpen();
      logEvent(EventName.NC_NOTIFICATION_OPEN, { module: moduleValue });
      if (!notification.isRead) {
        onRead(notification.id, true);
      }
      navigate(translateNotificationDeepLink(notification), {
        state: { fromNotifications: true },
      });
      const incidenceType = getTimeTrackingIncidenceAmplitudeType(notification);
      if (incidenceType) {
        logEvent(EventName.TIME_TRACKING_INCIDENCE_NOTIFICATION_OPENED, {
          incidenceType,
          source: TimeTrackingIncidenceNotificationSource.NOTIFICATION_CENTER,
          managerId: user?.id,
        });
      }
    },
    [navigate, onOpen, onRead, user?.id],
  );

  // Attach passive scroll listener for load-more; cleanup on unmount or when handler changes.
  useEffect(() => {
    const el = scrollContainerRef.current;
    if (!el) return;
    el.addEventListener('scroll', handleScroll, { passive: true });
    return () => el.removeEventListener('scroll', handleScroll);
  }, [handleScroll]);

  return (
    <Stack
      ref={scrollContainerRef}
      sx={{
        width: '100%',
        overflowX: 'hidden',
        overflowY: 'auto',
        maxHeight: '100%',
      }}
    >
      <InfiniteList
        sx={{ width: '100%' }}
        isSuccess={!!notifications}
        isLoading={loading}
        isEmpty={notifications?.length === 0}
        fetchNextPage={undefined}
        hasNextPage={hasNextPage}
        isFetchingNextPage={isFetchingNextPage}
        showNoResultsMessage={false}
        loadingSkeleton
        renderSkeleton={
          <Stack sx={{ width: '100%' }}>
            {SKELETON_KEYS.map(key => (
              <NotificationListItemSkeleton key={key} />
            ))}
          </Stack>
        }
      >
        {!loading &&
          notifications.map(notification => {
            const moduleValue = String(notification.module);
            const metaText = formatNotificationCopetin({
              createdAt: notification.createdAt,
              module: moduleValue,
              user,
              t,
              coursesCustomName,
            });
            return (
              <NotificationListItem
                key={notification.id}
                notification={notification}
                metaText={metaText}
                optionsOpenId={optionsOpenId}
                onOptionsOpenChange={setOptionsOpenId}
                isMarkingRead={isMarkingRead}
                onClick={() =>
                  handleNotificationClick(notification, moduleValue)
                }
                onRead={onRead}
                onDelete={onDelete}
              />
            );
          })}
        {isFetchingNextPage && <NotificationListItemSkeleton />}
      </InfiniteList>
      {isEmpty && <NotificationsEmptyState />}
      {showError && <NotificationsErrorState />}
    </Stack>
  );
};

export default NotificationSidePanelContent;
