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

interface ReferralsState {
  referrals: Referral[];
  pendingReferrals: Referral[];
  meta: any;
  loading: boolean;
  actionLoading: boolean;
  error: string | null;
}

const initialState: ReferralsState = {
  referrals: [],
  pendingReferrals: [],
  meta: null,
  loading: false,
  actionLoading: false,
  error: null,
};

export const fetchMyReferrals = createAsyncThunk(
  ReferralsActions.FETCH_MY_REFERRALS,
  async (_: void, { rejectWithValue }) => {
    try {
      const response = (await apiGet('/recruitment/referrals')) as AxiosResponse<{
        data: Referral[];
        meta: any;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchAllReferrals = createAsyncThunk(
  ReferralsActions.FETCH_ALL_REFERRALS,
  async (
    params?: {
      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/referrals/all${query}`)) as AxiosResponse<{
        data: Referral[];
        meta: any;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchPendingReferrals = createAsyncThunk(
  ReferralsActions.FETCH_PENDING_REFERRALS,
  async (_: void, { rejectWithValue }) => {
    try {
      const response = (await apiGet('/recruitment/referrals/pending')) as AxiosResponse<{
        data: Referral[];
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const createReferral = createAsyncThunk(
  ReferralsActions.CREATE_REFERRAL,
  async (payload: any, { rejectWithValue }) => {
    try {
      const response = (await apiPost('/recruitment/referrals', payload)) as AxiosResponse<{
        data: Referral;
      }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const convertReferral = createAsyncThunk(
  ReferralsActions.CONVERT_REFERRAL,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/recruitment/referrals/${id}/convert`,
        {},
      )) as AxiosResponse<{ data: Referral }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const ReferralsSlice = createSlice({
  name: 'referrals',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchMyReferrals.pending, (state: Draft<ReferralsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchMyReferrals.fulfilled,
        (
          state: Draft<ReferralsState>,
          action: PayloadAction<{ data: Referral[]; meta: any }>,
        ) => {
          state.referrals = action.payload.data;
          state.meta = action.payload.meta;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(
        fetchMyReferrals.rejected,
        (state: Draft<ReferralsState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchAllReferrals.pending, (state: Draft<ReferralsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchAllReferrals.fulfilled,
        (
          state: Draft<ReferralsState>,
          action: PayloadAction<{ data: Referral[]; meta: any }>,
        ) => {
          state.referrals = action.payload.data;
          state.meta = action.payload.meta;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(
        fetchAllReferrals.rejected,
        (state: Draft<ReferralsState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchPendingReferrals.pending, (state: Draft<ReferralsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchPendingReferrals.fulfilled,
        (state: Draft<ReferralsState>, action: PayloadAction<{ data: Referral[] }>) => {
          state.pendingReferrals = action.payload.data;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchPendingReferrals.rejected, (state: Draft<ReferralsState>) => {
        state.loading = false;
      });

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

    builder
      .addCase(convertReferral.pending, (state: Draft<ReferralsState>) => {
        state.actionLoading = true;
        state.error = null;
      })
      .addCase(
        convertReferral.fulfilled,
        (state: Draft<ReferralsState>, action: PayloadAction<{ data: Referral }>) => {
          const updated = action.payload.data;
          const index = state.referrals.findIndex((r) => r.id === updated.id);
          if (index !== -1) {
            state.referrals[index] = updated;
          }
          state.pendingReferrals = state.pendingReferrals.filter((r) => r.id !== updated.id);
          state.actionLoading = false;
          state.error = null;
        },
      )
      .addCase(
        convertReferral.rejected,
        (state: Draft<ReferralsState>, action: RejectedActionPayload) => {
          state.actionLoading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );
  },
});

export default ReferralsSlice;
export type { ReferralsState };
