export class LocationEditorSectionRegistry {
    static #sections = new Map();

    static register(definition = {}) {
        const id = String(definition.id || "").trim();
        const moduleId = String(definition.moduleId || "").trim();
        if (!id || !moduleId || typeof definition.render !== "function") {
            throw new Error("Location editor sections require id, moduleId, and render.");
        }

        const normalized = {
            id,
            moduleId,
            order: Number.isFinite(Number(definition.order)) ? Number(definition.order) : 100,
            isAvailable: typeof definition.isAvailable === "function" ? definition.isAvailable : null,
            render: definition.render,
            transformPatch: typeof definition.transformPatch === "function" ? definition.transformPatch : null
        };
        this.#sections.set(id, normalized);
        return { id, moduleId, order: normalized.order };
    }

    static async renderFor(entity = {}, context = {}) {
        const sections = this.#listAvailable(entity, context);
        const rendered = await Promise.all(sections.map(async section => ({
            id: section.id,
            moduleId: section.moduleId,
            html: String(await section.render({ entity: foundry.utils.deepClone(entity), context }) || "")
        })));
        return rendered.filter(section => section.html);
    }

    static async transformPatch(entity = {}, formData, patch = {}, context = {}) {
        let nextPatch = foundry.utils.deepClone(patch || {});
        let moduleId = "";

        for (const section of this.#listAvailable(entity, context)) {
            if (!section.transformPatch) continue;
            const result = await section.transformPatch({
                entity: foundry.utils.deepClone(entity),
                formData,
                patch: foundry.utils.deepClone(nextPatch),
                context
            });
            if (!result) continue;

            const transformedPatch = result.patch && typeof result.patch === "object" ? result.patch : result;
            if (!transformedPatch || typeof transformedPatch !== "object" || Array.isArray(transformedPatch)) continue;
            nextPatch = foundry.utils.deepClone(transformedPatch);

            const resultModuleId = String(result.moduleId || "").trim();
            if (resultModuleId && moduleId && moduleId !== resultModuleId) {
                throw new Error("A location edit cannot update module data owned by multiple modules at once.");
            }
            if (resultModuleId) moduleId = resultModuleId;
        }

        return { patch: nextPatch, moduleId };
    }

    static #listAvailable(entity, context) {
        return [...this.#sections.values()]
            .filter(section => !section.isAvailable || section.isAvailable({ entity, context }) !== false)
            .sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
    }
}
