import { SiteScenePicker } from "../../site/applications/SiteScenePicker.js";
import { NexusPlayerSceneAccess } from "../../nexus/services/NexusPlayerSceneAccess.js";
import { LocationEntityStore } from "./LocationEntityStore.js";
import { LocationSceneService } from "./LocationSceneService.js";

export class LocationSceneWorkflow {
    static getControlModel(locationId) {
        const scene = LocationSceneService.getPrimaryScene(locationId);
        return {
            hasScene: !!scene,
            canOpen: !!scene && NexusPlayerSceneAccess.canUserViewScene(scene),
            label: "Open Scene",
            icon: "fas fa-map",
            title: scene ? `Open ${scene.name}` : ""
        };
    }

    static getMenuItems(locationId, { onChanged = null } = {}) {
        if (!game.user?.isGM) return [];
        const scene = LocationSceneService.getPrimaryScene(locationId);
        if (!scene) {
            return [
                {
                    id: "create-location-scene",
                    label: "Create Scene",
                    status: "Creates and opens an empty map",
                    icon: "fas fa-map-location-dot",
                    onSelect: () => this.create(locationId, { onChanged })
                },
                {
                    id: "link-location-scene",
                    label: "Link Existing Scene",
                    icon: "fas fa-link",
                    onSelect: () => this.selectExisting(locationId, { onChanged })
                }
            ];
        }

        return [
            {
                id: "open-location-scene",
                label: "Open Scene",
                status: scene.name,
                icon: "fas fa-map",
                onSelect: () => this.open(locationId)
            },
            {
                id: "replace-location-scene",
                label: "Replace Linked Scene",
                status: "Current Scene is kept",
                icon: "fas fa-link",
                onSelect: () => this.selectExisting(locationId, { replace: true, onChanged })
            },
            {
                id: "detach-location-scene",
                label: "Detach Scene",
                status: "Scene is kept",
                icon: "fas fa-link-slash",
                onSelect: () => this.detach(locationId, { onChanged })
            }
        ];
    }

    static async open(locationId) {
        const scene = LocationSceneService.getPrimaryScene(locationId);
        if (!scene) {
            ui.notifications.warn("This Location does not have a Scene.");
            return false;
        }
        if (!NexusPlayerSceneAccess.canUserViewScene(scene)) {
            ui.notifications.warn("This Scene is not currently available to view.");
            return false;
        }
        try {
            return await LocationSceneService.open(locationId);
        } catch (error) {
            this.#reportError(error, "The Location Scene could not be opened.");
            return false;
        }
    }

    static async create(locationId, { onChanged = null } = {}) {
        if (!game.user?.isGM) return false;
        try {
            await LocationSceneService.create(locationId);
            await onChanged?.();
            return true;
        } catch (error) {
            this.#reportError(error, "The Location Scene could not be created.");
            return false;
        }
    }

    static selectExisting(locationId, { replace = false, onChanged = null } = {}) {
        if (!game.user?.isGM) return null;
        const location = LocationEntityStore.getLocation(locationId);
        if (!location) return null;

        const parent = location.hierarchy?.parent || null;
        const containingSceneId = parent?.kind === "scene"
            ? parent.sceneId
            : parent?.kind === "site" ? parent.parentSceneId : null;
        const currentScene = LocationSceneService.getPrimaryScene(locationId);

        const picker = new SiteScenePicker(currentScene?.id || null, async (sceneId, { descendantCount = 0 } = {}) => {
            const scene = game.scenes.get(sceneId);
            if (descendantCount > 0) {
                const countLabel = `${descendantCount} ${descendantCount === 1 ? "descendant" : "descendants"}`;
                const confirmed = await foundry.applications.api.DialogV2.confirm({
                    window: { title: "Adopt Scene Branch" },
                    content: `<p>Use <strong>${foundry.utils.escapeHTML(scene?.name || "this Scene")}</strong> as the map for <strong>${foundry.utils.escapeHTML(location.display?.name || "this Location")}</strong>?</p><p>This Scene currently has ${countLabel}. The entire branch will appear beneath the Location.</p><p class="notification warning">Detaching preserves the Scene branch. Deleting the Location may delete its owned Scene branch.</p>`,
                    modal: true,
                    rejectClose: false,
                    yes: { label: "Adopt Branch" },
                    no: { label: "Cancel" }
                });
                if (!confirmed) return false;
            }

            try {
                if (replace && currentScene) await LocationSceneService.replace(locationId, sceneId);
                else await LocationSceneService.link(locationId, sceneId);
                await onChanged?.();
                return true;
            } catch (error) {
                this.#reportError(error, "The selected Scene could not be linked.");
                return false;
            }
        }, {
            mode: "location",
            locationId,
            excludedSceneIds: containingSceneId ? [containingSceneId] : []
        });
        picker.render(true);
        return picker;
    }

    static async detach(locationId, { onChanged = null } = {}) {
        if (!game.user?.isGM) return false;
        const location = LocationEntityStore.getLocation(locationId);
        const scene = LocationSceneService.getPrimaryScene(locationId);
        if (!location || !scene) return false;

        const confirmed = await foundry.applications.api.DialogV2.confirm({
            window: { title: "Detach Location Scene" },
            content: `<p>Detach <strong>${foundry.utils.escapeHTML(scene.name)}</strong> from <strong>${foundry.utils.escapeHTML(location.display?.name || "this Location")}</strong>?</p><p>The Scene and its descendants will be kept.</p>`,
            modal: true,
            rejectClose: false,
            yes: { label: "Detach Scene" },
            no: { label: "Cancel" }
        });
        if (!confirmed) return false;

        try {
            await LocationSceneService.detach(locationId);
            await onChanged?.();
            return true;
        } catch (error) {
            this.#reportError(error, "The Location Scene could not be detached.");
            return false;
        }
    }

    static #reportError(error, fallback) {
        console.error("Augur Nexus | Location Scene workflow failed", error);
        ui.notifications.error(error?.message || fallback);
    }
}
