import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  RecruitmentAssessment,
  RecruitmentCandidate,
  CreateRecruitmentAssessmentPayload,
  UpdateRecruitmentAssessmentPayload,
  PaginationMeta,
} from '@/interface/Assessment';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import { RecruitmentAssessmentsActions } from './actionTypes';
import { apiGet, apiPost, apiPut, apiDelete } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface RecruitmentAssessmentsState {
  assessments: RecruitmentAssessment[];
  assessment: RecruitmentAssessment | null;
  candidates: RecruitmentCandidate[];
  meta: PaginationMeta | null;
  candidatesMeta: PaginationMeta | null;
  loading: boolean;
  error: string | null;
}

const initialState: RecruitmentAssessmentsState = {
  assessments: [],
  assessment: null,
  candidates: [],
  meta: null,
  candidatesMeta: null,
  loading: false,
  error: null,
};

export const fetchRecruitmentAssessments = createAsyncThunk<
  { data: RecruitmentAssessment[]; meta: PaginationMeta },
  { page?: number; search?: string; is_active?: boolean } | undefined,
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.FETCH_ALL_REQUEST, async (params, thunkAPI) => {
  try {
    const queryParams = new URLSearchParams();
    if (params?.page) queryParams.append('page', params.page.toString());
    if (params?.search) queryParams.append('search', params.search);
    if (params?.is_active !== undefined) queryParams.append('is_active', params.is_active ? '1' : '0');
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response: AxiosResponse = await apiGet(`/assessment/recruitment-assessments${query}`);
    return { data: response.data.data, meta: response.data.meta };
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

export const fetchRecruitmentAssessment = createAsyncThunk<
  RecruitmentAssessment,
  string,
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.FETCH_ONE_REQUEST, async (id, thunkAPI) => {
  try {
    const response: AxiosResponse = await apiGet(`/assessment/recruitment-assessments/${id}`);
    return response.data.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

export const createRecruitmentAssessment = createAsyncThunk<
  RecruitmentAssessment,
  CreateRecruitmentAssessmentPayload,
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.CREATE_REQUEST, async (payload, thunkAPI) => {
  try {
    const response: AxiosResponse = await apiPost('/assessment/recruitment-assessments', payload);
    return response.data.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

export const updateRecruitmentAssessment = createAsyncThunk<
  RecruitmentAssessment,
  UpdateRecruitmentAssessmentPayload,
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.UPDATE_REQUEST, async (payload, thunkAPI) => {
  try {
    const { id, ...data } = payload;
    const response: AxiosResponse = await apiPut(`/assessment/recruitment-assessments/${id}`, data);
    return response.data.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

export const deleteRecruitmentAssessment = createAsyncThunk<
  string,
  string,
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.DELETE_REQUEST, async (id, thunkAPI) => {
  try {
    await apiDelete(`/assessment/recruitment-assessments/${id}`);
    return id;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

export const regenerateToken = createAsyncThunk<
  RecruitmentAssessment,
  string,
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.REGENERATE_TOKEN_REQUEST, async (id, thunkAPI) => {
  try {
    const response: AxiosResponse = await apiPost(
      `/assessment/recruitment-assessments/${id}/regenerate-token`,
    );
    return response.data.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

export const fetchCandidates = createAsyncThunk<
  { data: RecruitmentCandidate[]; meta: PaginationMeta },
  { id: string; page?: number; search?: string; status?: string },
  { rejectValue: RejectedActionPayload }
>(RecruitmentAssessmentsActions.FETCH_CANDIDATES_REQUEST, async (params, thunkAPI) => {
  try {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.search) queryParams.append('search', params.search);
    if (params.status) queryParams.append('status', params.status);
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response: AxiosResponse = await apiGet(
      `/assessment/recruitment-assessments/${params.id}/candidates${query}`,
    );
    return { data: response.data.data, meta: response.data.meta };
  } catch (error) {
    if (axios.isAxiosError(error)) {
      return thunkAPI.rejectWithValue(error.response?.data as ServerErrorResponse);
    }
    throw error;
  }
});

const RecruitmentAssessmentsSlice = createSlice({
  name: 'recruitmentAssessments',
  initialState,
  reducers: {
    clearAssessment: (state) => {
      state.assessment = null;
    },
    clearCandidates: (state) => {
      state.candidates = [];
      state.candidatesMeta = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchRecruitmentAssessments.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchRecruitmentAssessments.fulfilled, (state, action) => {
        state.loading = false;
        state.assessments = action.payload.data;
        state.meta = action.payload.meta;
      })
      .addCase(fetchRecruitmentAssessments.rejected, (state, action) => {
        state.loading = false;
        Helpers.handleServerError(action.payload);
      })

      .addCase(fetchRecruitmentAssessment.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchRecruitmentAssessment.fulfilled, (state, action) => {
        state.loading = false;
        state.assessment = action.payload;
      })
      .addCase(fetchRecruitmentAssessment.rejected, (state, action) => {
        state.loading = false;
        Helpers.handleServerError(action.payload);
      })

      .addCase(createRecruitmentAssessment.pending, (state) => {
        state.loading = true;
      })
      .addCase(
        createRecruitmentAssessment.fulfilled,
        (state, action: PayloadAction<RecruitmentAssessment>) => {
          state.loading = false;
          state.assessments = [action.payload, ...state.assessments];
          message.success('Recruitment assessment created.');
        },
      )
      .addCase(createRecruitmentAssessment.rejected, (state, action) => {
        state.loading = false;
        Helpers.handleServerError(action.payload);
      })

      .addCase(updateRecruitmentAssessment.fulfilled, (state, action) => {
        const idx = state.assessments.findIndex((a) => a.id === action.payload.id);
        if (idx !== -1) state.assessments[idx] = action.payload;
        if (state.assessment?.id === action.payload.id) state.assessment = action.payload;
        message.success('Recruitment assessment updated.');
      })
      .addCase(updateRecruitmentAssessment.rejected, (_, action) => {
        Helpers.handleServerError(action.payload);
      })

      .addCase(deleteRecruitmentAssessment.fulfilled, (state, action) => {
        state.assessments = state.assessments.filter((a) => a.id !== action.payload);
        message.success('Recruitment assessment deleted.');
      })
      .addCase(deleteRecruitmentAssessment.rejected, (_, action) => {
        Helpers.handleServerError(action.payload);
      })

      .addCase(regenerateToken.fulfilled, (state, action) => {
        const idx = state.assessments.findIndex((a) => a.id === action.payload.id);
        if (idx !== -1) state.assessments[idx] = action.payload;
        if (state.assessment?.id === action.payload.id) state.assessment = action.payload;
        message.success('Share link regenerated.');
      })
      .addCase(regenerateToken.rejected, (_, action) => {
        Helpers.handleServerError(action.payload);
      })

      .addCase(fetchCandidates.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchCandidates.fulfilled, (state, action) => {
        state.loading = false;
        state.candidates = action.payload.data;
        state.candidatesMeta = action.payload.meta;
      })
      .addCase(fetchCandidates.rejected, (state, action) => {
        state.loading = false;
        Helpers.handleServerError(action.payload);
      });
  },
});

export const { clearAssessment, clearCandidates } = RecruitmentAssessmentsSlice.actions;
export default RecruitmentAssessmentsSlice;
