import Vue from 'vue'
import Util from '@/util'

export const state = () => ({
    list: [],
    remote: {},
    local: {},
    logo: {
        name: '',
        url: '',
        file: null,
    },
    branches: [],
});

export const getters = {
    hasMembers: (state) => state.list.length > 0,
    hasChanges: (state) => {

        if (!Util.areEqualInputs(
            state.remote,
            state.local,
            ['summaries', 'addresses', 'contacts', 'contributions']
        )) return true

        if (state.logo.url) return true

        return false
    },
    revision: (state) => {
        if (!state.local.revision) return false
        return JSON.parse(state.local.revision.data)
    },
    revisionHasChanges: (state, getters) => {
        if (!getters.revision) return false

        if (Util.areEqualInputs(
            state.local,
            getters.revision
        )) return true

        return false
    },

    membersFiltered: (state, getters, rootState, rootGetters) => {

        if (rootGetters.isSuperAdmin || rootGetters.isAdmin || rootGetters.isOperator) {
            return state.list
        }
        if (rootGetters.loggedInUser.isMemberEditor) return state.list.filter(
            (member) => member.user_id === rootGetters.loggedInUser.id
        )
        return state.list
    },

    isSuperAdminAdminOrDelegated: (state, getters, rootState, rootGetters) => {
        if (rootGetters.isSuperAdmin || rootGetters.isAdmin) return true
        if (!state.local.user_id) return false
        return state.local.user_id === rootGetters.loggedInUser.id
    },

    isMemberValidated: (state) => {
        return !!state.local.informal_name && !!state.local.formal_name && !!state.local.kvk_number
    },

    getBranchById: (state) => (id) => state.branches.find(b => b.id === id),
}

/** @type {import('@typedefs/store').ActionTree} */
export const actions = {
    async pullData({ commit, state }) {
        try {
            const response = await this.$axios.get('/members')
            await commit('STORE_MEMBERS', response.data)
        } catch (error) {
            console.log("pullMembers -> error", error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }
    },

    async pullBranches({ commit, state }) {
        try {
            const response = await this.$axios.get('members/branches')
            await commit("STORE_BRANCHES", response.data)
        } catch (error) {
            console.log("pullBranches -> error", error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }
    },

    async pullTypes({ commit }) {
        try {
            const response = await this.$axios.get('members/types');
            await commit('STORE_TYPES', response.data);
        } catch (error) {
            console.log('pullTypes -> error', error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: 'error',
                icon: 'mdi-close',
            });
        }
    },

    async getAndSetMember({ commit, dispatch, state }, url) {
        try {
            const response = await dispatch('get', url)
            await commit('SET_MEMBER', response)
        } catch (error) {
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }
    },

    async get({ state }, url) {
        try {
            const response = await this.$axios.get(`/members/${url}`)
            return response.data
        } catch (error) {

            $nuxt.error({ statusCode: 401, message: 'Lid niet gevonden' })

            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }
    },

    async store({ dispatch, commit, state, getters, rootGetters }, revision = false) {
        const formData = new FormData()

        let data;

        if (revision) {

            data = { ...getters.revision }
            if (revision.show_on_website) data.show_on_website = 1

            if (data.sub_branches.some(branch => branch.id)) {
                const subBranchesIds = data.sub_branches.map(({ id }) => id)
                data.sub_branches = [...subBranchesIds]
            }

            data.revisor_id = rootGetters.loggedInUser.id

        } else {

            if (state.local.show_on_website) await commit('UPDATE_FIELD', { field: 'show_on_website', value: 1 })
            if (state.local.sub_branches.some(branch => branch.id)) {
                const subBranchesIds = state.local.sub_branches.map(({ id }) => id)
                await commit('UPDATE_FIELD', { field: 'sub_branches', value: subBranchesIds })
            }

            data = { ...state.local }
        }

        const fieldsAllowedNull = this.$constants.store.members.fieldsAllowedNull

        for (let key in data) {
            if ((data[key] && data[key] != "null")
                || (data[key] === null && fieldsAllowedNull.indexOf(key) !== -1)
            ) {
                const value = data[key] ?? ''

                // If value is array/object, stringify that
                formData.append(
                    key,
                    typeof value === 'object'
                        ? JSON.stringify(value)
                        : value
                )
            }
        }

        if (state.logo.file) formData.append('logo', state.logo.file)
        else formData.delete('logo')

        let slug = '';

        // console.log([...formData])

        await this.$axios.post('/members', formData)
            .then(async response => {
                Promise.resolve(response)
                await dispatch('pullData');
                slug = response.data.slug
            })
            .catch(error => Promise.reject(error))

        return slug
    },

    async storeRevision({ state, rootGetters, dispatch }) {

        const formData = new FormData()

        const tmpObj = { ...state.local }

        // Remove not useful data attached
        delete tmpObj.revision;
        delete tmpObj.data;
        delete tmpObj.addresses;
        delete tmpObj.summaries;
        delete tmpObj.contacts;

        const revision = JSON.stringify(tmpObj)


        if (state.local.revision) formData.append('id', state.local.revision.id)
        if (state.logo.file) formData.append('logo', state.logo.file)
        formData.append('member_id', state.local.id)
        formData.append('user_id', rootGetters.loggedInUser.id)
        formData.append('data', revision)

        // console.log([...formData])

        await this.$axios.post('/members/revision', formData)
            .then(async response => {
                Promise.resolve(response)
                await dispatch('pullData');
            })
            .catch(error => Promise.reject(error))
    },

    async deleteMember({ dispatch, state }, memberId = state.remote.id) {

        if (!memberId) return

        try {

            await this.$axios.delete(`/members/${memberId}`)
            await dispatch('pullData');

            $nuxt.$notifier.showMessage({
                content: `Member deleted`,
                color: 'success',
                icon: 'mdi-delete',
            });

        } catch (error) {
            console.log("deleteMember -> error", error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }

    },


    async storeSummary({ dispatch, state }, data) {

        if (!state.remote.id) return

        data['member_id'] = state.remote.id

        if (data['toAll'] === false) { delete data['toAll'] }

        await this.$axios.post(`/members/summaries`, data)
            .then(async response => {

                Promise.resolve(response)

                await dispatch('getAndSetMember', data['member_id'])

                $nuxt.$notifier.showMessage({
                    content: 'Werknemers opgeslagen',
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: error,
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async storeContribution({ dispatch, state, rootGetters }, data) {

        if (!state.remote.id) return
        if (!rootGetters.isSuperAdminOrAdmin && data.toAll) return

        data['member_id'] = state.remote.id

        if (data['toAll'] === false) { delete data['toAll'] }

        await this.$axios.post(`/members/contributions`, data)
            .then(async response => {

                Promise.resolve(response)

                // if (!data.toAll) {
                await dispatch('getAndSetMember', data['member_id'])
                // }

                $nuxt.$notifier.showMessage({
                    content: `Contribution added`,
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: error,
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async storeAddress({ dispatch, state }, data) {

        if (!state.remote.id) return

        data['member_id'] = state.remote.id

        await this.$axios.post(`/members/addresses`, data)
            .then(async response => {

                Promise.resolve(response)

                await dispatch('getAndSetMember', data['member_id'])

                $nuxt.$notifier.showMessage({
                    content: `Address added`,
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: error,
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async storeContact({ dispatch, state }, data) {
        if (!state.remote.id) return

        data['member_id'] = state.remote.id

        await this.$axios.post(`/members/contacts`, data)
            .then(async response => {

                Promise.resolve(response)

                await dispatch('getAndSetMember', data['member_id'])

                $nuxt.$notifier.showMessage({
                    content: `Contact added`,
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: `${error.response ? error.response.data.message : error}.`,
                    ...(error.response && {
                        errors: error.response.data.errors,
                    }),
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async deleteSummary({ commit, state }, item) {

        if (!item.id) return

        try {

            await this.$axios.delete(`/members/summaries/${item.id}`)

            await commit('DELETE_SUMMARY_LOCAL', item)

            $nuxt.$notifier.showMessage({
                content: `Summary deleted`,
                color: 'success',
                icon: 'mdi-delete',
            });

        } catch (error) {
            console.log("addSummary -> error", error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }

    },

    async deleteContribution({ commit, state }, item) {

        if (!item.id) return

        try {

            await this.$axios.delete(`/members/contributions/${item.id}`)

            await commit('DELETE_CONTRIBUTION_LOCAL', item)

            $nuxt.$notifier.showMessage({
                content: `Contribution deleted`,
                color: 'success',
                icon: 'mdi-delete',
            });

        } catch (error) {
            console.log(error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }

    },

    async addManagementLink({ dispatch, commit, stage }, data) {
        if (!data) return

        let link = { member_id: data };

        await this.$axios.post(`/members/managementlink/addlink`, link)
            .then(async response => {

                Promise.resolve(response)

                await dispatch('pullData');

                $nuxt.$notifier.showMessage({
                    content: `Link added`,
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: `${error.response ? error.response.data.message : error}.`,
                    ...(error.response && {
                        errors: error.response.data.errors,
                    }),
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async deleteManagementLink({ dispatch, commit, stage }, data) {
        if (!data) return

        let link = { link_id: data };

        await this.$axios.post(`/members/managementlink/deletelink`, link)
            .then(async response => {

                Promise.resolve(response)

                await dispatch('pullData');

                $nuxt.$notifier.showMessage({
                    content: `Link removed`,
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: `${error.response ? error.response.data.message : error}.`,
                    ...(error.response && {
                        errors: error.response.data.errors,
                    }),
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async changeManagementLink({ dispatch, commit, stage }, data) {
        if (!data) return

        await this.$axios.post(`/members/managementlink/changelink`, data)
            .then(async response => {

                Promise.resolve(response)

                await dispatch('pullData');

                $nuxt.$notifier.showMessage({
                    content: `Link added`,
                    color: 'success',
                    icon: 'mdi-check',
                });
            })
            .catch(error => {
                Promise.reject(error)

                $nuxt.$notifier.showMessage({
                    content: `${error.response ? error.response.data.message : error}.`,
                    ...(error.response && {
                        errors: error.response.data.errors,
                    }),
                    color: "error",
                    icon: "mdi-close",
                });
            })
    },

    async deleteAddress({ commit, state }, item) {

        if (!item.id) return

        try {

            await this.$axios.delete(`/members/addresses/${item.id}`)

            await commit('DELETE_ADDRESS_LOCAL', item)

            $nuxt.$notifier.showMessage({
                content: `Address deleted`,
                color: 'success',
                icon: 'mdi-delete',
            });

        } catch (error) {
            console.log("deleteAddress -> error", error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }

    },

    async deleteContact({ commit, state }, item) {

        if (!item.id) return

        try {

            await this.$axios.delete(`/members/contacts/${item.id}`)

            await commit('DELETE_CONTACT_LOCAL', item)

            $nuxt.$notifier.showMessage({
                content: `Contact deleted`,
                color: 'success',
                icon: 'mdi-delete',
            });

        } catch (error) {
            console.log("deleteContact -> error", error)
            $nuxt.$notifier.showMessage({
                content: error,
                color: "error",
                icon: "mdi-close",
            });
        }

    },

    async updateManagementLinks({ commit, state }, item) {
        console.log(item);
    },

    async resetMember({ commit }) {
        await commit('RESET_MEMBER');
        await commit('RESET_LOGO');
    },

}

export const mutations = {
    STORE_MEMBERS: (state, payload) => state.list = payload,
    STORE_BRANCHES: (state, payload) => state.branches = payload,
    STORE_TYPES: (state, payload) => state.types = payload,
    SET_MEMBER: (state, payload) => {
        state.remote = { ...payload };
        state.local = { ...payload };
    },
    UPDATE_FIELD: (state, payload) => {

        // Old way with reactivity problems
        // state.local[payload.field] = payload.value

        // New way that solves with reactivity
        Vue.set(state.local, payload.field, payload.value)
    },
    RESET_MEMBER: (state) => {
        state.remote = {};
        state.local = {};
    },

    RESET_MEMBERS: (state) => state.list = [],

    RESET_LOGO: (state) => {
        state.logo = {
            name: '',
            url: '',
            file: null,
        };
    },
    UPDATE_LOGO: (state, payload) => {
        state.logo = payload;
    },
    DELETE_ADDRESS_LOCAL: (state, payload) => {
        // Workaround because Vuex doesn't recognize changes otherwise
        const tmp = [...state.local.addresses];
        const index = tmp.indexOf(payload)
        tmp.splice(index, 1)

        state.local.addresses = []
        state.local.addresses = [...tmp]
    },
    DELETE_CONTACT_LOCAL: (state, payload) => {
        // Workaround because Vuex doesn't recognize changes otherwise
        const tmp = [...state.local.contacts];
        const index = tmp.indexOf(payload)
        tmp.splice(index, 1)

        state.local.contacts = []
        state.local.contacts = [...tmp]
    },
    DELETE_SUMMARY_LOCAL: (state, payload) => {
        // Workaround because Vuex doesn't recognize changes otherwise
        const tmp = [...state.local.summaries];
        const index = tmp.indexOf(payload)
        tmp.splice(index, 1)

        state.local.summaries = []
        state.local.summaries = [...tmp]
    },

    DELETE_CONTRIBUTION_LOCAL: (state, payload) => {
        // Workaround because Vuex doesn't recognize changes otherwise
        const tmp = [...state.local.contributions];
        const index = tmp.indexOf(payload)
        tmp.splice(index, 1)

        state.local.contributions = []
        state.local.contributions = [...tmp]
    },
}
