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

export class NexusDeletionProgressApplication extends HandlebarsApplicationMixin(ApplicationV2) {
    #completed = 0;
    #total = 0;
    #message = "Preparing deletion...";
    #startedAt = 0;
    #timer = null;

    static DEFAULT_OPTIONS = {
        id: "nexus-deletion-progress",
        tag: "div",
        classes: ["augur-nexus", "nexus-deletion-progress"],
        window: {
            title: "Deleting Nexus Content",
            icon: "fas fa-trash-can",
            minimizable: false,
            resizable: false
        },
        position: { width: 460, height: "auto" }
    };

    static PARTS = {
        content: {
            template: "modules/augur-nexus/templates/deletion/deletion-progress.hbs"
        }
    };

    constructor(options = {}) {
        super({
            ...options,
            id: options.id || `nexus-deletion-progress-${foundry.utils.randomID()}`
        });
    }

    async open() {
        if (!this.#startedAt) this.#startedAt = Date.now();
        await this.render({ force: true });
        this.#timer ||= globalThis.setInterval(() => this.#refresh(), 1000);
        return this;
    }

    addTotal(count = 0) {
        this.#total += this.#normalizeCount(count);
        this.#refresh();
        return this;
    }

    setMessage(message = "") {
        if (message) this.#message = String(message);
        this.#refresh();
        return this;
    }

    advance(count = 1, message = "") {
        this.#completed = Math.min(this.#total, this.#completed + this.#normalizeCount(count));
        if (message) this.#message = String(message);
        this.#refresh();
        return this;
    }

    async complete(message = "Deletion complete.") {
        this.#completed = this.#total;
        this.#message = message;
        this.#refresh();
        await new Promise(resolve => globalThis.setTimeout(resolve, 300));
        await this.closeProgress();
    }

    async closeProgress() {
        if (this.#timer) {
            globalThis.clearInterval(this.#timer);
            this.#timer = null;
        }
        if (this.rendered) await this.close();
    }

    _prepareContext() {
        return this.#getViewState();
    }

    _onRender(context, options) {
        super._onRender(context, options);
        this.#refresh();
    }

    _onClose(options) {
        if (this.#timer) {
            globalThis.clearInterval(this.#timer);
            this.#timer = null;
        }
        return super._onClose(options);
    }

    #getViewState() {
        const total = Math.max(this.#total, this.#completed);
        const completed = Math.min(this.#completed, total);
        return {
            message: this.#message,
            completed,
            total,
            remaining: Math.max(0, total - completed),
            pct: total > 0 ? Math.round((completed / total) * 100) : 0,
            elapsed: this.#formatElapsed(Date.now() - (this.#startedAt || Date.now()))
        };
    }

    #refresh() {
        const root = this.element;
        if (!root) return;
        const state = this.#getViewState();
        const setText = (selector, value) => {
            const element = root.querySelector(selector);
            if (element) element.textContent = String(value);
        };
        setText("[data-deletion-message]", state.message);
        setText("[data-deletion-completed]", state.completed);
        setText("[data-deletion-total]", state.total);
        setText("[data-deletion-remaining]", state.remaining);
        setText("[data-deletion-elapsed]", state.elapsed);
        const bar = root.querySelector("[data-deletion-progress-bar]");
        if (bar) bar.style.width = `${state.pct}%`;
        const progress = root.querySelector("[data-deletion-progress]");
        if (progress) {
            progress.setAttribute("aria-valuenow", String(state.completed));
            progress.setAttribute("aria-valuemax", String(state.total));
        }
    }

    #normalizeCount(value) {
        const numeric = Math.floor(Number(value) || 0);
        return Math.max(0, numeric);
    }

    #formatElapsed(milliseconds) {
        const seconds = Math.max(0, Math.floor(Number(milliseconds || 0) / 1000));
        const minutes = Math.floor(seconds / 60);
        const remainder = seconds % 60;
        return `${String(minutes).padStart(2, "0")}:${String(remainder).padStart(2, "0")}`;
    }
}
