import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  TrainingEnrollment,
  CreateTrainingEnrollmentPayload,
  DeleteTrainingEnrollmentPayload,
  BulkEnrollPayload,
  ApproveEnrollmentPayload,
  WithdrawEnrollmentPayload,
  CompleteEnrollmentPayload,
} from '@/interface/Training';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import { TrainingEnrollmentsActions } from './actionTypes';
import { apiDelete, apiGet, apiPost } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface TrainingEnrollmentState {
  enrollments: TrainingEnrollment[];
  myTraining: TrainingEnrollment[];
  meta: {
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
  } | null;
  loading: boolean;
  error: string | null;
}

const initialState: TrainingEnrollmentState = {
  enrollments: [],
  myTraining: [],
  meta: null,
  loading: false,
  error: null,
};

export const fetchTrainingEnrollments = createAsyncThunk(
  TrainingEnrollmentsActions.FETCH_TRAINING_ENROLLMENTS_REQUEST,
  async (params?: {
    session_id?: string;
    employee_id?: string;
    status?: string;
    pending_approval?: boolean;
    per_page?: number;
  }) => {
    const queryParams = new URLSearchParams();
    if (params?.session_id) queryParams.append('session_id', params.session_id);
    if (params?.employee_id) queryParams.append('employee_id', params.employee_id);
    if (params?.status) queryParams.append('status', params.status);
    if (params?.pending_approval !== undefined)
      queryParams.append('pending_approval', String(params.pending_approval));
    if (params?.per_page) queryParams.append('per_page', String(params.per_page));
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response = (await apiGet(`/training/enrollments${query}`)) as AxiosResponse<
      TrainingEnrollment[]
    >;
    return response.data;
  },
);

export const createTrainingEnrollment = createAsyncThunk(
  TrainingEnrollmentsActions.CREATE_TRAINING_ENROLLMENT_REQUEST,
  async (payload: CreateTrainingEnrollmentPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        '/training/enrollments',
        payload,
      )) as AxiosResponse<{ data: TrainingEnrollment }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteTrainingEnrollment = createAsyncThunk(
  TrainingEnrollmentsActions.DELETE_TRAINING_ENROLLMENT_REQUEST,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiDelete(
        `/training/enrollments/${id}`,
      )) as AxiosResponse<DeleteTrainingEnrollmentPayload>;
      const responseData = response.data;
      responseData.id = id;
      return responseData;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const bulkEnroll = createAsyncThunk(
  TrainingEnrollmentsActions.BULK_ENROLL_REQUEST,
  async (payload: BulkEnrollPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        '/training/enrollments/bulk',
        payload,
      )) as AxiosResponse<{ data: TrainingEnrollment[] }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const approveEnrollment = createAsyncThunk(
  TrainingEnrollmentsActions.APPROVE_ENROLLMENT_REQUEST,
  async (payload: ApproveEnrollmentPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/training/enrollments/${payload.id}/approve`,
        {},
      )) as AxiosResponse<{ data: TrainingEnrollment }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const withdrawEnrollment = createAsyncThunk(
  TrainingEnrollmentsActions.WITHDRAW_ENROLLMENT_REQUEST,
  async (payload: WithdrawEnrollmentPayload, { rejectWithValue }) => {
    try {
      const { id, ...data } = payload;
      const response = (await apiPost(
        `/training/enrollments/${id}/withdraw`,
        data,
      )) as AxiosResponse<{ data: TrainingEnrollment }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const completeEnrollment = createAsyncThunk(
  TrainingEnrollmentsActions.COMPLETE_ENROLLMENT_REQUEST,
  async (payload: CompleteEnrollmentPayload, { rejectWithValue }) => {
    try {
      const { id, ...data } = payload;
      const response = (await apiPost(
        `/training/enrollments/${id}/complete`,
        data,
      )) as AxiosResponse<{ data: TrainingEnrollment }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchMyTraining = createAsyncThunk(
  TrainingEnrollmentsActions.FETCH_MY_TRAINING_REQUEST,
  async () => {
    const response = (await apiGet(
      '/training/enrollments/my-training',
    )) as AxiosResponse<TrainingEnrollment[]>;
    return response.data;
  },
);

const updateEnrollmentInArray = (
  state: Draft<TrainingEnrollmentState>,
  enrollment: TrainingEnrollment,
) => {
  const index = state.enrollments.findIndex((e) => e.id === enrollment.id);
  if (index !== -1) state.enrollments[index] = enrollment;
};

export const TrainingEnrollmentsSlice = createSlice({
  name: 'trainingEnrollments',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchTrainingEnrollments.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchTrainingEnrollments.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment[]>,
        ) => {
          state.enrollments = action.payload;
          state.error = null;
          state.loading = false;
        },
      )
      .addCase(fetchTrainingEnrollments.rejected, (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load training enrollments';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(createTrainingEnrollment.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        createTrainingEnrollment.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment>,
        ) => {
          state.enrollments.unshift(action.payload);
          state.error = null;
          state.loading = false;
          message.success('Enrollment created successfully');
        },
      )
      .addCase(
        createTrainingEnrollment.rejected,
        (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deleteTrainingEnrollment.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        deleteTrainingEnrollment.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<DeleteTrainingEnrollmentPayload>,
        ) => {
          state.enrollments = state.enrollments.filter((e) => e.id !== action.payload.id);
          state.loading = false;
          message.success(action.payload.message);
        },
      )
      .addCase(
        deleteTrainingEnrollment.rejected,
        (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(bulkEnroll.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        bulkEnroll.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment[]>,
        ) => {
          state.enrollments.unshift(...action.payload);
          state.error = null;
          state.loading = false;
          message.success(`${action.payload.length} employees enrolled successfully`);
        },
      )
      .addCase(
        bulkEnroll.rejected,
        (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(approveEnrollment.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        approveEnrollment.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment>,
        ) => {
          updateEnrollmentInArray(state, action.payload);
          state.loading = false;
          state.error = null;
          message.success('Enrollment approved successfully');
        },
      )
      .addCase(
        approveEnrollment.rejected,
        (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(withdrawEnrollment.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        withdrawEnrollment.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment>,
        ) => {
          updateEnrollmentInArray(state, action.payload);
          state.loading = false;
          state.error = null;
          message.success('Enrollment withdrawn successfully');
        },
      )
      .addCase(
        withdrawEnrollment.rejected,
        (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(completeEnrollment.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        completeEnrollment.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment>,
        ) => {
          updateEnrollmentInArray(state, action.payload);
          state.loading = false;
          state.error = null;
          message.success('Enrollment completed successfully');
        },
      )
      .addCase(
        completeEnrollment.rejected,
        (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchMyTraining.pending, (state: Draft<TrainingEnrollmentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchMyTraining.fulfilled,
        (
          state: Draft<TrainingEnrollmentState>,
          action: PayloadAction<TrainingEnrollment[]>,
        ) => {
          state.myTraining = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchMyTraining.rejected, (state: Draft<TrainingEnrollmentState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load your training';
        message.error(Helpers.handleServerError(action.payload), 8);
      });
  },
});

export default TrainingEnrollmentsSlice;
export type { TrainingEnrollmentState };
