import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  TrainingProgram,
  CreateTrainingProgramPayload,
  UpdateTrainingProgramPayload,
  DeleteTrainingProgramPayload,
} from '@/interface/Training';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import { TrainingProgramsActions } from './actionTypes';
import { apiDelete, apiGet, apiPost, apiPut } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface TrainingProgramState {
  programs: TrainingProgram[];
  eligibleEmployees: any[];
  loading: boolean;
  error: string | null;
}

const initialState: TrainingProgramState = {
  programs: [],
  eligibleEmployees: [],
  loading: false,
  error: null,
};

export const fetchTrainingPrograms = createAsyncThunk(
  TrainingProgramsActions.FETCH_TRAINING_PROGRAMS_REQUEST,
  async (params?: {
    category_id?: string;
    provider_id?: string;
    delivery_method?: string;
    is_recurring?: boolean;
    search?: string;
    per_page?: number;
  }) => {
    const queryParams = new URLSearchParams();
    if (params?.category_id) queryParams.append('category_id', params.category_id);
    if (params?.provider_id) queryParams.append('provider_id', params.provider_id);
    if (params?.delivery_method) queryParams.append('delivery_method', params.delivery_method);
    if (params?.is_recurring !== undefined)
      queryParams.append('is_recurring', String(params.is_recurring));
    if (params?.search) queryParams.append('search', params.search);
    if (params?.per_page) queryParams.append('per_page', String(params.per_page));
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response = (await apiGet(`/training/programs${query}`)) as AxiosResponse<
      TrainingProgram[]
    >;
    return response.data;
  },
);

export const createTrainingProgram = createAsyncThunk(
  TrainingProgramsActions.CREATE_TRAINING_PROGRAM_REQUEST,
  async (payload: CreateTrainingProgramPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        '/training/programs',
        payload,
      )) as AxiosResponse<{ data: TrainingProgram }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateTrainingProgram = createAsyncThunk(
  TrainingProgramsActions.UPDATE_TRAINING_PROGRAM_REQUEST,
  async (payload: UpdateTrainingProgramPayload, { rejectWithValue }) => {
    try {
      const { id, ...data } = payload;
      const response = (await apiPut(
        `/training/programs/${id}`,
        data,
      )) as AxiosResponse<{ data: TrainingProgram }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteTrainingProgram = createAsyncThunk(
  TrainingProgramsActions.DELETE_TRAINING_PROGRAM_REQUEST,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiDelete(
        `/training/programs/${id}`,
      )) as AxiosResponse<DeleteTrainingProgramPayload>;
      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 fetchEligibleEmployees = createAsyncThunk(
  TrainingProgramsActions.FETCH_ELIGIBLE_EMPLOYEES_REQUEST,
  async (id: string) => {
    const response = (await apiGet(
      `/training/programs/${id}/eligible-employees`,
    )) as AxiosResponse<any[]>;
    return response.data;
  },
);

export const TrainingProgramsSlice = createSlice({
  name: 'trainingPrograms',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchTrainingPrograms.pending, (state: Draft<TrainingProgramState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchTrainingPrograms.fulfilled,
        (state: Draft<TrainingProgramState>, action: PayloadAction<TrainingProgram[]>) => {
          state.programs = action.payload;
          state.error = null;
          state.loading = false;
        },
      )
      .addCase(fetchTrainingPrograms.rejected, (state: Draft<TrainingProgramState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load training programs';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(createTrainingProgram.pending, (state: Draft<TrainingProgramState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        createTrainingProgram.fulfilled,
        (state: Draft<TrainingProgramState>, action: PayloadAction<TrainingProgram>) => {
          state.programs.unshift(action.payload);
          state.error = null;
          state.loading = false;
          message.success('Training program created successfully');
        },
      )
      .addCase(
        createTrainingProgram.rejected,
        (state: Draft<TrainingProgramState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(updateTrainingProgram.pending, (state: Draft<TrainingProgramState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        updateTrainingProgram.fulfilled,
        (state: Draft<TrainingProgramState>, action: PayloadAction<TrainingProgram>) => {
          const index = state.programs.findIndex((p) => p.id === action.payload.id);
          if (index !== -1) {
            state.programs[index] = action.payload;
          }
          state.loading = false;
          state.error = null;
          message.success('Training program updated successfully');
        },
      )
      .addCase(
        updateTrainingProgram.rejected,
        (state: Draft<TrainingProgramState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deleteTrainingProgram.pending, (state: Draft<TrainingProgramState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        deleteTrainingProgram.fulfilled,
        (
          state: Draft<TrainingProgramState>,
          action: PayloadAction<DeleteTrainingProgramPayload>,
        ) => {
          state.programs = state.programs.filter((p) => p.id !== action.payload.id);
          state.loading = false;
          message.success(action.payload.message);
        },
      )
      .addCase(
        deleteTrainingProgram.rejected,
        (state: Draft<TrainingProgramState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchEligibleEmployees.pending, (state: Draft<TrainingProgramState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchEligibleEmployees.fulfilled,
        (state: Draft<TrainingProgramState>, action: PayloadAction<any[]>) => {
          state.eligibleEmployees = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchEligibleEmployees.rejected, (state: Draft<TrainingProgramState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load eligible employees';
        message.error(Helpers.handleServerError(action.payload), 8);
      });
  },
});

export default TrainingProgramsSlice;
export type { TrainingProgramState };
