import { computed, flow } from "mobx";

import { AbstractCategoryCollection, ClientCollection, RouteHttpVerb } from "@devowl-wp/utils";

import { CookieGroupModel } from "./cookieGroupModel.js";
import { request } from "../utils/request.js";
import { locationRestCookieGroupOrderPut } from "../wp-api/cookieGroupOrder.put.js";

import type { CookieStore } from "../store/cookie.js";
import type {
    ParamsRouteCookieGroupOrderPut,
    RequestRouteCookieGroupOrderPut,
    ResponseRouteCookieGroupOrderPut,
} from "../wp-api/cookieGroupOrder.put.js";

@ClientCollection.annotate({
    path: "/rcb-cookie-group",
    singlePath: "/rcb-cookie-group/:id",
    namespace: "wp/v2",
    methods: [RouteHttpVerb.GET],
    request,
})
class CookieGroupCollection extends AbstractCategoryCollection<CookieGroupModel> {
    public readonly store: CookieStore;

    @computed
    public get sortedGroups() {
        const result = Array.from(this.entries.values());
        result.sort((a, b) => {
            if (a.data.meta.order < b.data.meta.order) {
                return -1;
            } else if (a.data.meta.order > b.data.meta.order) {
                return 1;
            } else {
                return 0;
            }
        });
        return result;
    }

    public constructor(store: CookieStore) {
        super();
        this.store = store;
    }

    public orderCookieGroups: (ids: number[]) => Promise<void> = flow(function* (this: CookieGroupCollection, ids) {
        this.busy = true;
        try {
            yield request<
                RequestRouteCookieGroupOrderPut,
                ParamsRouteCookieGroupOrderPut,
                ResponseRouteCookieGroupOrderPut
            >({
                location: locationRestCookieGroupOrderPut,
                request: {
                    ids,
                },
            });

            // Apply the order to existing cached models instead of fetching again
            let i = 0;
            for (const id of ids) {
                const group = this.entries.get(id);
                group.setOrder(i);
                i++;
            }
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busy = false;
        }
    });

    public instance(response: CookieGroupModel["data"]): CookieGroupModel {
        return new CookieGroupModel(this).fromResponse(response);
    }
}

export { CookieGroupCollection };
