import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  PeerReviewAssignment,
  PeerReviewAssignmentResponse,
  PaginatedPeerReviewAssignments,
  CreatePeerReviewAssignmentPayload,
  AutoAssignPeerReviewPayload,
  BulkAssignPeerReviewPayload,
  AggregateScoresResponse,
  AnonymizedFeedbackResponse,
} from '@/interface/PeerReviewAssignment';
import { apiDelete, apiGet, apiPost, apiPut } from '@/services/api/api';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { PeerReviewAssignmentActions } from './actionTypes';
import { PaginationLinks, PaginationMeta } from '@/interface/Paginated';
import { GetParams, toQueryString } from '@/interface/GetParams';

interface PeerReviewAssignmentState {
  assignments: PeerReviewAssignment[];
  currentAssignment: PeerReviewAssignment | null;
  aggregateScores: Record<string, unknown> | null;
  anonymizedFeedback: Record<string, unknown>[];
  links?: PaginationLinks;
  meta?: PaginationMeta;
  loading: boolean;
  error: string | null;
}

const initialState: PeerReviewAssignmentState = {
  assignments: [],
  currentAssignment: null,
  aggregateScores: null,
  anonymizedFeedback: [],
  loading: false,
  error: null,
};

export const fetchPeerReviewAssignments = createAsyncThunk(
  PeerReviewAssignmentActions.FETCH_ASSIGNMENTS_REQUEST,
  async (params?: GetParams) => {
    const query = toQueryString(params);
    const response = (await apiGet(`/peer-review-assignments${query}`)) as AxiosResponse<PaginatedPeerReviewAssignments>;
    return response.data;
  },
);

export const fetchPeerReviewAssignment = createAsyncThunk(
  PeerReviewAssignmentActions.FETCH_ASSIGNMENT_REQUEST,
  async (id: string) => {
    const response = (await apiGet(`/peer-review-assignments/${id}`)) as AxiosResponse<PeerReviewAssignmentResponse>;
    return response.data.data;
  },
);

export const createPeerReviewAssignment = createAsyncThunk(
  PeerReviewAssignmentActions.CREATE_ASSIGNMENT_REQUEST,
  async (payload: CreatePeerReviewAssignmentPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/peer-review-assignments', payload)) as AxiosResponse<PeerReviewAssignmentResponse>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updatePeerReviewAssignment = createAsyncThunk(
  PeerReviewAssignmentActions.UPDATE_ASSIGNMENT_REQUEST,
  async (payload: Partial<CreatePeerReviewAssignmentPayload> & { id: string }, { rejectWithValue }) => {
    try {
      const response = (await apiPut(`/peer-review-assignments/${payload.id}`, payload)) as AxiosResponse<PeerReviewAssignmentResponse>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deletePeerReviewAssignment = createAsyncThunk(
  PeerReviewAssignmentActions.DELETE_ASSIGNMENT_REQUEST,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiDelete(`/peer-review-assignments/${id}`)) as AxiosResponse<{ message: string }>;
      return { message: response.data.message, id };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const autoAssignPeerReviews = createAsyncThunk(
  PeerReviewAssignmentActions.AUTO_ASSIGN_REQUEST,
  async (payload: AutoAssignPeerReviewPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/peer-review-assignments/auto-assign', payload)) as AxiosResponse<PaginatedPeerReviewAssignments>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const bulkAssignPeerReviews = createAsyncThunk(
  PeerReviewAssignmentActions.BULK_ASSIGN_REQUEST,
  async (payload: BulkAssignPeerReviewPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/peer-review-assignments/bulk-assign', payload)) as AxiosResponse<PaginatedPeerReviewAssignments>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchAggregateScores = createAsyncThunk(
  PeerReviewAssignmentActions.FETCH_AGGREGATE_SCORES_REQUEST,
  async ({ revieweeId, appraisalCycleId }: { revieweeId: string; appraisalCycleId?: string }) => {
    const query = appraisalCycleId ? `?appraisal_cycle_id=${appraisalCycleId}` : '';
    const response = (await apiGet(`/peer-review-assignments/aggregate-scores/${revieweeId}${query}`)) as AxiosResponse<AggregateScoresResponse>;
    return response.data.data;
  },
);

export const fetchAnonymizedFeedback = createAsyncThunk(
  PeerReviewAssignmentActions.FETCH_ANONYMIZED_FEEDBACK_REQUEST,
  async ({ revieweeId, appraisalCycleId }: { revieweeId: string; appraisalCycleId?: string }) => {
    const query = appraisalCycleId ? `?appraisal_cycle_id=${appraisalCycleId}` : '';
    const response = (await apiGet(`/peer-review-assignments/anonymized-feedback/${revieweeId}${query}`)) as AxiosResponse<AnonymizedFeedbackResponse>;
    return response.data.data;
  },
);

export const PeerReviewAssignmentSlice = createSlice({
  name: 'peerReviewAssignments',
  initialState,
  reducers: {
    clearCurrentAssignment: (state: Draft<PeerReviewAssignmentState>) => {
      state.currentAssignment = null;
    },
    clearAggregateScores: (state: Draft<PeerReviewAssignmentState>) => {
      state.aggregateScores = null;
      state.anonymizedFeedback = [];
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchPeerReviewAssignments.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchPeerReviewAssignments.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<PaginatedPeerReviewAssignments>) => {
          state.assignments = action.payload.data;
          state.meta = action.payload.meta;
          state.links = action.payload.links;
          state.loading = false;
        },
      )
      .addCase(fetchPeerReviewAssignments.rejected, (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(fetchPeerReviewAssignment.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        fetchPeerReviewAssignment.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<PeerReviewAssignment>) => {
          state.currentAssignment = action.payload;
          state.loading = false;
        },
      )
      .addCase(fetchPeerReviewAssignment.rejected, (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(createPeerReviewAssignment.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        createPeerReviewAssignment.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<PeerReviewAssignment>) => {
          state.assignments.unshift(action.payload);
          state.loading = false;
        },
      )
      .addCase(
        createPeerReviewAssignment.rejected,
        (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(updatePeerReviewAssignment.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        updatePeerReviewAssignment.fulfilled,
        (state: Draft<PeerReviewAssignmentState>) => {
          state.loading = false;
          message.success('Assignment updated successfully', 10);
        },
      )
      .addCase(
        updatePeerReviewAssignment.rejected,
        (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deletePeerReviewAssignment.pending, (state: Draft<PeerReviewAssignmentState>) => {})
      .addCase(
        deletePeerReviewAssignment.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<{ message: string; id: string }>) => {
          state.assignments = state.assignments.filter((item) => item.id !== action.payload.id);
          message.success(action.payload.message, 10);
        },
      )
      .addCase(deletePeerReviewAssignment.rejected, (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(autoAssignPeerReviews.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        autoAssignPeerReviews.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<PeerReviewAssignment[]>) => {
          state.assignments = [...action.payload, ...state.assignments];
          state.loading = false;
          message.success(`Auto-assigned ${action.payload.length} peer reviewers`, 10);
        },
      )
      .addCase(
        autoAssignPeerReviews.rejected,
        (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(bulkAssignPeerReviews.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        bulkAssignPeerReviews.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<PeerReviewAssignment[]>) => {
          state.assignments = [...action.payload, ...state.assignments];
          state.loading = false;
          message.success(`Bulk-assigned ${action.payload.length} peer reviewers`, 10);
        },
      )
      .addCase(
        bulkAssignPeerReviews.rejected,
        (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchAggregateScores.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        fetchAggregateScores.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<Record<string, unknown>>) => {
          state.aggregateScores = action.payload;
          state.loading = false;
        },
      )
      .addCase(fetchAggregateScores.rejected, (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(fetchAnonymizedFeedback.pending, (state: Draft<PeerReviewAssignmentState>) => {
        state.loading = true;
      })
      .addCase(
        fetchAnonymizedFeedback.fulfilled,
        (state: Draft<PeerReviewAssignmentState>, action: PayloadAction<Record<string, unknown>[]>) => {
          state.anonymizedFeedback = action.payload;
          state.loading = false;
        },
      )
      .addCase(fetchAnonymizedFeedback.rejected, (state: Draft<PeerReviewAssignmentState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });
  },
});

export const { clearCurrentAssignment, clearAggregateScores } = PeerReviewAssignmentSlice.actions;
export default PeerReviewAssignmentSlice;
export type { PeerReviewAssignmentState };
