import update from "immutability-helper";
import cloneDeep from "lodash/cloneDeep";

/**
 * Update the lanes in the state
 * @param state
 * @param lanes
 * @returns {unknown}
 */
const updateLanes = (state, lanes) => update(state, { lanes: { $set: lanes } });

/**
 * Helper functions for managing lanes
 * @type {{moveCardAcrossLanes: (function(*, {fromLaneId: *, toLaneId: *, cardId: *, index: *}): *), initialiseLanes: (function(*, {lanes: *}): {lanes: *})}}
 */
const LaneHelper = {
  /**
   * Initialise the lanes
   * @param state
   * @param lanes
   * @returns {unknown}
   */
  initialiseLanes: (state, { lanes }) => {
    const newLanes = lanes.map((lane) => {
      lane.currentPage = 1;
      lane.cards && lane.cards.forEach((c) => (c.laneId = lane.id));
      return lane;
    });
    return updateLanes(state, newLanes);
  },

  /**
   * Move a card from one lane to another
   * @param state
   * @param fromLaneId
   * @param toLaneId
   * @param cardId
   * @param index
   * @returns {unknown}
   */
  moveCardAcrossLanes: (state, { fromLaneId, toLaneId, cardId, index }) => {
    // Clone the state to avoid mutation
    const newLanes = cloneDeep(state.lanes);

    // Find the source and destination lanes using the lane IDs
    const fromLane = newLanes.find((lane) => lane.id === fromLaneId);
    const toLane = newLanes.find((lane) => lane.id === toLaneId);

    if (!fromLane || !toLane) {
      throw new Error("Source or destination lane not found");
    }

    // Find the card in the source lane
    const cardIndex = fromLane.cards.findIndex((card) => card.id === cardId);
    if (cardIndex === -1) {
      throw new Error("Card not found in the source lane");
    }

    // Remove the card from the source lane
    const [card] = fromLane.cards.splice(cardIndex, 1);

    // Insert the card into the destination lane at the specified index
    toLane.cards.splice(index, 0, card);

    let idx = 0;

    // Update the lane and card indexes for all lanes
    newLanes.forEach((lane, laneIndex) => {
      lane.cards.forEach((card, cardIndex) => {
        card.idx = idx;
        card.laneIndex = laneIndex;
        card.cardIndex = cardIndex;
        card.laneId = lane.id;
        idx++;
      });
    });

    return update(state, {
      lanes: { $set: newLanes }
    });
  }

  // TODO: (Note), the rest of this commented out logic is for the way the original Trello board was implemented
  // It would not be hard to adapt should we need to use it in the future

  // const updateLaneCards = (lane, cards) => update(lane, { cards: { $set: cards } });
  // paginateLane: (state, { laneId, newCards, nextPage }) => {
  //   const updatedLanes = LaneHelper.appendCardsToLane(state, { laneId: laneId, newCards: newCards });
  //   updatedLanes.find((lane) => lane.id === laneId).currentPage = nextPage;
  //   return updateLanes(state, updatedLanes);
  // },
  // appendCardsToLane: (state, { laneId, newCards, index }) => {
  //   const lane = state.lanes.find((lane) => lane.id === laneId);
  //   newCards = newCards
  //     .map((c) => update(c, { laneId: { $set: laneId } }))
  //     .filter((c) => lane.cards.find((card) => card.id === c.id) == null);
  //   return state.lanes.map((lane) => {
  //     if (lane.id === laneId) {
  //       const cardsToUpdate =
  //         index !== undefined
  //           ? [...lane.cards.slice(0, index), ...newCards, ...lane.cards.slice(index)]
  //           : [...lane.cards, ...newCards];
  //       return updateLaneCards(lane, cardsToUpdate);
  //     } else {
  //       return lane;
  //     }
  //   });
  // },

  // appendCardToLane: (state, { laneId, card, index }) => {
  //   const newLanes = LaneHelper.appendCardsToLane(state, { laneId: laneId, newCards: [card], index });
  //   return updateLanes(state, newLanes);
  // },
  //
  // addLane: (state, lane) => {
  //   const newLane = { cards: [], ...lane };
  //   return updateLanes(state, [...state.lanes, newLane]);
  // },
  //
  // updateLane: (state, updatedLane) => {
  //   const newLanes = state.lanes.map((lane) => (updatedLane.id === lane.id ? { ...lane, ...updatedLane } : lane));
  //   return updateLanes(state, newLanes);
  // },
  //
  // removeCardFromLane: (state, { laneId, cardId }) => {
  //   // Clone the state to avoid mutation
  //   const newLanes = cloneDeep(state.lanes);
  //
  //   // Find the lane from which the card will be removed
  //   const lane = newLanes.find((lane) => lane.id === laneId);
  //
  //   // Find the card in the lane
  //   const cardIndex = lane.cards.findIndex((card) => card.id === cardId);
  //   if (cardIndex === -1) {
  //     throw new Error("Card not found in the lane");
  //   }
  //
  //   // Remove the card from the lane
  //   lane.cards.splice(cardIndex, 1);
  //
  //   let idx = 0;
  //
  //   // Update the lane and card indexes for all lanes
  //   newLanes.forEach((lane, laneIndex) => {
  //     lane.cards.forEach((card, cardIndex) => {
  //       card.idx = idx;
  //       card.laneIndex = laneIndex;
  //       card.cardIndex = cardIndex;
  //       card.laneId = lane.id;
  //       idx++;
  //     });
  //   });
  //
  //   return update(state, {
  //     lanes: { $set: newLanes }
  //   });
  // },
  // updateCardsForLane: (state, { laneId, cards }) => {
  //   const lanes = state.lanes.map((lane) => (lane.id === laneId ? updateLaneCards(lane, cards) : lane));
  //   return updateLanes(state, lanes);
  // },
  //
  // updateCardForLane: (state, { laneId, card: updatedCard }) => {
  //   const lanes = state.lanes.map((lane) => {
  //     if (lane.id === laneId) {
  //       const cards = lane.cards.map((card) => (card.id === updatedCard.id ? { ...card, ...updatedCard } : card));
  //       return updateLaneCards(lane, cards);
  //     } else {
  //       return lane;
  //     }
  //   });
  //   return updateLanes(state, lanes);
  // },
  //
  // removeLane: (state, { laneId }) => {
  //   const updatedLanes = state.lanes.filter((lane) => lane.id !== laneId);
  //   return updateLanes(state, updatedLanes);
  // }
};

export default LaneHelper;
