import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import APIs from '@src/api/APIs';
import { IActivity, ICollection, IFilter, INFT, IProfile, IUserInfo } from 'metarare';

type UserState = {
  isUserInfoLoaded: boolean;
  isUserProfileLoaded: boolean;
  userInfo: IUserInfo | null;
  activity: IActivity[];
  bid: INFT[];
  collection: ICollection[];
  like: INFT[];
  onSale: INFT[];
  owned: INFT[];
  profile: IProfile | null;
}

const userState: UserState = {
  isUserInfoLoaded: true,
  isUserProfileLoaded: true,
  userInfo: null,
  activity: [],
  bid: [],
  collection: [],
  like: [],
  onSale: [],
  owned: [],
  profile: null,
};

export const fetchUserInfo = createAsyncThunk(
  'user/fetchUserInfo',
  async (_, thunkAPI) => {
    try {
      const response = await APIs.fetchUserInfo();
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserActivity = createAsyncThunk<Promise<any>, string>(
  'user/fetchUserActivity',
  async (name, thunkAPI) => {
    try {
      const response = await APIs.fetchUserActivity(name);
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserBid = createAsyncThunk<Promise<any>, IFilter>(
  'user/fetchUserBid',
  async (filter, thunkAPI) => {
    try {
      const response = await APIs.fetchUserBid(filter);
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserCollection = createAsyncThunk<Promise<any>, { name: string; filter: IFilter }>(
  'user/fetchUserCollection',
  async ({ name, filter }, thunkAPI) => {
    try {
      const response = await APIs.fetchUserCollection({ name, filter });
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserLike = createAsyncThunk<Promise<any>, { name: string; filter: IFilter }>(
  'user/fetchUserLike',
  async ({ name, filter }, thunkAPI) => {
    try {
      const response = await APIs.fetchUserLike({ name, filter });
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserOnSale = createAsyncThunk<Promise<any>, { name: string; filter: IFilter }>(
  'user/fetchUserOnSale',
  async ({ name, filter }, thunkAPI) => {
    try {
      const response = await APIs.fetchUserOnSale({ name, filter });
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserOwned = createAsyncThunk<Promise<any>, { name: string; filter: IFilter }>(
  'user/fetchUserOwned',
  async ({ name, filter }, thunkAPI) => {
    try {
      const response = await APIs.fetchUserOwned({ name, filter });
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const fetchUserProfile = createAsyncThunk<Promise<any>, string>(
  'user/fetchUserProfile',
  async (name, thunkAPI) => {
    try {
      const response = await APIs.fetchUserProfile(name);
      return response;
    } catch (err) {
      return thunkAPI.rejectWithValue('Something went wrong.');
    }
  }
);

export const slice = createSlice({
  name: 'user',
  initialState: userState,
  reducers: {
    resetProfile: (state: UserState) => {
      state.userInfo = null;
    },
    resetOnSale: (state: UserState) => {
      state.onSale = [];
    },
    resetOwned: (state: UserState) => {
      state.owned = [];
    },
    resetCollection: (state: UserState) => {
      state.collection = [];
    },
    resetLike: (state: UserState) => {
      state.like = [];
    },
    resetBid: (state: UserState) => {
      state.bid = [];
    },
    removeLike: (state: UserState, action: PayloadAction<number>) => {
      const tokenId = action.payload;

      state.like = state.like.filter(item => item.token_id !== tokenId);
    }
  },
  extraReducers: {
    [fetchUserInfo.pending.type]: (state: UserState, action) => {
      state.isUserInfoLoaded = false;
    },
    [fetchUserInfo.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.userInfo = payload;
      state.isUserInfoLoaded = true;
    },
    [fetchUserInfo.rejected.type]: (state: UserState, action) => {
      state.isUserInfoLoaded = true;
    },
    [fetchUserActivity.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.activity = payload;
    },
    [fetchUserBid.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.bid = [
        ...state.bid,
        ...payload
      ];
    },
    [fetchUserCollection.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.collection = [
        ...state.collection,
        ...payload
      ];
    },
    [fetchUserLike.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.like = [
        ...state.like,
        ...payload
      ];
    },
    [fetchUserOnSale.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.onSale = [
        ...state.onSale,
        ...payload
      ];
    },
    [fetchUserOwned.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.owned = [
        ...state.owned,
        ...payload
      ];
    },
    [fetchUserProfile.pending.type]: (state: UserState, action) => {
      state.isUserProfileLoaded = false;
    },
    [fetchUserProfile.fulfilled.type]: (state: UserState, action) => {
      const { payload } = action;

      state.profile = payload;
      state.isUserProfileLoaded = true;
    },
    [fetchUserProfile.rejected.type]: (state: UserState, action) => {
      state.isUserProfileLoaded = true;
    },
  },
});

export const {
  resetProfile,
  resetOnSale,
  resetCollection,
  resetLike,
  resetBid,
  resetOwned,
  removeLike
} = slice.actions;

const UserReducer = slice.reducer;
export default UserReducer;
