export class OpinionInfluenceProviderRegistry {
    static #providers = new Map();

    static register(definition = {}) {
        const id = String(definition.id || "").trim();
        if (!id || typeof definition.resolve !== "function") {
            throw new Error("Opinion influence providers require an id and resolve function.");
        }
        this.#providers.set(id, {
            id,
            moduleId: String(definition.moduleId || "augur-nexus").trim() || "augur-nexus",
            label: String(definition.label || id).trim() || id,
            sort: Number(definition.sort || 100),
            supports: typeof definition.supports === "function" ? definition.supports : () => true,
            resolve: definition.resolve
        });
        Hooks.callAll("augurNexusOpinionInfluenceProvidersChanged", { reason: "register", providerId: id });
        return id;
    }

    static unregister(providerId = "") {
        const id = String(providerId || "").trim();
        const removed = this.#providers.delete(id);
        if (removed) Hooks.callAll("augurNexusOpinionInfluenceProvidersChanged", { reason: "unregister", providerId: id });
        return removed;
    }

    static resolve(context = {}) {
        const groups = [];
        const providers = [...this.#providers.values()]
            .sort((a, b) => a.sort - b.sort || a.id.localeCompare(b.id));
        for (const provider of providers) {
            try {
                if (!provider.supports(context)) continue;
                const result = provider.resolve(context);
                const group = this.#normalizeResult(result, provider);
                if (group) groups.push(group);
            } catch (error) {
                console.warn(`Augur: Nexus | Opinion influence provider ${provider.id} failed.`, error);
            }
        }
        return groups;
    }

    static #normalizeResult(result, provider) {
        if (!result || typeof result !== "object") return null;
        const value = Number(result.value || 0);
        if (!Number.isFinite(value)) return null;
        const details = (Array.isArray(result.details) ? result.details : [])
            .map(detail => ({
                id: String(detail?.id || "").trim(),
                label: String(detail?.label || "").trim(),
                value: Math.round(Number(detail?.value || 0))
            }))
            .filter(detail => detail.id && detail.label && detail.value);
        if (!value && !details.length) return null;
        return {
            id: String(result.id || provider.id),
            providerId: provider.id,
            moduleId: provider.moduleId,
            label: String(result.label || provider.label),
            value: Math.round(value),
            details
        };
    }
}
