import "es6-promise/auto";
import { createStore } from "vuex";
import { postLocation } from "./api";
import prepareLocations from "./store.locations.js";
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods";

const debug = process.env.NODE_ENV !== "production";
//console.log('window.activity', window.activity);

const addIdToValue = (string, id) => {
  let array = string ? string.split(",") : [];
  array.push(id.toString());
  let str = array.join();
  return str;
};

const removeIdFromValue = (string, id) => {
  let array = string.split(",");
  array = array.filter((el) => el !== id.toString());
  let str = array.join();
  return str;
};

const store = createStore({
  strict: debug,
  state: {
    me: null,
    activity: window.activity,
    accompanyingPeriodWorks: [],
    socialIssuesOther: [],
    socialActionsList: [],
    availableLocations: [],
  },
  getters: {
    suggestedEntities(state) {
      if (
        typeof state.activity.accompanyingPeriod === "undefined" ||
        state.activity.accompanyingPeriod === null
      ) {
        return [];
      }
      const allEntities = [
        ...store.getters.suggestedPersons,
        ...store.getters.suggestedRequestor,
        ...store.getters.suggestedUsers,
        ...store.getters.suggestedResources,
      ];
      const uniqueIds = [
        ...new Set(allEntities.map((i) => `${i.type}-${i.id}`)),
      ];
      return Array.from(
        uniqueIds,
        (id) => allEntities.filter((r) => `${r.type}-${r.id}` === id)[0],
      );
    },
    suggestedPersons(state) {
      const existingPersonIds = state.activity.persons.map((p) => p.id);
      return state.activity.activityType.personsVisible === 0
        ? []
        : state.activity.accompanyingPeriod.participations
            .filter((p) => p.endDate === null)
            .map((p) => p.person)
            .filter((p) => !existingPersonIds.includes(p.id));
    },
    suggestedRequestor(state) {
      if (state.activity.accompanyingPeriod.requestor === null) {
        return [];
      }
      const existingPersonIds = state.activity.persons.map((p) => p.id);
      const existingThirdPartyIds = state.activity.thirdParties.map(
        (p) => p.id,
      );

      return [state.activity.accompanyingPeriod.requestor].filter(
        (r) =>
          (r.type === "person" &&
            !existingPersonIds.includes(r.id) &&
            state.activity.activityType.personsVisible !== 0) ||
          (r.type === "thirdparty" &&
            !existingThirdPartyIds.includes(r.id) &&
            state.activity.activityType.thirdPartiesVisible !== 0),
      );
    },
    suggestedUsers(state) {
      const existingUserIds = state.activity.users.map((p) => p.id);
      let suggestedUsers =
        state.activity.activityType.usersVisible === 0
          ? []
          : [state.activity.accompanyingPeriod.user].filter(
              (u) => u !== null && !existingUserIds.includes(u.id),
            );

      state.accompanyingPeriodWorks.forEach((work) => {
        work.referrers.forEach((r) => {
          if (!existingUserIds.includes(r.id)) {
            suggestedUsers.push(r);
          }
        });
      });
      // Add the current user from the state
      if (state.me && !existingUserIds.includes(state.me.id)) {
        suggestedUsers.push(state.me);
      }
      // console.log("suggested users", suggestedUsers);

      return suggestedUsers.filter((u) => u.enabled === true);
    },
    suggestedResources(state) {
      // const resources = state.activity.accompanyingPeriod.resources;
      const existingPersonIds = state.activity.persons.map((p) => p.id);
      const existingThirdPartyIds = state.activity.thirdParties.map(
        (p) => p.id,
      );
      return state.activity.accompanyingPeriod.resources
        .map((r) => r.resource)
        .filter(
          (r) =>
            (r.type === "person" &&
              !existingPersonIds.includes(r.id) &&
              state.activity.activityType.personsVisible !== 0) ||
            (r.type === "thirdparty" &&
              !existingThirdPartyIds.includes(r.id) &&
              state.activity.activityType.thirdPartiesVisible !== 0),
        );
    },
    socialActionsListSorted(state) {
      return [...state.socialActionsList]
        .sort((a, b) => a.ordering - b.ordering)
        .reduce((acc, action) => {
          const issueText = action.issue?.text || "Uncategorized";
          // Find if the group for the issue already exists
          let group = acc.find((item) => item.issue === issueText);
          if (!group) {
            group = { issue: issueText, actions: [] };
            acc.push(group);
          }
          group.actions.push(action);
          return acc;
        }, []);
    },
  },
  mutations: {
    setWhoAmI(state, me) {
      state.me = me;
    },
    // SocialIssueAcc
    addIssueInList(state, issue) {
      //console.log('add issue list', issue.id);
      state.activity.accompanyingPeriod.socialIssues.push(issue);
    },
    addIssueSelected(state, issue) {
      //console.log('add issue selected', issue.id);
      state.activity.socialIssues.push(issue);
    },
    updateIssuesSelected(state, issues) {
      //console.log('update issues selected', issues);
      state.activity.socialIssues = issues;
    },
    updateIssuesOther(state, payload) {
      //console.log('update issues other');
      state.socialIssuesOther = payload;
    },
    removeIssueInOther(state, issue) {
      //console.log('remove issue other', issue.id);
      state.socialIssuesOther = state.socialIssuesOther.filter(
        (i) => i.id !== issue.id,
      );
    },
    resetActionsList(state) {
      //console.log('reset list actions');
      state.socialActionsList = [];
    },
    addActionInList(state, action) {
      state.socialActionsList.push(action);
    },
    updateActionsSelected(state, actions) {
      //console.log('update actions selected', actions);
      state.activity.socialActions = actions;
    },
    filterList(state, list) {
      const filterList = (list) => {
        // remove duplicates entries
        list = list.filter(
          (value, index) =>
            list.findIndex((array) => array.id === value.id) === index,
        );
        // alpha sort
        list.sort((a, b) => (a.text > b.text ? 1 : b.text > a.text ? -1 : 0));
        return list;
      };
      if (list === "issues") {
        state.activity.accompanyingPeriod.socialIssues = filterList(
          state.activity.accompanyingPeriod.socialIssues,
        );
      }
      if (list === "actions") {
        state.socialActionsList = filterList(state.socialActionsList);
      }
    },

    // ConcernedGroups
    addPersonsInvolved(state, payload) {
      console.log("### mutation addPersonsInvolved", payload);
      switch (payload.result.type) {
        case "person":
          state.activity.persons.push(payload.result);
          break;
        case "thirdparty":
          state.activity.thirdParties.push(payload.result);
          break;
        case "user":
          state.activity.users.push(payload.result);
          break;
      }
    },
    removePersonInvolved(state, payload) {
      //console.log('### mutation removePersonInvolved', payload.type);
      switch (payload.type) {
        case "person":
          state.activity.persons = state.activity.persons.filter(
            (person) => person !== payload,
          );
          break;
        case "thirdparty":
          state.activity.thirdParties = state.activity.thirdParties.filter(
            (thirdparty) => thirdparty !== payload,
          );
          break;
        case "user":
          state.activity.users = state.activity.users.filter(
            (user) => user !== payload,
          );
          break;
      }
    },
    updateLocation(state, value) {
      console.log("### mutation: updateLocation", value);
      state.activity.location = value;
    },
    addAvailableLocationGroup(state, group) {
      state.availableLocations.push(group);
    },
    setAccompanyingPeriodWorks(state, works) {
      state.accompanyingPeriodWorks = works;
    },
  },
  actions: {
    addIssueSelected({ commit }, issue) {
      let aSocialIssues = document.getElementById(
        "chill_activitybundle_activity_socialIssues",
      );
      aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
      commit("addIssueSelected", issue);
    },
    updateIssuesSelected({ commit }, payload) {
      let aSocialIssues = document.getElementById(
        "chill_activitybundle_activity_socialIssues",
      );
      aSocialIssues.value = "";
      payload.forEach((item) => {
        aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
      });
      commit("updateIssuesSelected", payload);
    },
    updateActionsSelected({ commit }, payload) {
      let aSocialActions = document.getElementById(
        "chill_activitybundle_activity_socialActions",
      );
      aSocialActions.value = "";
      payload.forEach((item) => {
        aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
      });
      commit("updateActionsSelected", payload);
    },
    addAvailableLocationGroup({ commit }, payload) {
      commit("addAvailableLocationGroup", payload);
    },
    addPersonsInvolved({ commit }, payload) {
      //console.log('### action addPersonsInvolved', payload.result.type);
      switch (payload.result.type) {
        case "person":
          let aPersons = document.getElementById(
            "chill_activitybundle_activity_persons",
          );
          aPersons.value = addIdToValue(aPersons.value, payload.result.id);
          break;
        case "thirdparty":
          let aThirdParties = document.getElementById(
            "chill_activitybundle_activity_thirdParties",
          );
          aThirdParties.value = addIdToValue(
            aThirdParties.value,
            payload.result.id,
          );
          break;
        case "user":
          let aUsers = document.getElementById(
            "chill_activitybundle_activity_users",
          );
          aUsers.value = addIdToValue(aUsers.value, payload.result.id);
          break;
      }
      commit("addPersonsInvolved", payload);
    },
    removePersonInvolved({ commit }, payload) {
      //console.log('### action removePersonInvolved', payload);
      switch (payload.type) {
        case "person":
          let aPersons = document.getElementById(
            "chill_activitybundle_activity_persons",
          );
          aPersons.value = removeIdFromValue(aPersons.value, payload.id);
          break;
        case "thirdparty":
          let aThirdParties = document.getElementById(
            "chill_activitybundle_activity_thirdParties",
          );
          aThirdParties.value = removeIdFromValue(
            aThirdParties.value,
            payload.id,
          );
          break;
        case "user":
          let aUsers = document.getElementById(
            "chill_activitybundle_activity_users",
          );
          aUsers.value = removeIdFromValue(aUsers.value, payload.id);
          break;
      }
      commit("removePersonInvolved", payload);
    },
    updateLocation({ commit }, value) {
      console.log("### action: updateLocation", value);
      let hiddenLocation = document.getElementById(
        "chill_activitybundle_activity_location",
      );
      if (value.onthefly) {
        const body = {
          type: "location",
          name:
            value.name === "__AccompanyingCourseLocation__" ? null : value.name,
          locationType: {
            id: value.locationType.id,
            type: "location-type",
          },
        };
        if (value.address.id) {
          Object.assign(body, {
            address: {
              id: value.address.id,
            },
          });
        }
        postLocation(body)
          .then((location) => (hiddenLocation.value = location.id))
          .catch((err) => {
            console.log(err.message);
          });
      } else {
        hiddenLocation.value = value.id;
      }
      commit("updateLocation", value);
    },
    async fetchAccompanyingPeriodWorks({ state, commit }) {
      const accompanyingPeriodId = state.activity.accompanyingPeriod.id;
      const url = `/api/1.0/person/accompanying-course/${accompanyingPeriodId}/works.json`;
      try {
        const works = await fetchResults(url);
        // console.log('works', works);
        commit("setAccompanyingPeriodWorks", works);
      } catch (error) {
        console.error("Failed to fetch works:", error);
      }
    },
    getWhoAmI({ commit }) {
      const url = `/api/1.0/main/whoami.json`;
      makeFetch("GET", url).then((user) => {
        commit("setWhoAmI", user);
      });
    },
  },
});

store.dispatch("getWhoAmI");

prepareLocations(store);
store.dispatch("fetchAccompanyingPeriodWorks");

export default store;
