import { isPurposeEnabledForVendor } from "./isPurposeEnabledForVendor.js";

import type { Declarations, GVL, IntMap, TCModel, Vendor } from "@iabtechlabtcf/core";

function findUsedVendorsForDeclaration(
    gvl: GVL,
    model: TCModel,
    id: number,
    declaration: keyof Omit<Declarations, "stacks">,
    isLegInt: boolean,
    sorted = false,
) {
    let vendors: IntMap<Vendor> = {};

    // Directly access the GVL methods based on declaration
    // @see https://www.npmjs.com/package/@iabtechlabtcf/core#get-only-vendors-with-a-specific-feature-or-purpose-under-legal-basis
    switch (declaration) {
        case "features":
            vendors = gvl.getVendorsWithFeature(id);
            break;
        case "specialFeatures":
            vendors = gvl.getVendorsWithSpecialFeature(id);
            break;
        case "specialPurposes":
            vendors = gvl.getVendorsWithSpecialPurpose(id);
            break;
        case "purposes":
            vendors = isLegInt ? gvl.getVendorsWithLegIntPurpose(id) : gvl.getVendorsWithConsentPurpose(id);
            break;
        case "dataCategories":
            // This method is currently not implemented in the GVL object, so we need to implement hits ourself
            vendors = Object.values(gvl.vendors).reduce((acc, vendor) => {
                if (vendor.dataDeclaration?.includes(id)) {
                    acc[vendor.id] = vendor;
                }
                return acc;
            }, {});
            break;
        default:
            vendors = gvl.getVendorsWithConsentPurpose(id);
    }

    // Combine with flexible purposes if applicable.
    if (declaration === "purposes") {
        vendors = {
            ...vendors,
            ...gvl.getVendorsWithFlexiblePurpose(id),
        };
    }

    // Filter and sort efficiently.
    const result = Object.values(vendors).filter(
        (vendor) => declaration !== "purposes" || isPurposeEnabledForVendor(model, id, isLegInt, vendor),
    );

    if (sorted) {
        result.sort((a, b) => a.name.localeCompare(b.name));
    }

    return result;
}

export { findUsedVendorsForDeclaration };
