import {
  DeleteEmployeeDocumentPayload,
  DeleteEmployeeDocumentResponse,
  EmployeeDocument,
} from '@/interface/EmployeeDocument';
import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { apiDelete, apiGet, apiPost } 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 { DocumentActions } from './actionTypes';

interface DocumentState {
  documents: EmployeeDocument[];
  loading: boolean;
  deleting: boolean;
  error: string | null;
}

const initialState: DocumentState = {
  documents: [],
  loading: false,
  deleting: false,
  error: null,
};

export const fetchDocuments = createAsyncThunk(
  DocumentActions.FETCH_DOCUMENTS_REQUEST,
  async (payload: string) => {
    const response = (await apiGet(`/hr/employees/${payload}/documents`)) as AxiosResponse<
      EmployeeDocument[]
    >;
    return response.data;
  },
);

export const createDocument = createAsyncThunk(
  DocumentActions.CREATE_DOCUMENT_REQUEST,
  async (payload: FormData, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/hr/employees/${payload.get('employee_id')}/documents`,
        payload,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        },
      )) as AxiosResponse<EmployeeDocument>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateDocument = createAsyncThunk(
  DocumentActions.UPDATE_DOCUMENT_REQUEST,
  async (payload: FormData, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/hr/employees/${payload.get('employee_id')}/documents/${payload.get('document_id')}?_method=PUT`,
        payload,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        },
      )) as AxiosResponse<EmployeeDocument>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteDocument = createAsyncThunk(
  DocumentActions.DELETE_DOCUMENT_REQUEST,
  async (payload: DeleteEmployeeDocumentPayload) => {
    const response = (await apiDelete(
      `/hr/employees/${payload.employee_id}/documents/${payload.document_id}`,
    )) as AxiosResponse<DeleteEmployeeDocumentResponse>;
    const responseData = response.data;
    responseData.id = payload.document_id;
    return responseData;
  },
);

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

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

    builder
      .addCase(updateDocument.pending, (state: Draft<DocumentState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        updateDocument.fulfilled,
        (state: Draft<DocumentState>, action: PayloadAction<EmployeeDocument>) => {
          state.loading = false;
          state.error = null;
          const index = state.documents.findIndex((item) => item.id === action.payload.id);
          if (index > -1) {
            state.documents[index] = action.payload;
          }
          message.success('Successfully updated Document', 8);
        },
      )
      .addCase(
        updateDocument.rejected,
        (state: Draft<DocumentState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

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

export default DocumentSlice;
export type { DocumentState };
