import $ from "jquery";
import { action, computed, observable, reaction, runInAction } from "mobx";

import type {
    TcfVendorConfigurationMeta,
    TcfVendorConfigurationRestrictivePurposes,
} from "@devowl-wp/cookie-consent-web-client";
import type { WpRestEndpointWithMultilingualSection } from "@devowl-wp/multilingual";
import type { PostStatus } from "@devowl-wp/utils";
import { AbstractPost, ClientModel } from "@devowl-wp/utils";

import { TcfVendor } from "./tcfVendor.js";
import { request } from "../utils/request.js";

import type { TcfVendorConfigurationCollection } from "./tcfVendorConfigurationCollection.js";

@ClientModel.annotate({
    keyId: "id",
    namespace: "wp/v2",
    request,
    create: {
        path: "/rcb-tcf-vendor-conf",
    },
    patch: {
        path: "/rcb-tcf-vendor-conf/:id",
    },
    delete: {
        path: "/rcb-tcf-vendor-conf/:id",
    },
})
class TcfVendorConfigurationModel extends AbstractPost<
    TcfVendorConfigurationCollection,
    Omit<
        TcfVendorConfigurationMeta,
        "restrictivePurposes" | "dataProcessingInCountries" | "dataProcessingInCountriesSpecialTreatments"
    > & {
        // Saved as serialized JSON
        restrictivePurposes: string;
        // Saved as serialized JSON
        dataProcessingInCountries: string;
        // Saved as serialized JSON
        dataProcessingInCountriesSpecialTreatments: string;
    },
    {
        vendor: TcfVendor["data"];
        blocker: false | number;
    } & WpRestEndpointWithMultilingualSection
> {
    @observable
    public vendorModel?: TcfVendor;

    @computed
    public get restrictivePurposes(): TcfVendorConfigurationRestrictivePurposes {
        const result = JSON.parse(this.data.meta.restrictivePurposes);

        // Merge with original vendor purposes so all are listed
        return $.extend(true, {}, this.vendorModel?.restrictivePurposes || {}, result);
    }

    @computed
    public get dataProcessingInCountries(): TcfVendorConfigurationMeta["dataProcessingInCountries"] {
        return JSON.parse(this.data.meta.dataProcessingInCountries || "[]");
    }

    @computed
    public get dataProcessingInCountriesSpecialTreatments(): TcfVendorConfigurationMeta["dataProcessingInCountriesSpecialTreatments"] {
        return JSON.parse(this.data.meta.dataProcessingInCountriesSpecialTreatments || "[]");
    }

    public constructor(
        collection: TcfVendorConfigurationModel["collection"],
        data: Partial<TcfVendorConfigurationModel["data"]> = {},
    ) {
        super(collection, data);

        reaction(
            () => this.data.vendor,
            (vendor) =>
                runInAction(() => {
                    if (vendor) {
                        const { vendors } = this.collection.store;
                        const vendorId = vendor.id.toString();
                        let existing = vendors.get(vendorId);
                        if (!existing) {
                            existing = new TcfVendor(vendor, this.collection.store);
                            vendors.set(vendorId, existing);
                        }
                        this.vendorModel = existing;
                    }
                }),
            { fireImmediately: true },
        );

        // Automatically set the vendor model (e.g. newly saved configuration)
        reaction(
            () => this.data.meta?.vendorId,
            (vendorId) => {
                if (vendorId) {
                    this.vendorModel = this.collection.store.vendors.get(vendorId.toString());
                }
            },
            {
                fireImmediately: true,
            },
        );
    }

    @action
    public setStatus(status: PostStatus) {
        this.data.status = status;
    }

    @action
    public setMeta(meta: TcfVendorConfigurationModel["data"]["meta"]) {
        this.data.meta = meta;
    }

    public transformDataForPatch(): any {
        const data = super.transformDataForPatch();
        return {
            status: data.status,
            meta: data.meta,
        };
    }

    public afterPatch() {
        this.collection.store.rootStore.optionStore.fetchCurrentRevision();
    }

    public afterDelete() {
        this.collection.store.rootStore.optionStore.fetchCurrentRevision();
    }

    public afterPersist() {
        this.collection.store.rootStore.optionStore.fetchCurrentRevision();
    }
}

export { TcfVendorConfigurationModel };
