(function (root) {
  "use strict";

  function selectedValue(configuration, groupId, overrideValue = "") {
    if (overrideValue) return String(overrideValue).trim();
    const group = (configuration?.groups || []).find(item => item.id === groupId);
    const value = String(group?.values?.[0] || "").trim();
    if (value.includes("自定义")) return String(group?.customValue || "").trim();
    return value;
  }

  function pricePerKg(snapshot) {
    const price = Number(snapshot?.price);
    const unit = String(snapshot?.unit || "").replace(/\s+/g, "").toLowerCase();
    if (!(price > 0)) return null;
    if (unit.includes("吨") || unit.includes("ton")) return price / 1000;
    if (unit.includes("kg") || unit.includes("千克") || unit.includes("公斤")) return price;
    return null;
  }

  function gsmFrom(value) {
    return Number(String(value || "").match(/(\d+(?:\.\d+)?)\s*(?:g|克)/i)?.[1] || 0);
  }

  function safeRate(value, fallback = 0) {
    const number = Number(value);
    return Number.isFinite(number) && number >= 0 && number < 1 ? number : fallback;
  }

  function money(value) {
    const number = Number(value || 0);
    if (number >= 100) return number.toFixed(0);
    if (number >= 10) return number.toFixed(1);
    return number.toFixed(2);
  }

  function standardSheetCandidates(engine) {
    return Object.values(engine?.printSheetFormats || {}).flatMap(format =>
      ["regular", "large"].map(standard => ({
        formatId: format.id,
        standard,
        widthMm: Number(format[standard]?.[0] || 0),
        heightMm: Number(format[standard]?.[1] || 0)
      }))
    ).filter(item => item.widthMm > 0 && item.heightMm > 0)
      .sort((left, right) => left.widthMm * left.heightMm - right.widthMm * right.heightMm);
  }

  function estimate(context = {}) {
    const engine = context.engine;
    if (typeof engine?.calculateBookQuote !== "function") {
      return { ok: false, error: "书刊页数计价引擎尚未加载", missing: ["计价引擎"] };
    }
    const configuration = context.configuration || {};
    const pageCountText = selectedValue(configuration, "page_count", context.pageCount);
    const sizeText = selectedValue(configuration, "size");
    const coverMaterialName = selectedValue(configuration, "cover_material");
    const innerMaterialName = selectedValue(configuration, "inner_material");
    const printName = selectedValue(configuration, "print_color");
    const bindingName = selectedValue(configuration, "binding");
    const missing = [];
    let finishedSize;
    try {
      finishedSize = engine.parseDimensions(sizeText, 2);
    } catch (_) {
      missing.push("成品尺寸");
    }
    let pageCount = 0;
    try {
      pageCount = engine.parseBookPageCount(pageCountText);
    } catch (error) {
      if (context.strict) return { ok: false, error: error.message, missing: ["内页页数"] };
      missing.push("内页页数");
    }
    const coverPrice = context.materialPrice?.(coverMaterialName) || {};
    const innerPrice = context.materialPrice?.(innerMaterialName) || {};
    const coverPricePerKg = pricePerKg(coverPrice);
    const innerPricePerKg = pricePerKg(innerPrice);
    const coverGsm = gsmFrom(coverMaterialName);
    const innerGsm = gsmFrom(innerMaterialName);
    if (!(coverPricePerKg > 0) || !(coverGsm > 0)) missing.push("封面纸价/克重");
    if (!(innerPricePerKg > 0) || !(innerGsm > 0)) missing.push("内页纸价/克重");
    const printOperation = printName ? context.operationPrice?.(printName, "print") : null;
    const bindingOperation = bindingName ? context.operationPrice?.(bindingName, "process") : null;
    if (!printOperation?.configured || !printOperation?.printSheetTierPricing) missing.push("印刷开数价");
    if (!bindingOperation?.configured) missing.push(`${bindingName || "装订"}价`);
    const hardMissing = missing.filter(item => item !== `${bindingName || "装订"}价`);
    if (hardMissing.length) {
      return {
        ok: false,
        error: `书刊报价还缺：${[...new Set(missing)].join("、")}`,
        missing: [...new Set(missing)]
      };
    }
    const settings = context.settings || {};
    const lossRate = safeRate(settings.loss, 0);
    const bindingForCalculation = bindingOperation?.configured ? {
      id: bindingOperation.id || `book-${bindingName}`,
      name: bindingName,
      basis: bindingOperation.basis || "book",
      unitRate: Number(bindingOperation.unitPrice || 0),
      setupFee: Number(bindingOperation.setupFee || 0),
      minimumCharge: Number(bindingOperation.minimumCharge || 0),
      chargeMode: bindingOperation.chargeMode || "minimum",
      packageQuantity: Number(bindingOperation.includedQuantity || 0),
      packageFee: Number(bindingOperation.minimumCharge || 0),
      usagePerPiece: Number(bindingOperation.usagePerPiece ?? 1)
    } : {
      id: `book-${bindingName || "binding"}-pending`,
      name: bindingName || "装订待补",
      basis: "book",
      unitRate: 0,
      minimumCharge: 0,
      chargeMode: "linear",
      usagePerPiece: 1
    };
    try {
      const input = {
        quantity: Math.max(1, Number(context.quantity || 1)),
        pageCount,
        finishedWidthMm: finishedSize[0],
        finishedHeightMm: finishedSize[1],
        sheetWidthMm: Number(context.sheetWidthMm || 889),
        sheetHeightMm: Number(context.sheetHeightMm || 1194),
        coverMaterialName,
        coverGsm,
        coverMaterialPricePerKg: coverPricePerKg,
        innerMaterialName,
        innerGsm,
        innerMaterialPricePerKg: innerPricePerKg,
        printOperation,
        coverPrintSideCount: 1,
        innerPrintSideCount: 2,
        printWasteRate: lossRate,
        finishingWasteRate: 0,
        bindingName,
        bindingOperation: bindingForCalculation
      };
      const candidates = standardSheetCandidates(engine);
      let selected = null;
      candidates.forEach(coverSheet => candidates.forEach(innerSheet => {
        try {
          const candidateInput = {
            ...input,
            coverSheetWidthMm: coverSheet.widthMm,
            coverSheetHeightMm: coverSheet.heightMm,
            innerSheetWidthMm: innerSheet.widthMm,
            innerSheetHeightMm: innerSheet.heightMm
          };
          const candidateResult = engine.calculateBookQuote(candidateInput);
          if (!selected || candidateResult.costs.total < selected.result.costs.total) {
            selected = { input:candidateInput, result:candidateResult };
          }
        } catch (_) {}
      }));
      if (!selected) throw new Error("当前成品尺寸无法匹配已确认的全开、对开、四开或八开上机纸");
      const result = selected.result;
      const overheadRate = safeRate(settings.overheadRate, 0);
      const directWithOverhead = result.costs.total * (1 + overheadRate);
      const grossMargin = safeRate(context.profitRate, safeRate(settings.profit, 0));
      const preTax = directWithOverhead / Math.max(1 - grossMargin, 0.01);
      const taxRate = context.taxIncluded ? safeRate(settings.tax, 0) : 0;
      const total = preTax * (1 + taxRate);
      return {
        ok: true,
        complete: !missing.length,
        missing: [...new Set(missing)],
        result,
        input:selected.input,
        pageCount,
        coverMaterialName,
        innerMaterialName,
        printName,
        bindingName,
        coverPrice,
        innerPrice,
        printOperation,
        bindingOperation,
        estimatedTotal: total,
        estimatedUnitPrice: total / result.quantity
      };
    } catch (error) {
      return { ok: false, error: error.message || "书刊页数成本计算失败", missing: [...new Set(missing)] };
    }
  }

  function optionLabel(context = {}) {
    if (String(context.pageCount || "").includes("自定义")) return "";
    const report = estimate({ ...context, strict: false });
    if (!report.ok) return report.missing?.length ? `待补：${report.missing.join("、")}` : "选择规格后显示价格";
    const prefix = report.complete ? "系统约" : "已计";
    const suffix = report.complete ? "" : ` · 缺${report.missing.join("、")}`;
    return `${prefix} ¥${money(report.estimatedUnitPrice)}/本${suffix}`;
  }

  function breakdown(context = {}) {
    const report = estimate({ ...context, strict: true });
    if (!report.ok) return report;
    if (!report.complete) {
      return { ok: false, error: `书刊报价还缺：${report.missing.join("、")}。已填写部分不会被丢失。`, missing: report.missing };
    }
    const result = report.result;
    const cover = result.components.cover;
    const inner = result.components.inner;
    const coverPrint = result.printItems[0];
    const innerPrint = result.printItems[1];
    const binding = result.operationItems[0];
    const detailLineItems = [
      {
        category: "材料", name: `封面 · ${cover.materialName}`, pricingUnit: "元/kg",
        unitPrice: cover.materialPricePerKg, usage: cover.paper.weightKg, usageUnit: "kg",
        subtotal: cover.materialCost, source: report.coverPrice.source || "本厂封面纸价",
        detail: `${cover.layout.count}拼 · ${cover.productionSheets}张`
      },
      {
        category: "材料", name: `内页${result.pageCount}P · ${inner.materialName}`, pricingUnit: "元/kg",
        unitPrice: inner.materialPricePerKg, usage: inner.paper.weightKg, usageUnit: "kg",
        subtotal: inner.materialCost, source: report.innerPrice.source || "本厂内页纸价",
        detail: `${inner.forms}个印刷书帖 · ${inner.productionSheets}张`
      },
      {
        category: "印刷", name: coverPrint.name, pricingUnit: "元/印张",
        unitPrice: coverPrint.unitRate, usage: coverPrint.basisQuantity, usageUnit: "印张",
        subtotal: coverPrint.total, source: "本厂印刷开数价",
        detail: `${coverPrint.sheetFormat?.label || "上机纸"} · ${coverPrint.forms}个印刷书帖`
      },
      {
        category: "印刷", name: innerPrint.name, pricingUnit: "元/印张",
        unitPrice: innerPrint.unitRate, usage: innerPrint.basisQuantity, usageUnit: "印张",
        subtotal: innerPrint.total, source: "本厂印刷开数价",
        detail: `${innerPrint.sheetFormat?.label || "上机纸"} · ${innerPrint.forms}个印刷书帖`
      },
      {
        category: "工艺", name: binding.name, pricingUnit: `元/${binding.basis === "book" ? "本" : binding.basis}`,
        unitPrice: binding.unitRate, usage: binding.basisQuantity, usageUnit: binding.basis === "book" ? "本" : binding.basis,
        subtotal: binding.total, source: report.bindingOperation?.source || "本厂装订价",
        detail: Number(binding.minimumCharge || 0) > 0 ? `最低收费 ¥${Number(binding.minimumCharge).toFixed(2)}` : ""
      }
    ];
    return {
      ok: true,
      category: "书刊印刷",
      materialCost: result.costs.material,
      materialUnitCost: result.costs.material / Math.max(result.quantity, 1),
      printingCost: result.costs.printing,
      operationCost: result.costs.operations,
      operationItems: result.operationItems,
      detailLineItems,
      extraDirectCost: 0,
      laborCost: 0,
      machineCost: 0,
      materialLabel: `封面 ${cover.paper.weightKg.toFixed(3)}kg + 内页${result.pageCount}P ${inner.paper.weightKg.toFixed(3)}kg`,
      extraLabel: "",
      basis: `封面 ${cover.layout.count}拼/1个书帖；内页 ${inner.layout.count}页/面、${inner.forms}个印刷书帖；页数变化会重新计算纸张、印张和装订。`,
      formulaInput: report.input,
      formulaResult: result,
      libraryOperationIds: [binding.id],
      libraryOperationNames: [binding.name],
      usedCostItems: [
        context.costItem?.(report.coverMaterialName, ["material"]),
        context.costItem?.(report.innerMaterialName, ["material"])
      ].filter(Boolean),
      costVersionId: String(context.costVersionId || ""),
      costVersionEffectiveAt: String(context.costVersionEffectiveAt || "")
    };
  }

  root.JIANGLAI_BOOK_QUOTE = Object.freeze({ estimate, optionLabel, breakdown });
})(typeof globalThis !== "undefined" ? globalThis : this);
