import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { OkrKeyResult } from '@/interface/Goal';
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 { OkrKeyResultActions } from './actionTypes';

interface OkrKeyResultState {
  okrKeyResults: OkrKeyResult[];
  loading: boolean;
  error: string | null;
}

const initialState: OkrKeyResultState = {
  okrKeyResults: [],
  loading: false,
  error: null,
};

export const fetchOkrKeyResults = createAsyncThunk(
  OkrKeyResultActions.FETCH_OKR_KEY_RESULTS_REQUEST,
  async (goalId: string) => {
    const response = (await apiGet(`/goals/${goalId}/key-results`)) as AxiosResponse<{ data: OkrKeyResult[] }>;
    return response.data.data;
  },
);

export const createOkrKeyResult = createAsyncThunk(
  OkrKeyResultActions.CREATE_OKR_KEY_RESULT_REQUEST,
  async (payload: { goalId: string; data: Omit<OkrKeyResult, 'id' | 'goal_id' | 'created_at' | 'updated_at'> }, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/goals/${payload.goalId}/key-results`,
        payload.data,
      )) as AxiosResponse<{ data: OkrKeyResult }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateOkrKeyResult = createAsyncThunk(
  OkrKeyResultActions.UPDATE_OKR_KEY_RESULT_REQUEST,
  async (payload: Partial<OkrKeyResult> & { id: string }, { rejectWithValue }) => {
    try {
      const response = (await apiPut(
        `/key-results/${payload.id}`,
        payload,
      )) as AxiosResponse<{ data: OkrKeyResult }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteOkrKeyResult = createAsyncThunk(
  OkrKeyResultActions.DELETE_OKR_KEY_RESULT_REQUEST,
  async (id: string, { rejectWithValue }) => {
    try {
      const response = (await apiDelete(`/key-results/${id}`)) as AxiosResponse<{ message: string }>;
      return { message: response.data.message, id };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

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

    builder
      .addCase(createOkrKeyResult.pending, (state: Draft<OkrKeyResultState>) => {
        state.loading = true;
      })
      .addCase(
        createOkrKeyResult.fulfilled,
        (state: Draft<OkrKeyResultState>, action: PayloadAction<OkrKeyResult>) => {
          state.okrKeyResults.unshift(action.payload);
          state.loading = false;
        },
      )
      .addCase(
        createOkrKeyResult.rejected,
        (state: Draft<OkrKeyResultState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(updateOkrKeyResult.pending, (state: Draft<OkrKeyResultState>) => {
        state.loading = true;
      })
      .addCase(
        updateOkrKeyResult.fulfilled,
        (state: Draft<OkrKeyResultState>, action: PayloadAction<OkrKeyResult>) => {
          const idx = state.okrKeyResults.findIndex((kr) => kr.id === action.payload.id);
          if (idx !== -1) {
            state.okrKeyResults[idx] = action.payload;
          }
          state.loading = false;
          message.success('Successfully updated key result', 10);
        },
      )
      .addCase(
        updateOkrKeyResult.rejected,
        (state: Draft<OkrKeyResultState>, action: RejectedActionPayload) => {
          state.loading = false;
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deleteOkrKeyResult.pending, (state: Draft<OkrKeyResultState>) => {})
      .addCase(
        deleteOkrKeyResult.fulfilled,
        (state: Draft<OkrKeyResultState>, action: PayloadAction<{ message: string; id: string }>) => {
          state.okrKeyResults = state.okrKeyResults.filter((item) => item.id !== action.payload.id);
          message.success(action.payload.message, 10);
        },
      )
      .addCase(deleteOkrKeyResult.rejected, (state: Draft<OkrKeyResultState>, action: RejectedActionPayload) => {
        message.error(Helpers.handleServerError(action.payload), 8);
      });
  },
});

export default OkrKeyResultSlice;
export type { OkrKeyResultState };
