import { getCampaignEntityPlacementsOnScene } from "../../../api/markers.js";
import { getLocation, getLocations } from "../../../api/locations.js";

const MODULE_ID = "augur-nexus";

export class TradeRegionSceneService {
    static #entityIdsBySceneId = new Map();
    static #hooksRegistered = false;

    static registerHooks() {
        if (this.#hooksRegistered) return;
        this.#hooksRegistered = true;
        const invalidate = () => this.invalidate();
        for (const hook of ["createTile", "updateTile", "deleteTile", "createScene", "deleteScene"]) Hooks.on(hook, invalidate);
    }

    static invalidate() {
        this.#entityIdsBySceneId.clear();
    }

    static getLocationSceneIds(idOrEntity) {
        const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity;
        if (!entity?.id) return [];
        return (game.scenes?.contents || [])
            .filter(scene => this.#getSceneEntityIds(scene.id).has(entity.id))
            .map(scene => scene.id);
    }

    static resolveSceneId(idOrEntity, { sceneId = "" } = {}) {
        const requestedSceneId = String(sceneId || "").trim();
        if (requestedSceneId && this.isLocationOnScene(idOrEntity, requestedSceneId)) return requestedSceneId;
        const activeSceneId = String(globalThis.canvas?.scene?.id || "");
        if (activeSceneId && this.isLocationOnScene(idOrEntity, activeSceneId)) return activeSceneId;
        const sceneIds = this.getLocationSceneIds(idOrEntity);
        return sceneIds.length === 1 ? sceneIds[0] : "";
    }

    static async chooseSceneId(idOrEntity, { sceneId = "" } = {}) {
        const resolved = this.resolveSceneId(idOrEntity, { sceneId });
        if (resolved) return resolved;
        const sceneIds = this.getLocationSceneIds(idOrEntity);
        if (!sceneIds.length) return "";
        const scenes = sceneIds.map(id => game.scenes.get(id)).filter(Boolean)
            .sort((left, right) => left.name.localeCompare(right.name));
        if (scenes.length === 1) return scenes[0].id;
        const options = scenes.map(scene => `<option value="${foundry.utils.escapeHTML(scene.id)}">${foundry.utils.escapeHTML(scene.name)}</option>`).join("");
        return (await foundry.applications.api.DialogV2.prompt({
            window: { title: "Choose Trade Region" },
            content: `<label>Region <select name="sceneId" autofocus>${options}</select></label><p>This Location appears on more than one Scene. Choose which regional market to inspect.</p>`,
            rejectClose: false,
            ok: {
                label: "Open Region",
                icon: "fas fa-map",
                callback: (_event, button) => String(button.form.elements.sceneId?.value || "")
            }
        })) || "";
    }

    static getRegionLocations(sceneId, { locations = null } = {}) {
        const normalizedSceneId = String(sceneId || "").trim();
        const source = Array.isArray(locations) ? locations : getLocations();
        if (!normalizedSceneId) return [];
        const entityIds = this.#getSceneEntityIds(normalizedSceneId);
        return source.filter(entity => entityIds.has(entity.id));
    }

    static isLocationOnScene(idOrEntity, sceneId) {
        const entity = typeof idOrEntity === "string" ? getLocation(idOrEntity) : idOrEntity;
        return !!entity?.id && this.#getSceneEntityIds(String(sceneId || "")).has(entity.id);
    }

    static getScene(sceneId) {
        return game.scenes?.get(String(sceneId || "")) || null;
    }

    static getSceneName(sceneId) {
        return this.getScene(sceneId)?.name || "Unplaced Location";
    }

    static getLocationTypeId(entity = {}) {
        const stored = String(entity.moduleData?.[MODULE_ID]?.trade?.locationTypeId || entity.generation?.templateId || "").trim().toLocaleLowerCase();
        if (stored) return stored;
        return String(entity.profile?.type || entity.profile?.kindId || "").trim().toLocaleLowerCase();
    }

    static isTradingCenter(entity = {}) {
        const configured = entity.moduleData?.[MODULE_ID]?.trade?.tradingCenterEligible;
        if (typeof configured === "boolean") return configured;
        return entity?.profile?.kindId === "settlement";
    }

    static #getSceneEntityIds(sceneId) {
        const normalizedSceneId = String(sceneId || "");
        if (!normalizedSceneId) return new Set();
        if (this.#entityIdsBySceneId.has(normalizedSceneId)) return this.#entityIdsBySceneId.get(normalizedSceneId);
        const entityIds = new Set(getCampaignEntityPlacementsOnScene(normalizedSceneId, { entityType: "location" })
            .map(placement => String(placement.target?.entityId || ""))
            .filter(Boolean));
        this.#entityIdsBySceneId.set(normalizedSceneId, entityIds);
        return entityIds;
    }
}
