import {create} from 'zustand';
import {produce} from 'immer';

import * as rsssl_api from "../utils/api";
import {__} from "@wordpress/i18n";
const useOnboardingData = create(( set, get ) => ({
    steps: [],
    currentStepIndex: 0,
    currentStep: {},
    error: false,
    networkProgress: 0,
    networkActivationStatus: '',
    certificateValid: '',
    networkwide: false,
    sslEnabled: false,
    overrideSSL: false,
    showOnboardingModal: false,
    modalStatusLoaded: false,
    dataLoaded: false,
    processing: false,
    email: '',
    includeTips:false,
    sendTestEmail:true,
    overrideSSLDetection:false,
    footerStatus: '',
    setFooterStatus: (footerStatus) => {
        set({footerStatus:footerStatus})
    },
    setIncludeTips: (includeTips) => {
        set(state => ({ includeTips }))
    },
    setSendTestEmail: (sendTestEmail) => {
        set(state => ({ sendTestEmail }))
    },
    setEmail: (email) => {
        set(state => ({ email }))
    },
    setShowOnboardingModal: (showOnboardingModal) => {
        set(state => ({ showOnboardingModal }))
    },
    setProcessing: (processing) => {
        set(state => ({ processing }))
    },
    setCurrentStepIndex: (currentStepIndex) => {
        const currentStep = get().steps[currentStepIndex];
        set(state => ({ currentStepIndex, currentStep }))
    },
    dismissModal: async (dismiss) => {
        let data={};
        data.dismiss = dismiss;
        //dismiss is opposite of showOnboardingModal, so we check the inverse.
        set(() => ({showOnboardingModal: !dismiss}));
        await rsssl_api.doAction('dismiss_modal', data);
    },
    setOverrideSSL: async (override) => {
        set({overrideSSL: override});
        let data = {
            overrideSSL: override,
        };
        await rsssl_api.doAction('override_ssl_detection',data );
    },
    activateSSL: () => {
        set((state) => ({processing:true}));
        rsssl_api.runTest('activate_ssl' ).then( async ( response ) => {
            set((state) => ({processing:false}));
            get().setCurrentStepIndex( get().currentStepIndex+1 );
            //change url to https, after final check
            if ( response.success ) {
                if ( response.site_url_changed ) {
                    window.location.reload();
                } else {
                    if ( get().networkwide ) {
                        set(state => ({ networkActivationStatus:'main_site_activated' }))
                    }
                }

                set({ sslEnabled: true})
            }
        });
    },
    saveEmail:() => {
        get().setFooterStatus( __("Updating email preferences..", "really-simple-ssl") );
        let data={};
        data.email = get().email;
        data.includeTips = get().includeTips;
        data.sendTestEmail = get().sendTestEmail;
        set((state) => ({processing:true}));
        rsssl_api.doAction('update_email', data).then(( response ) => {
            set((state) => ({processing:false}));
            get().setFooterStatus('' );
        });
    },
    updateItemStatus: (stepId, id, action, status, activated) => {
        const index = get().steps.findIndex(item => { return item.id===stepId; });
        const itemIndex = get().steps[index].items.findIndex(item => {return item.id===id;});
        set(
            produce((state) => {
                if (typeof action !== 'undefined') state.steps[index].items[itemIndex].action = action;
                if (typeof status !== 'undefined') state.steps[index].items[itemIndex].status = status;
                if (typeof activated !== 'undefined') state.steps[index].items[itemIndex].activated = activated;
            })
        )
        let currentStep = get().steps[get().currentStepIndex];
        set(
            produce((state) => {
                    state.currentStep = currentStep;
                }
            ))
    },
    fetchOnboardingModalStatus: async () => {
        rsssl_api.doAction('get_modal_status').then((response) => {
            set({
                showOnboardingModal: !response.dismissed,
                modalStatusLoaded: true,
            })
        });
    },
    setShowOnBoardingModal: (showOnboardingModal) => set(state => ({ showOnboardingModal })),
    pluginInstaller: async (id, action, title) => {
        if ( !action ) {
            return;
        }

        set(() => ({processing:true}));
        get().updateItemStatus('plugins', id, action, 'processing');
        get().setFooterStatus(__("Installing %d...", "really-simple-ssl").replace("%d", title));

        let nextAction = await processAction(action, id);
        get().updateItemStatus('plugins', id, nextAction);

        if ( nextAction!=='none' && nextAction!=='completed') {
            get().setFooterStatus(__("Activating %d...", "really-simple-ssl").replace("%d", title));
            nextAction = await processAction(nextAction, id);
            get().updateItemStatus('plugins', id, nextAction);
        } else {
            get().setFooterStatus('');
        }
        set((state) => ({processing:false}));
    },
    getSteps: async (forceRefresh) => {
        const {steps, networkActivationStatus, certificateValid, networkProgress, networkwide,
            overrideSSL, error, sslEnabled, upgradedFromFree} = await retrieveSteps(forceRefresh);

        const urlParams = new URLSearchParams(window.location.search);
        const isVerified = urlParams.get('verified_email') === '1';

        let initialStepIndex = 0;
        let verified = isVerified;

        // If verified, go to features step
        if (isVerified) {
            const featuresIndex = steps.findIndex(step => step.id === 'features');
            if (featuresIndex !== -1) {
                initialStepIndex = featuresIndex;
                // Remove the parameter from URL
                urlParams.delete('verified_email');
                const newUrl = window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '');
                window.history.replaceState({}, '', newUrl);
            }
        } else if (!upgradedFromFree && (sslEnabled || (networkwide && networkActivationStatus === 'completed'))) {
            initialStepIndex = 1;
        }

        // Set all state at once to prevent multiple rerenders
        set({
            steps,
            currentStepIndex: initialStepIndex,
            currentStep: steps[initialStepIndex],
            networkActivationStatus,
            certificateValid,
            networkProgress,
            networkwide,
            overrideSSL,
            sslEnabled,
            dataLoaded: true,
            error,
            emailVerified: verified
        });

        if (networkActivationStatus === 'completed') {
            set({networkProgress: 100});
        }
    },
    refreshSSLStatus: (e) => {
        e.preventDefault();
        set( {processing: true} );
        set(
            produce((state) => {
                const stepIndex = state.steps.findIndex(step => {
                    return step.id==='activate_ssl';
                });
                const step = state.steps[stepIndex];
                step.items.forEach(function(item, j){
                    if (item.status==='error') {
                        step.items[j].status = 'processing';
                        step.items[j].title = __("Re-checking SSL certificate, please wait...","really-simple-ssl");
                    }
                });
                state.steps[stepIndex] = step;
            })
        )

        setTimeout(async function () {
            const {
                steps,
                certificateValid,
                error,
            } = await retrieveSteps(true);
            set({
                steps: steps,
                certificateValid: certificateValid,
                processing: false,
                error: error,
            });
        }, 1000) //add a delay, otherwise it's so fast the user may not trust it.
    },
    activateSSLNetworkWide: () => {
        let progress = get().networkProgress;
        if (typeof progress !== 'undefined') {
            get().setFooterStatus(__("%d% of subsites activated.").replace('%d', progress));
        }
        if (get().networkProgress>=100) {
            set({
                sslEnabled: true,
                networkActivationStatus:'completed'
            });
            return;
        }
        set( () => ({processing: true}));
        rsssl_api.runTest('activate_ssl_networkwide' ).then( ( response ) => {
            if (response.success) {
                set({
                    networkProgress: response.progress,
                    processing:false,
                });
                get().setFooterStatus(__("%d% of subsites activated.").replace('%d', response.progress));

                if (response.progress>=100) {
                    get().setFooterStatus('');
                    set({
                        sslEnabled: true,
                        networkActivationStatus:'completed'
                    });
                }
            }
        });
    }
}));

const retrieveSteps = (forceRefresh) => {
    let data={};
    data.forceRefresh = forceRefresh;
    return rsssl_api.doAction('onboarding_data', data).then( ( response ) => {
        let steps = response.steps;
        let sslEnabled=  response.ssl_enabled;
        let networkActivationStatus=  response.network_activation_status;
        let certificateValid = response.certificate_valid;
        let networkProgress = response.network_progress;
        let networkwide = response.networkwide;
        let overrideSSL = response.ssl_detection_overridden;
        let error = response.error;
        let upgradedFromFree = response.rsssl_upgraded_from_free;
        return {steps, networkActivationStatus, certificateValid, networkProgress, networkwide, overrideSSL, error, sslEnabled, upgradedFromFree};
    });
}

const processAction = async (action, id) => {
    let data={};
    data.id = id;
    return await rsssl_api.doAction(action, data).then( async ( response ) => {
        if ( response.success ){
            return response.next_action;
        } else {
            return 'failed';
        }
    }).catch(error => {
        return 'failed';
    });
}

export default useOnboardingData;