import {
  createContext,
  type PropsWithChildren,
  useCallback,
  useContext,
  useEffect,
  useState,
} from 'react';

import { isNil } from 'lodash-es';

import { useAuth } from 'src/contexts/JWTContext';
import {
  MenuItems,
  type PerformanceReview,
  type ReviewDetail,
} from 'src/pages/dashboard/performance/types';

import { useMenuQueryParam } from './hooks/useMenuQueryParam';
import { getIsReviewShared } from './utils';

export type PerformanceReviewContextValue = {
  reviews: ReviewDetail[];
  setSelectedReview: (num: number | null) => void;
  selectedReview: number | null;
  nextReview: () => void;
  allReviewsCompleted: boolean;
  setAllReviewsCompleted: (allReviewsCompleted: boolean) => void;
  menuSelected: MenuItems;
  setMenuSelected: (item: MenuItems) => void;
  performanceReviewStatus: PerformanceReview['status'] | null;
  userToShareId: number | null;
  setUserToShareId: (userId: number | null) => void;
  isSelectingUser: boolean;
  setIsSelectingUser: (isSelecting: boolean) => void;
  viewingReviewId: number | null;
  setViewingReviewId: (reviewId: number | null) => void;
};

const PerformanceReviewContext = createContext<PerformanceReviewContextValue>({
  reviews: [],
  setSelectedReview: () => null,
  selectedReview: null,
  nextReview: () => null,
  allReviewsCompleted: false,
  setAllReviewsCompleted: () => null,
  menuSelected: MenuItems.COMPLETE_REVIEW,
  setMenuSelected: () => null,
  performanceReviewStatus: null,
  userToShareId: null,
  setUserToShareId: () => null,
  isSelectingUser: false,
  setIsSelectingUser: () => null,
  viewingReviewId: null,
  setViewingReviewId: () => null,
});

type ProviderProps = {
  reviews: ReviewDetail[];
  reviewedFormReviews: ReviewDetail[]; // For reviewed users
  performanceReviewStatus: PerformanceReview['status'];
};

export const PerformanceReviewProvider = (
  props: PropsWithChildren<ProviderProps>,
) => {
  const { user } = useAuth();
  const { reviews, reviewedFormReviews, children, performanceReviewStatus } =
    props;

  const initialMenuFromUrl = useMenuQueryParam();
  const [menuSelected, setMenuSelected] = useState<MenuItems>(
    initialMenuFromUrl ?? MenuItems.COMPLETE_REVIEW,
  );
  const [selectedReview, setSelectedReview] = useState<number | null>(null);
  const [allReviewsCompleted, setAllReviewsCompleted] = useState(false);
  const [userToShareId, setUserToShareId] = useState<number | null>(null);
  const [isSelectingUser, setIsSelectingUser] = useState(false);
  const [viewingReviewId, setViewingReviewId] = useState<number | null>(null);

  // biome-ignore lint/correctness/useExhaustiveDependencies: Not needed
  useEffect(() => {
    if (
      performanceReviewStatus !== 'FINISHED' &&
      reviews?.length === 0 &&
      reviewedFormReviews?.length
    ) {
      // Reviewees can only fetch a review detail once it has been shared with
      // them; auto-selecting an unshared review guarantees a 404 from the
      // detail endpoint.
      const sharedReview = reviewedFormReviews.find(
        ({ reviewedId, shareStatus }) =>
          reviewedId === user?.id && getIsReviewShared(shareStatus),
      );
      if (!isNil(sharedReview)) {
        setSelectedReview(sharedReview.reviewId);
      }
    }
  }, [reviewedFormReviews, reviews]);

  // biome-ignore lint/correctness/useExhaustiveDependencies: Not needed
  useEffect(() => {
    if (performanceReviewStatus === 'FINISHED' && user) {
      setMenuSelected(MenuItems.MY_RESULTS);
      const reviewId = reviewedFormReviews[0]?.id || null;
      setSelectedReview(reviewId);
    }
  }, [performanceReviewStatus]);

  const nextReview = useCallback(
    (allCompleted?: boolean) => {
      if (allCompleted) {
        return setSelectedReview(null);
      }
      const currentIndex = reviews.findIndex(
        ({ reviewId }) => reviewId === selectedReview,
      );

      const nextReviewToHave = reviews[currentIndex + 1];
      setSelectedReview(nextReviewToHave?.reviewId || reviews[0].reviewId);
    },
    [reviews, selectedReview],
  );

  return (
    <PerformanceReviewContext.Provider
      value={{
        reviews,
        selectedReview,
        setSelectedReview,
        nextReview,
        allReviewsCompleted,
        setAllReviewsCompleted,
        menuSelected,
        setMenuSelected,
        performanceReviewStatus,
        setUserToShareId,
        userToShareId,
        isSelectingUser,
        setIsSelectingUser,
        viewingReviewId,
        setViewingReviewId,
      }}
    >
      {children}
    </PerformanceReviewContext.Provider>
  );
};

export const usePerformanceReview = () => useContext(PerformanceReviewContext);
