import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { Interview } from '@/interface/Recruitment';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { apiDelete, apiDownloadBlob, apiGet, apiPost, apiPut } from '@/services/api/api';
import { InterviewsActions } from './actionTypes';

interface InterviewsState {
  interviews: Interview[];
  interview: Interview | null;
  upcomingInterviews: Interview[];
  pendingFeedbackInterviews: Interview[];
  history: any[];
  stats: any | null;
  meta: any;
  loading: boolean;
  actionLoading: boolean;
  error: string | null;
}

const initialState: InterviewsState = {
  interviews: [],
  interview: null,
  upcomingInterviews: [],
  pendingFeedbackInterviews: [],
  history: [],
  stats: null,
  meta: null,
  loading: false,
  actionLoading: false,
  error: null,
};

export const fetchInterviews = createAsyncThunk(
  InterviewsActions.FETCH_INTERVIEWS,
  async (
    params?: {
      job_opening_id?: string;
      applicant_id?: string;
      status?: string;
      search?: string;
      per_page?: number;
      page?: number;
    },
    { rejectWithValue },
  ) => {
    try {
      const queryParams = new URLSearchParams(
        Object.entries(params ?? {})
          .filter(([, v]) => v !== undefined && v !== null)
          .map(([k, v]) => [k, String(v)]),
      );
      const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
      const response = (await apiGet(`/recruitment/interviews${query}`)) as AxiosResponse<{
        data: Interview[];
        meta: any;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchInterview = createAsyncThunk(
  InterviewsActions.FETCH_INTERVIEW,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiGet(`/recruitment/interviews/${id}`)) as AxiosResponse<{
        data: Interview;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchUpcomingInterviews = createAsyncThunk(
  InterviewsActions.FETCH_UPCOMING,
  async (_: void, { rejectWithValue }) => {
    try {
      const response = (await apiGet('/recruitment/interviews/upcoming')) as AxiosResponse<{
        data: Interview[];
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchPendingFeedbackInterviews = createAsyncThunk(
  InterviewsActions.FETCH_PENDING_FEEDBACK,
  async (_: void, { rejectWithValue }) => {
    try {
      const response = (await apiGet('/recruitment/interviews/pending-feedback')) as AxiosResponse<{
        data: Interview[];
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchInterviewHistory = createAsyncThunk(
  InterviewsActions.FETCH_HISTORY,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiGet(`/recruitment/interviews/${id}/history`)) as AxiosResponse<{
        data: any[];
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchInterviewStats = createAsyncThunk(
  InterviewsActions.FETCH_STATS,
  async (jobOpeningId: string, { rejectWithValue }) => {
    try {
      const response = (await apiGet(
        `/recruitment/interviews/stats/${jobOpeningId}`,
      )) as AxiosResponse<{ data: any }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const createInterview = createAsyncThunk(
  InterviewsActions.CREATE_INTERVIEW,
  async (payload: any, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/recruitment/interviews', payload)) as AxiosResponse<{
        data: Interview;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateInterview = createAsyncThunk(
  InterviewsActions.UPDATE_INTERVIEW,
  async ({ id, ...rest }: { id: string } & any, { rejectWithValue }) => {
    try {
      const response = (await apiPut(
        `/recruitment/interviews/${id}`,
        rest,
      )) as AxiosResponse<{ data: Interview }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteInterview = createAsyncThunk(
  InterviewsActions.DELETE_INTERVIEW,
  async (id: string, { rejectWithValue }) => {
    try {
      await apiDelete(`/recruitment/interviews/${id}`);
      return id;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const scheduleInterview = createAsyncThunk(
  InterviewsActions.SCHEDULE_INTERVIEW,
  async ({ id, ...rest }: { id: string } & any, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/recruitment/interviews/${id}/schedule`,
        rest,
      )) as AxiosResponse<{ data: Interview }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const rescheduleInterview = createAsyncThunk(
  InterviewsActions.RESCHEDULE_INTERVIEW,
  async ({ id, ...rest }: { id: string } & any, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/recruitment/interviews/${id}/reschedule`,
        rest,
      )) as AxiosResponse<{ data: Interview }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const cancelInterview = createAsyncThunk(
  InterviewsActions.CANCEL_INTERVIEW,
  async (
    { id, cancellation_reason }: { id: string; cancellation_reason: string },
    { rejectWithValue },
  ) => {
    try {
      const response = (await apiPost(`/recruitment/interviews/${id}/cancel`, {
        cancellation_reason,
      })) as AxiosResponse<{ data: Interview }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const submitInterviewFeedback = createAsyncThunk(
  InterviewsActions.SUBMIT_FEEDBACK,
  async ({ id, ...rest }: { id: string } & any, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/recruitment/interviews/${id}/feedback`,
        rest,
      )) as AxiosResponse<{ data: Interview }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const generateInterviewToken = createAsyncThunk(
  InterviewsActions.GENERATE_TOKEN,
  async ({ interviewId, ...rest }: { interviewId: string } & any, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/recruitment/interviews/${interviewId}/generate-token`,
        rest,
      )) as AxiosResponse<{ data: any }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const downloadInterviewCalendar = createAsyncThunk(
  InterviewsActions.DOWNLOAD_CALENDAR,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = await apiDownloadBlob(`/recruitment/interviews/${id}/download-calendar`);
      return response.data as Blob;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const InterviewsSlice = createSlice({
  name: 'interviews',
  initialState,
  reducers: {
    clearInterview(state: Draft<InterviewsState>) {
      state.interview = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchInterviews.pending, (state: Draft<InterviewsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchInterviews.fulfilled,
        (
          state: Draft<InterviewsState>,
          action: PayloadAction<{ data: Interview[]; meta: any }>,
        ) => {
          state.interviews = action.payload.data;
          state.meta = action.payload.meta;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(
        fetchInterviews.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchInterview.pending, (state: Draft<InterviewsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          state.interview = action.payload.data;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchInterview.rejected, (state: Draft<InterviewsState>) => {
        state.loading = false;
      });

    builder
      .addCase(fetchUpcomingInterviews.pending, (state: Draft<InterviewsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchUpcomingInterviews.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview[] }>) => {
          state.upcomingInterviews = action.payload.data;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchUpcomingInterviews.rejected, (state: Draft<InterviewsState>) => {
        state.loading = false;
      });

    builder
      .addCase(fetchPendingFeedbackInterviews.pending, (state: Draft<InterviewsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchPendingFeedbackInterviews.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview[] }>) => {
          state.pendingFeedbackInterviews = action.payload.data;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchPendingFeedbackInterviews.rejected, (state: Draft<InterviewsState>) => {
        state.loading = false;
      });

    builder
      .addCase(fetchInterviewHistory.pending, (state: Draft<InterviewsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchInterviewHistory.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: any[] }>) => {
          state.history = action.payload.data ?? [];
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchInterviewHistory.rejected, (state: Draft<InterviewsState>) => {
        state.loading = false;
      });

    builder
      .addCase(fetchInterviewStats.pending, (state: Draft<InterviewsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchInterviewStats.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: any }>) => {
          state.stats = action.payload.data;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchInterviewStats.rejected, (state: Draft<InterviewsState>) => {
        state.loading = false;
      });

    builder
      .addCase(createInterview.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        createInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          state.interviews.unshift(action.payload.data);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        createInterview.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(updateInterview.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        updateInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          const updated = action.payload.data;
          const index = state.interviews.findIndex((i) => i.id === updated.id);
          if (index !== -1) {
            state.interviews[index] = updated;
          }
          if (state.interview?.id === updated.id) {
            state.interview = updated;
          }
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        updateInterview.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deleteInterview.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        deleteInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<string>) => {
          state.interviews = state.interviews.filter((i) => i.id !== action.payload);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        deleteInterview.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    const updateInterviewInState = (
      state: Draft<InterviewsState>,
      updated: Interview,
    ) => {
      const index = state.interviews.findIndex((i) => i.id === updated.id);
      if (index !== -1) {
        state.interviews[index] = updated;
      }
      if (state.interview?.id === updated.id) {
        state.interview = updated;
      }
    };

    builder
      .addCase(scheduleInterview.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        scheduleInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          updateInterviewInState(state, action.payload.data);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        scheduleInterview.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(rescheduleInterview.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        rescheduleInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          updateInterviewInState(state, action.payload.data);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        rescheduleInterview.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(cancelInterview.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        cancelInterview.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          updateInterviewInState(state, action.payload.data);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        cancelInterview.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(submitInterviewFeedback.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        submitInterviewFeedback.fulfilled,
        (state: Draft<InterviewsState>, action: PayloadAction<{ data: Interview }>) => {
          updateInterviewInState(state, action.payload.data);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        submitInterviewFeedback.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(generateInterviewToken.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(generateInterviewToken.fulfilled, (state: Draft<InterviewsState>) => {
        state.actionLoading = false;
        state.error = null;
      })
      .addCase(
        generateInterviewToken.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(downloadInterviewCalendar.pending, (state: Draft<InterviewsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(downloadInterviewCalendar.fulfilled, (state: Draft<InterviewsState>) => {
        state.actionLoading = false;
        state.error = null;
      })
      .addCase(
        downloadInterviewCalendar.rejected,
        (state: Draft<InterviewsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );
  },
});

export const { clearInterview } = InterviewsSlice.actions;

export default InterviewsSlice;
export type { InterviewsState };
