import $ from "jquery";
import { action, flow, observable, runInAction } from "mobx";
import wp from "wp";

import type { FreemiumOptions } from "@devowl-wp/freemium";
import { isRatable } from "@devowl-wp/real-utils";
import { BaseOptions } from "@devowl-wp/utils";

import { request } from "../utils/request.js";
import { locationRestOptionsPostTypePatch } from "../wp-api/optionsPostType.patch.js";

import type { RootStore } from "./stores.js";
import type {
    ParamsRouteOptionsPostTypePatch,
    RequestRouteOptionsPostTypePatch,
    ResponseRouteOptionsPostTypePatch,
} from "../wp-api/optionsPostType.patch.js";

type CancellablePromise<R> = ReturnType<ReturnType<typeof flow<R, any>>>;

class OptionStore extends BaseOptions {
    @observable
    public busySettings = false;

    // Implement "others" property in your Assets.php;
    @observable
    public others: {
        showLicenseFormImmediate: boolean;
        isDevLicense: boolean;
        licenseActivationLink: string;
        tableCheckboxName: string;
        installPluginNonce: string;
        pluginRcpo: {
            active: boolean;
            installed: boolean;
            installUrl: string;
            activateUrl: string;
        };
        pluginCptUi: OptionStore["others"]["pluginRcpo"] & {
            manageTaxonomiesUrl: string;
        };
        postTypes: Record<
            string,
            { link: string; label: string; available: boolean; active: boolean; fastMode: boolean }
        >;
        canManageOptions: boolean;
        isAvailable: boolean;
        screenSettings: {
            isActive: boolean;
            isFastMode: boolean;
        };
        blogId: number;
        rcpo: boolean;
        simplePageOrdering: boolean;
        simplePageOrderingLink: string;
        editOrderBy: string;
        editOrder: string;
        typenow: string;
        taxnow: string;
        allPostCnt: number;
        taxos: {
            [key: string]: string;
        };
        sortableTaxos: Record<string, boolean>;
        pluginsUrl: string;
    } & FreemiumOptions;

    public readonly pureSlug: ReturnType<typeof BaseOptions.getPureSlug>;

    public readonly pureSlugCamelCased: ReturnType<typeof BaseOptions.getPureSlug>;

    public readonly rootStore: RootStore;

    public get isRatable() {
        return isRatable(this.slug);
    }

    public constructor(rootStore: RootStore) {
        super();
        this.rootStore = rootStore;
        this.pureSlug = BaseOptions.getPureSlug(process.env.slug);
        this.pureSlugCamelCased = BaseOptions.getPureSlug(process.env.slug, true);

        // Use the localized WP object to fill this object values.
        runInAction(() => Object.assign(this, (window as any)[this.pureSlugCamelCased]));
    }

    public updatePostTypeOptions: (
        post_type: string,
        update: RequestRouteOptionsPostTypePatch,
    ) => Promise<ResponseRouteOptionsPostTypePatch> = flow(function* (
        this: OptionStore,
        post_type,
        { active, fastMode },
    ) {
        this.busySettings = true;
        try {
            const result: ResponseRouteOptionsPostTypePatch = yield request<
                RequestRouteOptionsPostTypePatch,
                ParamsRouteOptionsPostTypePatch,
                ResponseRouteOptionsPostTypePatch
            >({
                location: locationRestOptionsPostTypePatch,
                params: {
                    post_type,
                },
                request: {
                    ...(active === undefined
                        ? {}
                        : {
                              active: active,
                          }),
                    ...(fastMode === undefined
                        ? {}
                        : {
                              fastMode: fastMode,
                          }),
                },
            });

            // Update in our store
            if (active !== undefined) {
                this.others.postTypes[post_type].active = active;
            }

            if (fastMode !== undefined) {
                this.others.postTypes[post_type].fastMode = fastMode;
            }

            return result;
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busySettings = false;
        }
    });

    public installAndActivateCustomPostTypeUI: () => CancellablePromise<void> = flow(function* (this: OptionStore) {
        this.busySettings = true;

        const {
            others: { pluginCptUi, installPluginNonce },
        } = this;
        const { installed, installUrl, activateUrl } = pluginCptUi;
        const ajaxSend: (options: any) => Promise<void> = wp?.ajax?.send; // wp-utils.js is not loaded on frontend, so it is optional

        // Try to install plugin via AJAX request
        if (installed) {
            // Immediate activate the plugin
            try {
                yield $.get(activateUrl).promise();
                pluginCptUi.active = true;
            } catch (e) {
                // Fallback to usual redirect
                window.location.href = activateUrl;
            }
        } else {
            if (ajaxSend) {
                try {
                    yield ajaxSend({
                        data: {
                            action: "install-plugin",
                            slug: "custom-post-type-ui",
                            _ajax_nonce: installPluginNonce,
                        },
                    });

                    pluginCptUi.installed = true;

                    yield this.installAndActivateCustomPostTypeUI();
                } catch (e) {
                    // Fallback to install url (this can happen if FTP is configured to install plugin)
                    window.location.href = installUrl;
                }
            } else {
                window.location.href = installUrl;
            }
        }
    });

    public installAndActivateRealCustomPostOrder: () => CancellablePromise<void> = flow(function* (this: OptionStore) {
        this.busySettings = true;

        const {
            others: { pluginRcpo, installPluginNonce },
        } = this;
        const { installed, installUrl, activateUrl } = pluginRcpo;
        const ajaxSend: (options: any) => Promise<void> = wp?.ajax?.send; // wp-utils.js is not loaded on frontend, so it is optional

        // Try to install plugin via AJAX request
        if (installed) {
            // Immediate activate the plugin
            try {
                yield $.get(activateUrl).promise();
                pluginRcpo.active = true;
            } catch (e) {
                // Fallback to usual redirect
                window.location.href = activateUrl;
            }
        } else {
            if (ajaxSend) {
                try {
                    yield ajaxSend({
                        data: {
                            action: "install-plugin",
                            slug: "real-custom-post-order",
                            _ajax_nonce: installPluginNonce,
                        },
                    });

                    pluginRcpo.installed = true;

                    yield this.installAndActivateCustomPostTypeUI();
                } catch (e) {
                    // Fallback to install url (this can happen if FTP is configured to install plugin)
                    window.location.href = installUrl;
                }
            } else {
                window.location.href = installUrl;
            }
        }
    });

    @action
    public setTaxnow(taxnow: string) {
        this.others.taxnow = taxnow;
    }

    @action
    public setShowLicenseFormImmediate(state: boolean) {
        this.others.showLicenseFormImmediate = state;
    }
}

export { OptionStore };
