import { ACTIONS } from 'lbry-redux';

const reducers = {};
const defaultState = {
  fetching: false,
  claimedRewardsById: {}, // id => reward
  unclaimedRewards: [],
  claimPendingByType: {},
  claimErrorsByType: {},
  rewardedContentClaimIds: [],
};

reducers[ACTIONS.FETCH_REWARDS_STARTED] = state =>
  Object.assign({}, state, {
    fetching: true,
  });

reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = (state, action) => {
  const { userRewards } = action.data;

  const unclaimedRewards = [];
  const claimedRewards = {};
  userRewards.forEach(reward => {
    if (reward.transaction_id) {
      claimedRewards[reward.id] = reward;
    } else {
      unclaimedRewards.push(reward);
    }
  });

  return Object.assign({}, state, {
    claimedRewardsById: claimedRewards,
    unclaimedRewards,
    fetching: false,
  });
};

function setClaimRewardState(state, reward, isClaiming, errorMessage = '') {
  const newClaimPendingByType = Object.assign({}, state.claimPendingByType);
  const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType);

  // Currently, for multiple rewards of the same type, they will both show "claiming" when one is beacuse we track this by `reward_type`
  // To fix this we will need to use `claim_code` instead, and change all selectors to match
  if (reward) {
    if (isClaiming) {
      newClaimPendingByType[reward.reward_type] = isClaiming;
    } else {
      delete newClaimPendingByType[reward.reward_type];
    }
    if (errorMessage) {
      newClaimErrorsByType[reward.reward_type] = errorMessage;
    } else {
      delete newClaimErrorsByType[reward.reward_type];
    }
  }

  return Object.assign({}, state, {
    claimPendingByType: newClaimPendingByType,
    claimErrorsByType: newClaimErrorsByType,
  });
}

reducers[ACTIONS.CLAIM_REWARD_STARTED] = (state, action) => {
  const { reward } = action.data;

  return setClaimRewardState(state, reward, true, '');
};

reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = (state, action) => {
  const { reward } = action.data;
  const { unclaimedRewards } = state;

  const index = unclaimedRewards.findIndex(ur => ur.claim_code === reward.claim_code);
  unclaimedRewards.splice(index, 1);

  const { claimedRewardsById } = state;
  claimedRewardsById[reward.id] = reward;

  const newState = {
    ...state,
    unclaimedRewards: [...unclaimedRewards],
    claimedRewardsById: { ...claimedRewardsById },
  };

  return setClaimRewardState(newState, reward, false, '');
};

reducers[ACTIONS.CLAIM_REWARD_FAILURE] = (state, action) => {
  const { reward, error } = action.data;

  return setClaimRewardState(state, reward, false, error ? error.message : '');
};

reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = (state, action) => {
  const { reward } = action.data;

  return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], '');
};

reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = (state, action) => {
  const { claimIds } = action.data;

  return Object.assign({}, state, {
    rewardedContentClaimIds: claimIds,
  });
};

export default function rewardsReducer(state = defaultState, action) {
  const handler = reducers[action.type];
  if (handler) return handler(state, action);
  return state;
}