const { HandlebarsApplicationMixin } = foundry.applications.api;
import { MGT2Helper } from "../../helper.js";

export default class TravellerItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {

    /** @override */
    static DEFAULT_OPTIONS = {
        classes: ["mgt2", "sheet", "item"],
        position: { width: 630 },
        form: {
            submitOnChange: true,
            closeOnSubmit: false,
        },
        window: { resizable: true },
        actions: {
            careerEventCreate: TravellerItemSheet.#onCareerEventCreate,
            careerEventDelete: TravellerItemSheet.#onCareerEventDelete,
            optionCreate: TravellerItemSheet.#onOptionCreate,
            optionDelete: TravellerItemSheet.#onOptionDelete,
            modifierCreate: TravellerItemSheet.#onModifierCreate,
            modifierDelete: TravellerItemSheet.#onModifierDelete,
        },
    }

    /** Dynamic PARTS: template resolved per item type */
    get PARTS() {
        const type = this.document?.type ?? "item";
        return {
            sheet: {
                template: `systems/mgt2/templates/items/${type}-sheet.html`,
            },
        };
    }

    /** Resolve template dynamically based on item type */
    get template() {
        return `systems/mgt2/templates/items/${this.document.type}-sheet.html`;
    }

    tabGroups = { primary: "tab1" }

    /** @override */
    async _prepareContext() {
        const item = this.document;
        const source = item.toObject();

        const settings = {
            usePronouns: game.settings.get("mgt2", "usePronouns"),
        };

        let containers = null;
        let computers = null;
        let hadContainer = false;

        if (item.actor !== null) {
            hadContainer = true;
            containers = [{ name: "", _id: "" }].concat(item.actor.getContainers());
            computers = [{ name: "", _id: "" }].concat(item.actor.getComputers());
        }

        let weight = null;
        if (item.system.hasOwnProperty("weight")) {
            weight = MGT2Helper.convertWeightForDisplay(item.system.weight);
        }

        let skills = [];
        if (this.actor !== null) {
            for (let actorItem of this.actor.items) {
                if (actorItem.type === "talent" && actorItem.system.subType === "skill")
                    skills.push({ _id: actorItem._id, name: actorItem.getRollDisplay() });
            }
        }
        skills.sort(MGT2Helper.compareByName);
        skills = [{ _id: "NP", name: game.i18n.localize("MGT2.Items.NotProficient") }].concat(skills);

        return {
            item: item,
            document: item,
            cssClass: this.isEditable ? "editable" : "locked",
            system: item.system,
            source: source.system,
            fields: item.schema.fields,
            systemFields: item.system.schema.fields,
            isEditable: this.isEditable,
            isGM: game.user.isGM,
            config: CONFIG.MGT2,
            settings: settings,
            containers: containers,
            computers: computers,
            hadContainer: hadContainer,
            weight: weight,
            unitlabels: { weight: MGT2Helper.getWeightLabel() },
            skills: skills,
        };
    }

    /** @override — resolve the per-type template before rendering */
    async _renderHTML(context, options) {
        const templatePath = `systems/mgt2/templates/items/${this.document.type}-sheet.html`;
        const html = await foundry.applications.handlebars.renderTemplate(templatePath, context);
        return { sheet: html };
    }

    /** @override — put rendered HTML into the window content */
    _replaceHTML(result, content, options) {
        content.innerHTML = result.sheet;
        // Inject theme class dynamically (can't use game.settings in static DEFAULT_OPTIONS)
        const theme = game.settings.get("mgt2", "theme");
        if (theme) this.element.classList.add(theme);
        this._activateTabGroups();
        this._bindItemEvents();
    }

    /** Bind CSS class-based events (templates not yet migrated to data-action) */
    _bindItemEvents() {
        const html = this.element;
        if (!this.isEditable) return;
        const bind = (sel, handler) => {
            for (const el of html.querySelectorAll(sel)) {
                el.addEventListener("click", (ev) => handler.call(this, ev, ev.currentTarget));
            }
        };
        bind(".event-create", TravellerItemSheet.#onCareerEventCreate);
        bind(".event-delete", TravellerItemSheet.#onCareerEventDelete);
        bind(".options-create", TravellerItemSheet.#onOptionCreate);
        bind(".options-delete", TravellerItemSheet.#onOptionDelete);
        bind(".modifiers-create", TravellerItemSheet.#onModifierCreate);
        bind(".modifiers-delete", TravellerItemSheet.#onModifierDelete);
    }

    _activateTabGroups() {
        for (const [group, activeTab] of Object.entries(this.tabGroups)) {
            const nav = this.element.querySelector(`nav[data-group="${group}"], .horizontal-tabs`);
            if (!nav) continue;

            nav.querySelectorAll('[data-tab]').forEach(link => {
                link.classList.toggle('active', link.dataset.tab === activeTab);
                link.addEventListener('click', event => {
                    event.preventDefault();
                    this.tabGroups[group] = link.dataset.tab;
                    this.render();
                });
            });

            this.element.querySelectorAll(`.itemsheet-panel [data-tab], [data-group="${group}"][data-tab]`).forEach(content => {
                content.classList.toggle('active', content.dataset.tab === activeTab);
            });
        }
    }

    /** @override — process form data before submit (weight/qty/cost conversions + container logic) */
    _prepareSubmitData(event, form, formData) {
        const data = foundry.utils.expandObject(formData.object);

        if (data.hasOwnProperty("weight")) {
            data.system = data.system || {};
            data.system.weight = MGT2Helper.convertWeightFromInput(data.weight);
            delete data.weight;
        }

        if (data.system?.hasOwnProperty("quantity")) {
            data.system.quantity = MGT2Helper.getIntegerFromInput(data.system.quantity);
        }

        if (data.system?.hasOwnProperty("cost")) {
            data.system.cost = MGT2Helper.getIntegerFromInput(data.system.cost);
        }

        // Container/equipped logic
        if (data.system?.hasOwnProperty("container") && this.document.system.hasOwnProperty("equipped")) {
            const equippedChange = this.document.system.equipped !== data.system.equipped;
            const containerChange = this.document.system.container?.id !== data.system.container?.id;

            if (equippedChange && data.system.equipped === true) {
                data.system.container = { id: "" };
            } else if (containerChange && data.system.container?.id !== "" && this.document.system.container?.id === "") {
                data.system.equipped = false;
            }
        }

        return foundry.utils.flattenObject(data);
    }

    // =========================================================
    // Actions
    // =========================================================

    static async #onCareerEventCreate(event) {
        event.preventDefault();
        const events = this.document.system.events;
        let newEvents;
        if (!events || events.length === 0) {
            newEvents = [{ age: "", description: "" }];
        } else {
            newEvents = [...events, { age: "", description: "" }];
        }
        return this.document.update({ system: { events: newEvents } });
    }

    static async #onCareerEventDelete(event, target) {
        event.preventDefault();
        const element = target.closest("[data-events-part]");
        const index = Number(element.dataset.eventsPart);
        const events = foundry.utils.deepClone(this.document.system.events);
        const newEvents = Object.entries(events)
            .filter(([key]) => Number(key) !== index)
            .map(([, val]) => val);
        return this.document.update({ system: { events: newEvents } });
    }

    static async #onOptionCreate(event, target) {
        event.preventDefault();
        const property = target.dataset.property;
        const options = this.document.system[property];
        let newOptions;
        if (!options || options.length === 0) {
            newOptions = [{ name: "", description: "" }];
        } else {
            newOptions = [...options, { name: "", description: "" }];
        }
        return this.document.update({ [`system.${property}`]: newOptions });
    }

    static async #onOptionDelete(event, target) {
        event.preventDefault();
        const element = target.closest("[data-options-part]");
        const property = element.dataset.property;
        const index = Number(element.dataset.optionsPart);
        const options = foundry.utils.deepClone(this.document.system[property]);
        const newOptions = Object.entries(options)
            .filter(([key]) => Number(key) !== index)
            .map(([, val]) => val);
        return this.document.update({ [`system.${property}`]: newOptions });
    }

    static async #onModifierCreate(event) {
        event.preventDefault();
        const modifiers = this.document.system.modifiers;
        let newModifiers;
        if (!modifiers || modifiers.length === 0) {
            newModifiers = [{ characteristic: "Endurance", value: null }];
        } else {
            newModifiers = [...modifiers, { characteristic: "Endurance", value: null }];
        }
        return this.document.update({ system: { modifiers: newModifiers } });
    }

    static async #onModifierDelete(event, target) {
        event.preventDefault();
        const element = target.closest("[data-modifiers-part]");
        const index = Number(element.dataset.modifiersPart);
        const modifiers = foundry.utils.deepClone(this.document.system.modifiers);
        const newModifiers = Object.entries(modifiers)
            .filter(([key]) => Number(key) !== index)
            .map(([, val]) => val);
        return this.document.update({ system: { modifiers: newModifiers } });
    }
}
