import { queryClient } from 'src/config/react-query';
import {
  type CycleQueryData,
  type QueryFilter,
  type QueryId,
  type ReviewRole,
} from 'src/pages/dashboard/performance/types';

export const performanceKeys = {
  all: () => ['performance'],
  list: (page: number, limit: number, q: string) => [
    ...performanceKeys.all(),
    'list',
    page,
    limit,
    q,
  ],
  cycle: (id: QueryId) => [...performanceKeys.all(), 'cycle', id],
  review: (cycleId: QueryId, reviewId: QueryId) => [
    ...performanceKeys.all(),
    'review',
    cycleId,
    reviewId,
  ],
  cycleStats: (cycleId: QueryId, responsibleId?: QueryId) => [
    'performance-reviews',
    cycleId,
    'reviews',
    'stats',
    responsibleId,
  ],
  cycleStatsPrefix: (cycleId: QueryId) => [
    'performance-reviews',
    cycleId,
    'reviews',
    'stats',
  ],
  users: (
    id: QueryId,
    role: ReviewRole,
    responsibleId: QueryId,
    formatFilter: QueryFilter,
  ) => [
    'performance-reviews',
    id,
    'review-users',
    role,
    responsibleId,
    formatFilter,
  ],
  usersPrefix: (id: QueryId) => ['performance-reviews', id, 'review-users'],
  usersToShare: (
    id: QueryId,
    responsibleId: QueryId,
    formatFilter: QueryFilter,
  ) => ['performance-reviews', id, 'target-users', responsibleId, formatFilter],
  userToShare: (id: QueryId, userId: QueryId) => [
    'performance-reviews',
    id,
    'review-user-to-share',
    userId,
  ],
  allRevieweds: (id: QueryId) => ['performance-reviews', id, 'revieweds'],
  revieweds: (id: QueryId, params?: Record<string, unknown>) =>
    params
      ? [...performanceKeys.allRevieweds(id), params]
      : [...performanceKeys.allRevieweds(id)],
  reviewers: (id: QueryId, reviewedId: QueryId) => [
    'performance-reviews',
    id,
    'target-users',
    reviewedId,
    'reviewers',
  ],
  externalUserReviewers: (formatFilter: QueryFilter) => [
    'performance-reviews',
    'external-user-reviewers',
    formatFilter,
  ],
  externalCycle: (id: QueryId, externalReviewerId: QueryId) => [
    ...performanceKeys.all(),
    'external-cycle',
    id,
    externalReviewerId,
  ],
  externalReview: (
    cycleId: QueryId,
    reviewId: QueryId,
    externalReviewerId: QueryId,
  ) => [
    ...performanceKeys.all(),
    'external-review',
    cycleId,
    reviewId,
    externalReviewerId,
  ],
  notifications: {
    all: () => [...performanceKeys.all(), 'notifications'],
    module: () => [...performanceKeys.notifications.all(), 'module'],
  },
  calibrations: (cycleId: QueryId, answered?: boolean) => [
    ...performanceKeys.all(),
    'calibrations',
    cycleId,
    answered,
  ],
  calibrationDetail: (cycleId: QueryId, formReviewId: QueryId) => [
    ...performanceKeys.all(),
    'calibration-detail',
    cycleId,
    formReviewId,
  ],
  calibrationsSidebar: (cycleId: QueryId) => [
    ...performanceKeys.all(),
    'calibrations-sidebar',
    cycleId,
  ],
};

export const checkReviewAsCompleted = (cycleId: string, reviewId: number) => {
  queryClient.setQueryData(
    performanceKeys.cycle(cycleId),
    (oldData?: CycleQueryData): CycleQueryData => {
      const reviews = oldData?.data?.reviewerFormReviews;
      if (!reviews || !oldData?.data) return oldData ?? {};

      oldData.data.reviewerFormReviews = reviews.map(review =>
        review.id === reviewId ? { ...review, answered: true } : review,
      );

      return oldData;
    },
  );
};

export const invalidateReview = (cycleId: string, reviewId: number) =>
  queryClient.invalidateQueries(performanceKeys.review(cycleId, reviewId));

export const invalidateUserToShare = (cycleId: string, userId: number) =>
  queryClient.invalidateQueries(performanceKeys.userToShare(cycleId, userId));

export const invalidateUsersToShare = (
  cycleId: string,
  userId: number,
  formatFilter: QueryFilter,
) =>
  queryClient.invalidateQueries(
    performanceKeys.usersToShare(cycleId, userId, formatFilter),
  );

export const invalidateCycle = (cycleId: string) =>
  queryClient.invalidateQueries(performanceKeys.cycle(cycleId));

const invalidateRevieweds = (cycleId: string) =>
  queryClient.invalidateQueries(performanceKeys.allRevieweds(cycleId));

export const invalidateExternalReview = (
  cycleId: string,
  reviewId: number,
  externalReviewerId: QueryId,
) =>
  queryClient.invalidateQueries(
    performanceKeys.externalReview(cycleId, reviewId, externalReviewerId),
  );

const invalidateCycleStats = (cycleId: string, responsibleId?: QueryId) =>
  queryClient.invalidateQueries(
    performanceKeys.cycleStats(cycleId, responsibleId),
  );

export const invalidateAllCycleStats = (cycleId: string) =>
  queryClient.invalidateQueries(performanceKeys.cycleStatsPrefix(cycleId));

export const invalidateLeaderUsers = (cycleId: string) =>
  queryClient.invalidateQueries(performanceKeys.usersPrefix(cycleId));
