const MODULE_ID = "augur-nexus";
const FLAG_KEY = "shop";

import { ShopRestockProfileModel } from "./ShopRestockProfileModel.js";

export class ShopModel {
    static getFlag(document) {
        return document?.flags?.[MODULE_ID]?.[FLAG_KEY] || null;
    }

    static isShopDocument(document) {
        return document?.documentName === "JournalEntry" && Boolean(this.getFlag(document)?.id);
    }

    static fromDocument(document) {
        const data = this.getFlag(document);
        if (!data?.id) return null;
        return {
            ...this.normalize(data),
            journalEntryId: document.id,
            uuid: document.uuid
        };
    }

    static normalize(data = {}) {
        const hasTreasury = data.treasury && typeof data.treasury === "object";
        return {
            schemaVersion: 11,
            id: String(data.id || foundry.utils.randomID()),
            name: String(data.name || "Shop").trim() || "Shop",
            naming: this.#normalizeNaming(data.naming),
            display: {
                imageSrc: String(data.display?.imageSrc || "").trim(),
                imageSelection: this.#normalizeImageSelection(data.display),
                coverImageSrc: String(data.display?.coverImageSrc || "").trim(),
                color: /^#[0-9a-f]{6}$/i.test(String(data.display?.color || "")) ? String(data.display.color) : "#d18a42"
            },
            dossier: { defaultTab: String(data.dossier?.defaultTab || "").toLocaleLowerCase() === "journal" ? "journal" : "profile" },
            hierarchy: {
                parentLocationId: String(data.hierarchy?.parentLocationId || "") || null
            },
            markerRefs: (Array.isArray(data.markerRefs) ? data.markerRefs : []).map(ref => ({
                markerId: String(ref.markerId || ""),
                sceneId: String(ref.sceneId || ""),
                documentName: String(ref.documentName || "Tile"),
                documentId: String(ref.documentId || ""),
                labelId: String(ref.labelId || ""),
                markerKind: String(ref.markerKind || "reference"),
                target: foundry.utils.deepClone(ref.target || {})
            })).filter(ref => ref.markerId && ref.sceneId && ref.documentId),
            inventory: (Array.isArray(data.inventory) ? data.inventory : []).map(row => ({
                id: String(row.id || foundry.utils.randomID()),
                providerId: String(row.providerId || ""),
                productId: String(row.productId || ""),
                quantity: Math.max(0, Math.floor(Number(row.quantity) || 0)),
                priceOverride: row.priceOverride !== null && row.priceOverride !== undefined && row.priceOverride !== "" && Number.isFinite(Number(row.priceOverride))
                    ? Math.max(0, Math.round(Number(row.priceOverride)))
                    : null,
                pinned: row.pinned === true,
                generated: row.generated === true
            })).filter(row => row.providerId && row.productId),
            configuration: {
                finiteStock: data.configuration?.finiteStock !== false,
                buyingEnabled: data.configuration?.buyingEnabled !== false,
                sellingEnabled: data.configuration?.sellingEnabled !== false,
                cargoSlots: Math.max(1, Math.floor(Number(data.configuration?.cargoSlots) || 30)),
                unitLabel: String(data.configuration?.unitLabel || "Item"),
                pricingBasis: String(data.configuration?.pricingBasis || ""),
                currencyId: String(data.configuration?.currencyId || ""),
                themeId: String(data.configuration?.themeId || "default"),
                tradePolicyId: String(data.configuration?.tradePolicyId || ""),
                customerPurchaseMultiplier: this.#normalizeMultiplier(
                    data.configuration?.customerPurchaseMultiplier, 1
                ),
                customerSaleMultiplier: this.#normalizeMultiplier(
                    data.configuration?.customerSaleMultiplier, 0.75
                )
            },
            treasury: {
                currencyId: String(data.treasury?.currencyId || data.configuration?.currencyId || ""),
                amount: hasTreasury ? Math.max(0, Math.round(Number(data.treasury.amount) || 0)) : 50000,
                unlimited: data.treasury?.unlimited === true
            },
            restock: foundry.utils.deepClone(data.restock || { mode: "manual" }),
            restockProfile: ShopRestockProfileModel.normalize(data.restockProfile || {}),
            providerData: foundry.utils.deepClone(data.providerData || {}),
            moduleData: foundry.utils.deepClone(data.moduleData || {}),
            revision: Math.max(0, Number(data.revision) || 0),
            processedTransactionIds: (Array.isArray(data.processedTransactionIds) ? data.processedTransactionIds : [])
                .filter(Boolean).slice(-50),
            source: {
                moduleId: String(data.source?.moduleId || ""),
                templateId: String(data.source?.templateId || ""),
                seed: String(data.source?.seed || "")
            },
            lifecycle: {
                recreatable: data.lifecycle?.recreatable === true,
                recoveryHint: String(data.lifecycle?.recoveryHint || "").trim()
            }
        };
    }

    static getImage(shop = {}) { return String(shop?.display?.imageSrc || "").trim(); }
    static getImageSelection(shop = {}) { return this.#normalizeImageSelection(shop?.display); }
    static getCoverImage(shop = {}) { return String(shop?.display?.coverImageSrc || "").trim(); }
    static getAccent(shop = {}) { const value = String(shop?.display?.color || "").trim(); return /^#[0-9a-f]{6}$/i.test(value) ? value : "#d18a42"; }

    static #normalizeNaming(naming = {}) {
        const mode = ["unmanaged", "derived", "custom"].includes(naming?.mode)
            ? naming.mode
            : "unmanaged";
        return {
            mode,
            templateId: String(naming?.templateId || "").trim(),
            pattern: String(naming?.pattern || "").trim(),
            parentNameSnapshot: String(naming?.parentNameSnapshot || "").trim()
        };
    }


    static #normalizeMultiplier(value, fallback) {
        const number = Number(value);
        return Number.isFinite(number) ? Math.clamp(number, 0, 10) : fallback;
    }

    static #normalizeImageSelection(display = {}) {
        const imageSrc = String(display?.imageSrc || "").trim();
        const source = display?.imageSelection || {};
        const mode = ["preset", "catalog", "custom"].includes(source.mode)
            ? source.mode
            : imageSrc ? "custom" : "preset";
        return { mode, id: String(source.id || "").trim() };
    }
}



