import { action, computed, flow, observable, runInAction, set } from "mobx";

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 { locationRestSettingsVerifyPost } from "../wp-api/settings-verify.post.js";
import { locationRestSettingsPut } from "../wp-api/settings.post.js";

import type { RootStore } from "./stores.js";
import type {
    ParamsRestSettingsVerifyPost,
    RequestRestSettingsVerifyPost,
    ResponseRestSettingsVerifyPost,
} from "../wp-api/settings-verify.post.js";
import type {
    ParamsRestSettingsPut,
    RequestRestSettingsPut,
    ResponseRestSettingsPut,
} from "../wp-api/settings.post.js";

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

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

    // Implement "others" property in your Assets.php;
    @observable
    public others: {
        showLicenseFormImmediate: boolean;
        isDevLicense: boolean;
        licenseActivationLink: string;
        canManageOptions: boolean;
        thumbnailFolder: string;
        thumbnailFilename: string;
        chunkSize: number;
        pluginsUrl: string;
        implementations: string[];
    } & FreemiumOptions;

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

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

    public readonly rootStore: RootStore;

    @computed public get unimplemented() {
        return this.others.implementations.filter((i: string) => i.indexOf("DevOwl") === -1);
    }

    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 update: (thumbnailFolder: string, thumbnailFilename: string, chunkSize: number) => CancellablePromise<void> =
        flow(function* (this: OptionStore, thumbnailFolder, thumbnailFilename, chunkSize) {
            this.updateBusy = true;

            try {
                const requestData = {
                    thumbnailFolder,
                    thumbnailFilename,
                    chunkSize,
                };
                yield request<RequestRestSettingsPut, ParamsRestSettingsPut, ResponseRestSettingsPut>({
                    location: locationRestSettingsPut,
                    request: requestData,
                });

                set(this.others, requestData);
            } catch (e) {
                console.log(e);
                throw e;
            } finally {
                this.updateBusy = false;
            }
        });

    public verify: (
        thumbnailFolder: string,
        thumbnailFilename: string,
    ) => CancellablePromise<ResponseRestSettingsVerifyPost> = flow(function* (
        this: OptionStore,
        thumbnailFolder,
        thumbnailFilename,
    ) {
        this.updateBusy = true;

        try {
            const requestData = {
                thumbnailFolder,
                thumbnailFilename,
            };
            const result: ResponseRestSettingsVerifyPost = yield request<
                RequestRestSettingsVerifyPost,
                ParamsRestSettingsVerifyPost,
                ResponseRestSettingsVerifyPost
            >({
                location: locationRestSettingsVerifyPost,
                request: requestData,
            });
            return result;
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.updateBusy = false;
        }
    });

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

export { OptionStore };
