import { GVL, TCModel, TCString } from "@iabtechlabtcf/core";

import type { Tcf, TcfMetadata } from "../types/tcf.js";

/**
 * Restore e.g. a history entry to a valid `GVL` and `TCModel` instance.
 * Returns `undefined` if no TCF vendor-list.json object is given.
 */
function createTcfModel({ tcf, tcfMetadata, tcfString }: { tcf: Tcf; tcfMetadata: TcfMetadata; tcfString: string }) {
    if (!tcf || !tcfMetadata || !Object.keys(tcf.vendors).length) {
        return undefined;
    }

    /**
     * As I wrote in this Github [ticket](https://github.com/InteractiveAdvertisingBureau/iabtcf-es/issues/341), TCF tries to
     * fetch the translations for declarations (stacks, purposes, features, ...) when it is not in the `GVL.LANGUAGES_CACHE`.
     * In our case, we already localize the cookie banner with the correct and translated texts, but `GVL.prototype.changeLanguage` still
     * gets called when the consent language is other than `EN`.
     *
     * Unfortunately, the ticket got simply closed without any solution. Instead of filling `GVL.LANGUAGES_CACHE` manually, we simply
     * override the `fetchJson` method and check if the URL is broken as our `GVL` also does not expose a `baseUrl`.
     *
     * @see https://github.com/InteractiveAdvertisingBureau/iabtcf-es/blob/564a453ab408c826951994e8e547f1bf90043f5d/modules/core/src/GVL.ts#L419-L427
     * @see https://github.com/InteractiveAdvertisingBureau/iabtcf-es/blob/564a453ab408c826951994e8e547f1bf90043f5d/modules/core/src/GVL.ts#L380-L392
     */
    const originalFetchJson = (GVL.prototype as any).fetchJson;
    (GVL.prototype as any).fetchJson = function fetchJson(url: string) {
        if (!url.startsWith("undefined")) {
            // eslint-disable-next-line prefer-rest-params
            return originalFetchJson.apply(this, arguments);
        }
    };

    const gvl = new GVL(Object.assign({}, tcf, tcfMetadata) as any);

    // See https://git.io/Jmjqs
    (gvl as any).lang_ = tcfMetadata.language;

    const model = new TCModel(gvl);

    const { publisherCc } = tcfMetadata;
    if (publisherCc) {
        model.publisherCountryCode = publisherCc;
    }

    if (tcfString) {
        TCString.decode(tcfString, model);
    } else {
        model.unsetAll();
    }

    model.vendorsDisclosed.set(Object.keys(tcf.vendors).map(Number));

    return { gvl, model, original: tcf, metadata: tcfMetadata };
}

export { createTcfModel };
