import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { JobOpening } 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, apiGet, apiPost, apiPut } from '@/services/api/api';
import { JobOpeningsActions } from './actionTypes';

interface JobOpeningsState {
  jobOpenings: JobOpening[];
  jobOpening: JobOpening | null;
  meta: any;
  loading: boolean;
  actionLoading: boolean;
  error: string | null;
}

const initialState: JobOpeningsState = {
  jobOpenings: [],
  jobOpening: null,
  meta: null,
  loading: false,
  actionLoading: false,
  error: null,
};

export const fetchJobOpenings = createAsyncThunk(
  JobOpeningsActions.FETCH_JOB_OPENINGS,
  async (
    params?: {
      status?: string;
      department_id?: 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/job-openings${query}`)) as AxiosResponse<{
        data: JobOpening[];
        meta: any;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchJobOpening = createAsyncThunk(
  JobOpeningsActions.FETCH_JOB_OPENING,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiGet(`/recruitment/job-openings/${id}`)) as AxiosResponse<{
        data: JobOpening;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const createJobOpening = createAsyncThunk(
  JobOpeningsActions.CREATE_JOB_OPENING,
  async (payload: any, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/recruitment/job-openings', payload)) as AxiosResponse<{
        data: JobOpening;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateJobOpening = createAsyncThunk(
  JobOpeningsActions.UPDATE_JOB_OPENING,
  async ({ id, ...rest }: { id: string } & any, { rejectWithValue }) => {
    try {
      const response = (await apiPut(
        `/recruitment/job-openings/${id}`,
        rest,
      )) as AxiosResponse<{ data: JobOpening }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteJobOpening = createAsyncThunk(
  JobOpeningsActions.DELETE_JOB_OPENING,
  async (id: string, { rejectWithValue }) => {
    try {
      await apiDelete(`/recruitment/job-openings/${id}`);
      return id;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const JobOpeningsSlice = createSlice({
  name: 'jobOpenings',
  initialState,
  reducers: {
    clearJobOpening(state: Draft<JobOpeningsState>) {
      state.jobOpening = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchJobOpenings.pending, (state: Draft<JobOpeningsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchJobOpenings.fulfilled,
        (
          state: Draft<JobOpeningsState>,
          action: PayloadAction<{ data: JobOpening[]; meta: any }>,
        ) => {
          state.jobOpenings = action.payload.data;
          state.meta = action.payload.meta;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(
        fetchJobOpenings.rejected,
        (state: Draft<JobOpeningsState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchJobOpening.pending, (state: Draft<JobOpeningsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchJobOpening.fulfilled,
        (state: Draft<JobOpeningsState>, action: PayloadAction<{ data: JobOpening }>) => {
          state.jobOpening = action.payload.data;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchJobOpening.rejected, (state: Draft<JobOpeningsState>) => {
        state.loading = false;
      });

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

    builder
      .addCase(updateJobOpening.pending, (state: Draft<JobOpeningsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        updateJobOpening.fulfilled,
        (state: Draft<JobOpeningsState>, action: PayloadAction<{ data: JobOpening }>) => {
          const updated = action.payload.data;
          const index = state.jobOpenings.findIndex((j) => j.id === updated.id);
          if (index !== -1) {
            state.jobOpenings[index] = updated;
          }
          if (state.jobOpening?.id === updated.id) {
            state.jobOpening = updated;
          }
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        updateJobOpening.rejected,
        (state: Draft<JobOpeningsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

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

export const { clearJobOpening } = JobOpeningsSlice.actions;

export default JobOpeningsSlice;
export type { JobOpeningsState };
