import { ConnectionTargetResolver } from "../../connections/services/ConnectionTargetResolver.js";
import { RegionChronicleService } from "../services/RegionChronicleService.js";
import { RegionChronicleViewModel } from "../services/RegionChronicleViewModel.js";
import { RegionPopulationRunStore } from "../services/RegionPopulationRunStore.js";

const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
const instances = new Map();

export class RegionChronicleApplication extends HandlebarsApplicationMixin(ApplicationV2) {
    #sceneId;
    #filters = { search: "", faction: "", actor: "", location: "", type: "", scope: "regional", yearFrom: "", yearTo: "" };
    #searchTimer = null;
    #chronicleHookId = null;
    #entityHookId = null;
    #canvasHookId = null;

    static DEFAULT_OPTIONS = {
        id: "augur-region-chronicle",
        tag: "div",
        classes: ["augur-nexus", "augur-theme-fantasy", "augur-region-chronicle-app"],
        window: {
            title: "Regional Chronicle",
            icon: "fas fa-book-open",
            resizable: true,
            minimizable: true
        },
        position: { width: 1130, height: 780, left: 110, top: 60 },
        actions: {
            resetFilters: RegionChronicleApplication._onResetFilters,
            openChronicleParticipant: RegionChronicleApplication._onOpenParticipant
        }
    };

    static PARTS = {
        content: {
            template: "modules/augur-nexus/templates/region-population/region-chronicle.hbs",
            templates: ["modules/augur-nexus/templates/region-population/chronicle-event-list.hbs"]
        }
    };

    static show({ sceneId = canvas.scene?.id } = {}) {
        const id = String(sceneId || "");
        if (!id) return null;
        let application = instances.get(id);
        if (!application) {
            application = new this({ sceneId: id }, { id: `augur-region-chronicle-${id}` });
            instances.set(id, application);
        }
        application.render({ force: true, focus: true });
        return application;
    }

    constructor({ sceneId = canvas.scene?.id } = {}, options = {}) {
        super(options);
        this.#sceneId = String(sceneId || "");
        this.#chronicleHookId = Hooks.on("augurNexusRegionChronicleChanged", payload => {
            if (String(payload?.sceneId || "") !== this.#sceneId) return;
            if (payload.reason === "delete") void this.close();
            else void this.render({ force: true });
        });
        this.#entityHookId = Hooks.on("augurNexusCampaignEntitiesChanged", payload => {
            if (!["updateNpc", "updateFaction", "updateLocation", "updateShip"].includes(String(payload?.reason || ""))) return;
            void this.render({ force: true });
        });
        this.#canvasHookId = Hooks.on("canvasReady", activeCanvas => {
            const activeSceneId = String(activeCanvas?.scene?.id || canvas.scene?.id || "");
            if (activeSceneId && activeSceneId !== this.#sceneId) void this.close();
        });

    }

    get title() {
        return `${this.scene?.name || "Region"} — Regional Chronicle`;
    }
    get scene() {
        return game.scenes.get(this.#sceneId) || null;
    }

    async _prepareContext(options) {
        const scene = this.scene;
        const run = RegionPopulationRunStore.get(scene);
        const chronicle = RegionChronicleService.getData(scene, run);
        const events = Array.isArray(chronicle?.events) ? chronicle.events : [];
        const eventViews = events.map(event => RegionChronicleViewModel.prepareEvent(event));
        const yearValues = eventViews.map(event => Number(event.year || 0)).filter(Number.isFinite);
        const minYear = yearValues.length ? Math.min(...yearValues) : 1;
        const maxYear = yearValues.length ? Math.max(...yearValues) : Number(chronicle?.years || 1);
        const filtered = eventViews.filter(event => RegionChronicleViewModel.matchesFilters(event, this.#filters));
        const years = RegionChronicleViewModel.groupByYear(filtered);

        return {
            ...(super._prepareContext ? await super._prepareContext(options) : {}),
            available: !!chronicle,
            chronicle,
            filters: foundry.utils.deepClone(this.#filters),
            factionOptions: RegionChronicleViewModel.participantOptions(eventViews, "faction"),
            actorOptions: RegionChronicleViewModel.participantOptions(eventViews, "actor"),
            locationOptions: RegionChronicleViewModel.participantOptions(eventViews, "location"),
            typeOptions: RegionChronicleViewModel.typeOptions(eventViews),
            scopeOptions: [
                { value: "regional", label: "Regional record" },
                { value: "all", label: "All events" },
                { value: "personal", label: "Personal events" }
            ],
            minYear,
            maxYear,
            years,
            totalEvents: events.length,
            visibleEvents: filtered.length,
            summaryItems: RegionChronicleViewModel.summaryItems(chronicle),
            hasFilters: Object.entries(this.#filters).some(([key, value]) => key === "scope" ? value !== "regional" : !!value)
        };
    }

    _onRender(context, options) {
        super._onRender(context, options);
        for (const input of this.element.querySelectorAll("[data-chronicle-filter]")) {
            const eventName = input.dataset.chronicleFilter === "search" ? "input" : "change";
            input.addEventListener(eventName, () => this.#queueFilterRender(input));
        }
    }

    _onClose(options) {
        clearTimeout(this.#searchTimer);
        if (this.#chronicleHookId !== null) Hooks.off("augurNexusRegionChronicleChanged", this.#chronicleHookId);
        if (this.#entityHookId !== null) Hooks.off("augurNexusCampaignEntitiesChanged", this.#entityHookId);
        if (this.#canvasHookId !== null) Hooks.off("canvasReady", this.#canvasHookId);
        instances.delete(this.#sceneId);
        return super._onClose(options);
    }

    static async _onResetFilters() {
        this.#filters = { search: "", faction: "", actor: "", location: "", type: "", scope: "regional", yearFrom: "", yearTo: "" };
        await this.render({ force: true });
    }

    static async _onOpenParticipant(event, target) {
        const actionTarget = target?.closest?.("[data-entity-id]") || event?.target?.closest?.("[data-entity-id]");
        const entityId = String(actionTarget?.dataset?.entityId || "");
        if (!entityId) return;
        const node = ConnectionTargetResolver.fromEntityReference({ entityId });
        await ConnectionTargetResolver.openNode(node);
    }

    #queueFilterRender(input) {
        const key = String(input.dataset.chronicleFilter || "");
        if (!Object.hasOwn(this.#filters, key)) return;
        this.#filters[key] = String(input.value || "").trim();
        clearTimeout(this.#searchTimer);
        this.#searchTimer = setTimeout(() => void this.render({ force: true }), key === "search" ? 160 : 0);
    }


}
