const MODULE_ID = "fizzybubble";
const NOTES_FOLDER_NAME = "_simple_calendar_notes_directory";

Hooks.once("init", () => {
    game.settings.registerMenu(MODULE_ID, "scRebornTools", {
        name: "Simple Calendar Tools",
        label: "Open Tools",
        hint: "Export old Simple Calendar notes or migrate them to Simple Calendar Reborn.",
        icon: "fas fa-calendar-days",
        type: SCRebornToolsApp,
        restricted: true
    });
});

const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;

class SCRebornToolsApp extends HandlebarsApplicationMixin(ApplicationV2) {
    static _instance;

    static DEFAULT_OPTIONS = foundry.utils.mergeObject(
        foundry.utils.deepClone(super.DEFAULT_OPTIONS),
        {
            id: "fizzybubble-sc-reborn-tools",
            classes: ["fizzybubble-sc-reborn-tools"],
            position: { width: 560, height: "auto" },
            window: {
                title: "Simple Calendar Tools",
                resizable: true
            }
        }
    );

    static PARTS = {
        main: {
            template: `modules/${MODULE_ID}/templates/sc-reborn-tools.hbs`
        }
    };

    static show() {
        if (!game.user.isGM) {
            ui.notifications.warn("Only the GM can open Simple Calendar Tools.");
            return;
        }

        if (!this._instance) this._instance = new SCRebornToolsApp();
        this._instance.render(true);
    }

    static closeIfOpen() {
        if (!this._instance) return;
        try {
            this._instance.close();
        } catch (_) { }
        this._instance = null;
    }

    _deepClone(obj) {
        try {
            return foundry.utils.deepClone(obj);
        } catch {
            return JSON.parse(JSON.stringify(obj));
        }
    }

    _getOldNotes() {
        return game.journal.contents.filter(j =>
            j.folder?.name === NOTES_FOLDER_NAME &&
            j.flags?.["foundryvtt-simple-calendar"]?.noteData
        );
    }

    _getRebornNotes() {
        return game.journal.contents.filter(j =>
            j.folder?.name === NOTES_FOLDER_NAME &&
            j.flags?.["foundryvtt-simple-calendar-reborn"]?.noteData
        );
    }

    _normalizeRepeats(value) {
        if ([0, 1, 2, 3, 4].includes(value)) return value;

        const s = String(value ?? "").toLowerCase();
        if (s === "never" || s === "none" || s === "") return 0;
        if (s === "daily") return 1;
        if (s === "weekly") return 2;
        if (s === "monthly") return 3;
        if (s === "yearly" || s === "annually") return 4;
        return 0;
    }

    _normalizeDate(d) {
        if (!d || typeof d !== "object") return d;
        const out = this._deepClone(d);

        out.year = Number(out.year);
        out.month = Number(out.month ?? out.monthIndex);
        out.day = Number(out.day ?? out.dayOfMonth);
        out.hour = Number(out.hour ?? out.hours ?? 0) || 0;
        out.minute = Number(out.minute ?? out.minutes ?? 0) || 0;
        out.seconds = Number(out.seconds ?? out.second ?? 0) || 0;

        delete out.second;
        delete out.hours;
        delete out.minutes;
        delete out.monthIndex;
        delete out.dayOfMonth;

        return out;
    }

    async _prepareContext(options) {
        const context = await super._prepareContext(options);

        const oldNotes = this._getOldNotes();
        const rebornNotes = this._getRebornNotes();

        context.oldNotesCount = oldNotes.length;
        context.rebornNotesCount = rebornNotes.length;
        context.notesFolderName = NOTES_FOLDER_NAME;

        return context;
    }

    _onRender(context, options) {
        super._onRender(context, options);

        const part = this.element?.querySelector?.('[data-application-part="main"]') ?? this.element;
        if (!part) return;

        part.querySelector("[data-action='export-old-notes']")?.addEventListener("click", async (ev) => {
            ev.preventDefault();
            await this._exportOldNotes();
            this.render(false);
        });

        part.querySelector("[data-action='migrate-to-reborn']")?.addEventListener("click", async (ev) => {
            ev.preventDefault();
            await this._migrateToReborn();
            this.render(false);
        });
    }

    async _exportOldNotes() {
        if (!game.user.isGM) {
            ui.notifications.warn("Only the GM can export old notes.");
            return;
        }

        const journals = this._getOldNotes().map(j => {
            const raw = j.toObject();

            return {
                name: raw.name,
                folderName: j.folder?.name ?? null,
                folderId: raw.folder ?? null,
                flags: this._deepClone(raw.flags ?? {}),
                ownership: this._deepClone(raw.ownership ?? {}),
                sort: raw.sort ?? 0,
                pages: this._deepClone(raw.pages ?? [])
            };
        });

        const exportData = {
            meta: {
                exportedAt: new Date().toISOString(),
                worldId: game.world.id,
                worldTitle: game.world.title,
                foundryVersion: game.version ?? game.release?.version ?? "unknown",
                noteCount: journals.length,
                flagNamespace: "foundryvtt-simple-calendar",
                folderName: NOTES_FOLDER_NAME
            },
            journals
        };

        const fileName = `simple-calendar-old-notes-raw-${game.world.id}-${Date.now()}.json`;

        foundry.utils.saveDataToFile(
            JSON.stringify(exportData, null, 2),
            "application/json",
            fileName
        );

        console.log(`${MODULE_ID} | Exported old Simple Calendar notes`, exportData);
        ui.notifications.info(`Export complete: ${journals.length} old notes exported.`);
    }

    async _migrateToReborn() {
        if (!game.user.isGM) {
            ui.notifications.warn("Only the GM can migrate notes.");
            return;
        }

        const DELETE_OLD_FLAG_AFTER_MIGRATION = false;

        const notes = this._getOldNotes();

        let migrated = 0;
        let failed = 0;

        for (const j of notes) {
            try {
                const oldData = this._deepClone(j.flags["foundryvtt-simple-calendar"].noteData);

                const newData = {
                    calendarId: oldData.calendarId ?? "default",
                    startDate: this._normalizeDate(oldData.startDate ?? oldData.start ?? oldData.date),
                    endDate: this._normalizeDate(
                        oldData.endDate ?? oldData.end ?? oldData.startDate ?? oldData.start ?? oldData.date
                    ),
                    allDay: Boolean(oldData.allDay ?? true),
                    order: Number(oldData.order ?? 0) || 0,
                    categories: Array.isArray(oldData.categories) ? oldData.categories : [],
                    repeats: this._normalizeRepeats(oldData.repeats),
                    remindUsers: Array.isArray(oldData.remindUsers) ? oldData.remindUsers : [],
                    macro: oldData.macro ?? "none",
                    fromPredefined: Boolean(oldData.fromPredefined ?? false)
                };

                if (!newData.startDate || !Number.isFinite(newData.startDate.year)) {
                    throw new Error("Invalid startDate");
                }

                if (!newData.endDate || !Number.isFinite(newData.endDate.year)) {
                    newData.endDate = this._deepClone(newData.startDate);
                }

                const update = {
                    "flags.core.sheetClass": "foundryvtt-simple-calendar-reborn.NoteSheet",
                    "flags.foundryvtt-simple-calendar-reborn.noteData": newData
                };

                if (DELETE_OLD_FLAG_AFTER_MIGRATION) {
                    update["flags.-=foundryvtt-simple-calendar"] = null;
                }

                await j.update(update);
                migrated++;
            } catch (err) {
                failed++;
                console.error(`${MODULE_ID} | Migration failed:`, j.name, err);
            }
        }

        ui.notifications.info(
            `Migration complete: ${migrated} migrated, ${failed} failed. Reload the world afterwards.`
        );
    }
}

globalThis.SCRebornToolsApp = SCRebornToolsApp;