import { Asset, DeleteAssetPayload, DeleteAssetResponse, UpdateAssetPayload } from '@/interface/Asset';
import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { apiDelete, apiGet, apiPost, apiPut } from '@/services/api/api';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { AssetActions } from './actionTypes';

interface AssetState {
  assets: Asset[];
  loading: boolean;
  deleting: boolean;
  error: string | null;
}

const initialState: AssetState = {
  assets: [],
  loading: false,
  deleting: false,
  error: null,
};

export const fetchAssets = createAsyncThunk(AssetActions.FETCH_ASSETS_REQUEST, async (payload: string) => {
  const response = (await apiGet(`/hr/employees/${payload}/assets`)) as AxiosResponse<Asset[]>;
  return response.data;
});

export const createAsset = createAsyncThunk(
  AssetActions.CREATE_ASSET_REQUEST,
  async (
    payload: { employee_id: string } & Record<string, any>,
    { rejectWithValue },
  ) => {
    try {
      const response = (await apiPost(`/hr/employees/${payload.employee_id}/assets`, payload)) as AxiosResponse<Asset>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateAsset = createAsyncThunk(
  AssetActions.UPDATE_ASSET_REQUEST,
  async (payload: UpdateAssetPayload, { rejectWithValue }) => {
    try {
      const response = (await apiPut(`/hr/employees/${payload.employee_id}/assets/${payload.id}`, payload)) as AxiosResponse<Asset>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteAsset = createAsyncThunk(
  AssetActions.DELETE_ASSET_REQUEST,
  async (payload: DeleteAssetPayload) => {
    const response = (await apiDelete(`/hr/employees/${payload.employee_id}/assets/${payload.asset_id}`)) as AxiosResponse<DeleteAssetResponse>;

    const responseData = response.data;
    responseData.id = payload.asset_id;
    return responseData;
  },
);

export const AssetSlice = createSlice({
  name: 'assets',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(fetchAssets.pending, (state: Draft<AssetState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchAssets.fulfilled, (state: Draft<AssetState>, action: PayloadAction<Asset[]>) => {
        state.loading = false;
        state.error = null;
        state.assets = action.payload;
      })
      .addCase(fetchAssets.rejected, (state: Draft<AssetState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(createAsset.pending, (state: Draft<AssetState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(createAsset.fulfilled, (state: Draft<AssetState>, action: PayloadAction<Asset>) => {
        state.loading = false;
        state.error = null;
        state.assets.unshift(action.payload);
      })
      .addCase(createAsset.rejected, (state: Draft<AssetState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 10);
      });

    builder
      .addCase(updateAsset.pending, (state: Draft<AssetState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(updateAsset.fulfilled, (state: Draft<AssetState>, action: PayloadAction<Asset>) => {
        state.loading = false;
        state.error = null;

        const index = state.assets.findIndex((item) => item.id === action.payload.id);
        if (index > -1) {
          state.assets[index] = action.payload;
        }

        message.success('Successfully updated Asset', 8);
      })
      .addCase(updateAsset.rejected, (state: Draft<AssetState>, action: RejectedActionPayload) => {
        state.loading = false;
        message.error(Helpers.handleServerError(action.payload), 10);
      });

    builder
      .addCase(deleteAsset.pending, (state: Draft<AssetState>) => {
        state.deleting = true;
        state.error = null;
      })
      .addCase(deleteAsset.fulfilled, (state: Draft<AssetState>, action: PayloadAction<DeleteAssetResponse>) => {
        state.deleting = false;
        state.error = null;
        state.assets = state.assets.filter((item) => item.id !== action.payload.id);
        message.success(action.payload.message, 10);
      })
      .addCase(deleteAsset.rejected, (state: Draft<AssetState>, action: RejectedActionPayload) => {
        state.deleting = false;
        message.error(Helpers.handleServerError(action.payload), 8);
      });
  },
});

export default AssetSlice;
export type { AssetState };
