import { getLocation, registerLocationAction } from "../../../api/locations.js";
import { createShop, getShopsForParentLocation, openShopEditor, updateShop } from "../../../api/shops.js";
import { SettlementMarketplaceModel } from "../models/SettlementMarketplaceModel.js";
import { SettlementMarketplaceInventoryService } from "./SettlementMarketplaceInventoryService.js";
import { REGIONAL_MARKETPLACE_TRADE_POLICY_ID } from "./RegionalMarketplaceTradePolicy.js";
import { ShopCreationGateway } from "../../shops/services/ShopCreationGateway.js";

export class RegionalMarketplaceService {
    static register() {
        registerLocationAction({
            id: "augur-nexus:regional-marketplace",
            moduleId: "augur-nexus",
            order: 118,
            icon: "fas fa-scale-balanced",
            label: ({ location }) => this.get(location.id) ? "Edit Regional Marketplace" : "Add Regional Marketplace",
            matches: ({ location, user }) => user?.isGM === true
                && location?.profile?.kindId === "settlement"
                && location?.moduleData?.["augur-nexus"]?.trade?.marketplaceManagedByFeatureModule !== true,
            onSelect: ({ location }) => this.openOrCreate(location.id)
        });
        Hooks.on("augurNexusTradeMarketsReconcile", ({ locationIds = [], fallbackLocationId = "" } = {}) => {
            if (!game.user?.isGM) return;
            const ids = locationIds.length ? locationIds : [fallbackLocationId].filter(Boolean);
            void this.reconcile(ids).catch(error => console.error("Augur: Nexus | Failed to refresh regional marketplaces", error));
        });
    }

    static get(locationId) {
        return getShopsForParentLocation(locationId).find(shop => SettlementMarketplaceModel.isMarketplace(shop)) || null;
    }

    static async openOrCreate(locationId) {
        const location = getLocation(locationId);
        if (!location || !game.user?.isGM) return null;
        let shop = this.get(location.id);
        if (!shop) {
            if (!await ShopCreationGateway.authorize()) return null;
            shop = await this.#create(location);
        }
        return openShopEditor({ shopId: shop.id });
    }

    static async reconcile(locationIds = []) {
        const updated = [];
        for (const locationId of new Set((locationIds || []).map(String).filter(Boolean))) {
            const location = getLocation(locationId);
            const shop = this.get(locationId);
            if (!location || !shop || shop.source?.moduleId !== "augur-nexus") continue;
            const rules = SettlementMarketplaceModel.getRules(shop, location);
            const generated = await SettlementMarketplaceInventoryService.create({
                entity: location,
                shop,
                economy: SettlementMarketplaceModel.getEconomy(location),
                rules,
                seed: shop.source?.seed || `${location.id}:regional-market`
            });
            const inventory = [...(shop.inventory || []).filter(row => row.generated !== true), ...generated];
            if (this.#sameInventory(shop.inventory || [], inventory)) continue;
            updated.push(await updateShop(shop.id, {
                inventory,
                moduleData: {
                    ...(shop.moduleData || {}),
                    "augur-nexus": {
                        ...(shop.moduleData?.["augur-nexus"] || {}),
                        marketplace: SettlementMarketplaceModel.toModuleData(rules)
                    }
                }
            }));
        }
        return updated;
    }

    static #sameInventory(left = [], right = []) {
        const signature = row => JSON.stringify([
            String(row?.providerId || ""),
            String(row?.productId || ""),
            Number(row?.quantity || 0),
            row?.priceOverride ?? null,
            row?.pinned === true,
            row?.generated === true
        ]);
        return left.length === right.length && left.every((row, index) => signature(row) === signature(right[index]));
    }

    static async #create(location) {
        const rules = SettlementMarketplaceModel.getRules({}, location);
        const inventory = await SettlementMarketplaceInventoryService.create({
            entity: location,
            economy: SettlementMarketplaceModel.getEconomy(location),
            rules,
            seed: `${location.id}:regional-market`
        });
        const currencyId = game.system?.id === "pf2e" ? "pf2e-coins" : "dnd5e-cp";
        return createShop({
            name: `${location.display?.name || "Settlement"} Marketplace`,
            display: { imageSrc: "icons/svg/coins.svg" },
            hierarchy: { parentLocationId: location.id },
            inventory,
            configuration: {
                finiteStock: true,
                buyingEnabled: true,
                sellingEnabled: true,
                currencyId,
                themeId: "fantasy",
                customerPurchaseMultiplier: 1,
                customerSaleMultiplier: 1,
                tradePolicyId: REGIONAL_MARKETPLACE_TRADE_POLICY_ID,
                pricingBasis: "Local exports are cheaper; markets pay more for goods their trade network cannot supply."
            },
            treasury: { currencyId, amount: 50000, unlimited: false },
            moduleData: { "augur-nexus": { marketplace: SettlementMarketplaceModel.toModuleData(rules) } },
            source: { moduleId: "augur-nexus", templateId: "settlement-marketplace", seed: `${location.id}:regional-market` },
            lifecycle: { recreatable: true, recoveryHint: "This Marketplace can be added again from the Location menu." }
        });
    }
}
