(function (global) {
  const LABEL_TEMPLATES = [
    {
      id: "blank-roll-36x18",
      kind: "blank",
      title: "36×18 小标签",
      description: "卷式空白标签，适合小规格贴纸与价签。",
      suggestedName: "36×18 小标签",
      labelType: "roll",
      widthMm: 36,
      heightMm: 18,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 36,
        height: 18,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [],
    },
    {
      id: "blank-roll-50x30",
      kind: "blank",
      title: "50×30 商品标签",
      description: "通用卷式商品标签，适合货架价签和小型包装。",
      suggestedName: "50×30 商品标签",
      labelType: "roll",
      widthMm: 50,
      heightMm: 30,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 50,
        height: 30,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [],
    },
    {
      id: "blank-roll-70x40",
      kind: "blank",
      title: "70×40 条码标签",
      description: "适合库存、货架和仓储编码场景。",
      suggestedName: "70×40 条码标签",
      labelType: "roll",
      widthMm: 70,
      heightMm: 40,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 70,
        height: 40,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [],
    },
    {
      id: "blank-roll-100x150",
      kind: "blank",
      title: "100×150 物流面单",
      description: "适合快递面单与仓配发货标签。",
      suggestedName: "100×150 物流面单",
      labelType: "roll",
      widthMm: 100,
      heightMm: 150,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 100,
        height: 150,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [],
    },
    {
      id: "blank-a4-63x38",
      kind: "blank",
      title: "A4 三列小标签",
      description: "A4 成品标签纸，适合批量办公打印。",
      suggestedName: "A4 三列小标签",
      labelType: "flat",
      widthMm: 63.5,
      heightMm: 38.1,
      paper: {
        matchLabel: false,
        preset: "a4",
        width: 210,
        height: 297,
        landscape: false,
        marginTop: 13.2,
        marginBottom: 13.2,
        marginLeft: 7,
        marginRight: 7,
        gapX: 2.5,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [],
    },
    {
      id: "blank-disc-120-small-hub",
      kind: "blank",
      title: "标准光盘 120mm（小内环）",
      description: "120mm 光盘面模板，24mm 内径 / 116mm 外径，适合小内环可打印光盘。",
      suggestedName: "标准光盘 120mm（小内环）",
      labelType: "roll",
      widthMm: 120,
      heightMm: 120,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 120,
        height: 120,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 0 },
      content: [
        { type: "circle", leftMm: 2, topMm: 2, diameterMm: 116, stroke: "#f97316", strokeWidthMm: 0.5, fill: "transparent", excludeFromPrint: true, customType: "printGuide" },
        { type: "circle", leftMm: 48, topMm: 48, diameterMm: 24, stroke: "#f97316", strokeWidthMm: 0.5, fill: "transparent", excludeFromPrint: true, customType: "printGuide" },
      ],
    },
    {
      id: "blank-disc-120-standard",
      kind: "blank",
      title: "标准光盘 120mm",
      description: "120mm 光盘面模板，43mm 内径 / 116mm 外径，适合常见大内环可打印光盘。",
      suggestedName: "标准光盘 120mm",
      labelType: "roll",
      widthMm: 120,
      heightMm: 120,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 120,
        height: 120,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 0 },
      content: [
        { type: "circle", leftMm: 2, topMm: 2, diameterMm: 116, stroke: "#f97316", strokeWidthMm: 0.5, fill: "transparent", excludeFromPrint: true, customType: "printGuide" },
        { type: "circle", leftMm: 38.5, topMm: 38.5, diameterMm: 43, stroke: "#f97316", strokeWidthMm: 0.5, fill: "transparent", excludeFromPrint: true, customType: "printGuide" },
      ],
    },
    {
      id: "product-price-tag",
      kind: "business",
      title: "商品价签",
      description: "默认带品名、价格和条码布局。",
      suggestedName: "商品价签",
      labelType: "roll",
      widthMm: 50,
      heightMm: 30,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 50,
        height: 30,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [
        { type: "textbox", text: "商品名称", leftMm: 4, topMm: 3, widthMm: 22, fontSizeMm: 4.2, lineHeight: 1.1 },
        { type: "text", text: "¥ 99.00", leftMm: 4, topMm: 11, widthMm: 18, fontSizeMm: 7, fontWeight: "bold" },
        { type: "text", text: "限时优惠", leftMm: 4, topMm: 21, widthMm: 18, fontSizeMm: 2.8 },
        { type: "barcode", text: "6901234567892", leftMm: 26, topMm: 9.5, widthMm: 20, heightMm: 10.5, showText: false, format: "code128" },
        { type: "text", text: "6901234567892", leftMm: 25.5, topMm: 22, widthMm: 21, fontSizeMm: 2.5, textAlign: "center" },
      ],
    },
    {
      id: "barcode-label",
      kind: "business",
      title: "条码标签",
      description: "默认带标题、横线和居中条码布局。",
      suggestedName: "条码标签",
      labelType: "roll",
      widthMm: 70,
      heightMm: 40,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 70,
        height: 40,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [
        { type: "text", text: "库存编码标签", leftMm: 6, topMm: 4, widthMm: 58, fontSizeMm: 5, textAlign: "center", fontWeight: "bold" },
        { type: "line", x1Mm: 8, y1Mm: 10.5, x2Mm: 62, y2Mm: 10.5, strokeWidthMm: 0.4 },
        { type: "barcode", text: "INV-2026-04020", leftMm: 6, topMm: 13, widthMm: 58, heightMm: 15, showText: true, format: "code128" },
        { type: "text", text: "规格 / 型号", leftMm: 6, topMm: 33.5, widthMm: 58, fontSizeMm: 3.2, textAlign: "center" },
      ],
    },
    {
      id: "qrcode-label",
      kind: "business",
      title: "二维码标签",
      description: "默认带标题、二维码和说明文案。",
      suggestedName: "二维码标签",
      labelType: "roll",
      widthMm: 50,
      heightMm: 50,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 50,
        height: 50,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [
        { type: "text", text: "扫码查看详情", leftMm: 5, topMm: 4, widthMm: 40, fontSizeMm: 4.2, textAlign: "center", fontWeight: "bold" },
        { type: "qrcode", text: "https://labelnova.app", leftMm: 10, topMm: 12, sizeMm: 30, ecLevel: "M" },
        { type: "text", text: "LabelNova / Demo", leftMm: 7, topMm: 44, widthMm: 36, fontSizeMm: 3.2, textAlign: "center" },
      ],
    },
    {
      id: "shipping-waybill",
      kind: "business",
      title: "物流面单",
      description: "默认带抬头、收件信息、二维码和底部条码。",
      suggestedName: "物流面单",
      labelType: "roll",
      widthMm: 100,
      heightMm: 150,
      paper: {
        matchLabel: true,
        preset: "match",
        width: 100,
        height: 150,
        landscape: false,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        gapX: 0,
        gapY: 0,
      },
      print: { columns: 1, columnGap: 2 },
      content: [
        { type: "rect", leftMm: 4, topMm: 4, widthMm: 92, heightMm: 142, strokeWidthMm: 0.5 },
        { type: "text", text: "标准物流面单", leftMm: 8, topMm: 8, widthMm: 42, fontSizeMm: 6, fontWeight: "bold" },
        { type: "qrcode", text: "LDNV-2026-0001", leftMm: 69, topMm: 8, sizeMm: 18, ecLevel: "M" },
        { type: "line", x1Mm: 8, y1Mm: 30, x2Mm: 92, y2Mm: 30, strokeWidthMm: 0.4 },
        { type: "textbox", text: "收件人：张三\n电话：13800000000", leftMm: 8, topMm: 36, widthMm: 54, heightMm: 18, fontSizeMm: 4.2, lineHeight: 1.2 },
        { type: "textbox", text: "地址：上海市浦东新区张江高科技园区科苑路 88 号", leftMm: 8, topMm: 58, widthMm: 84, heightMm: 24, fontSizeMm: 4, lineHeight: 1.25 },
        { type: "line", x1Mm: 8, y1Mm: 92, x2Mm: 92, y2Mm: 92, strokeWidthMm: 0.4 },
        { type: "barcode", text: "YT202604200001", leftMm: 12, topMm: 100, widthMm: 76, heightMm: 18, showText: true, format: "code128" },
        { type: "textbox", text: "寄件人：LabelNova 仓库\n备注：易碎件，轻拿轻放", leftMm: 8, topMm: 124, widthMm: 84, heightMm: 14, fontSizeMm: 3.8, lineHeight: 1.2 },
      ],
    },
  ];

  function clone(value) {
    return JSON.parse(JSON.stringify(value));
  }

  function getLabelTemplates() {
    return clone(LABEL_TEMPLATES);
  }

  function getLabelTemplatesByKind(kind) {
    return getLabelTemplates().filter((template) => template.kind === kind);
  }

  function getLabelTemplateById(templateId) {
    const template = LABEL_TEMPLATES.find((item) => item.id === templateId);
    return template ? clone(template) : null;
  }

  function buildTemplateFormState(templateOrId) {
    const template =
      typeof templateOrId === "string" ? getLabelTemplateById(templateOrId) : clone(templateOrId);
    if (!template) return null;

    const paper = template.paper || {};
    const print = template.print || {};

    return {
      id: template.id,
      kind: template.kind,
      title: template.title,
      suggestedName: template.suggestedName || template.title,
      labelType: template.labelType || "roll",
      widthMm: template.widthMm,
      heightMm: template.heightMm,
      paperPreset: paper.preset || "match",
      paperWidthMm: paper.width || template.widthMm,
      paperHeightMm: paper.height || template.heightMm,
      landscape: !!paper.landscape,
      marginTopMm: paper.marginTop || 0,
      marginBottomMm: paper.marginBottom || 0,
      marginLeftMm: paper.marginLeft || 0,
      marginRightMm: paper.marginRight || 0,
      gapXmm: paper.gapX || 0,
      gapYmm: paper.gapY || 0,
      printColumns: print.columns || 1,
      printColumnGapMm: print.columnGap || 0,
      content: clone(template.content || []),
    };
  }

  function clampPercent(value) {
    if (!Number.isFinite(value)) return 0;
    return Math.max(0, Math.min(100, value));
  }

  function buildSheetPreviewItems(template) {
    const paper = template.paper || {};
    const paperWidth = Math.max(paper.width || template.widthMm || 0, 0.001);
    const paperHeight = Math.max(paper.height || template.heightMm || 0, 0.001);
    const marginTop = Math.max(paper.marginTop || 0, 0);
    const marginBottom = Math.max(paper.marginBottom || 0, 0);
    const marginLeft = Math.max(paper.marginLeft || 0, 0);
    const marginRight = Math.max(paper.marginRight || 0, 0);
    const gapX = Math.max(paper.gapX || 0, 0);
    const gapY = Math.max(paper.gapY || 0, 0);
    const labelWidth = Math.max(template.widthMm || 0, 0.001);
    const labelHeight = Math.max(template.heightMm || 0, 0.001);
    const cols = Math.max(1, Math.floor((paperWidth - marginLeft - marginRight + gapX) / (labelWidth + gapX)));
    const rows = Math.max(1, Math.floor((paperHeight - marginTop - marginBottom + gapY) / (labelHeight + gapY)));
    const items = [{ type: "sheet", left: 0, top: 0, width: 100, height: 100, cols, rows }];

    for (let row = 0; row < rows; row++) {
      for (let col = 0; col < cols; col++) {
        items.push({
          type: "cell",
          left: clampPercent(((marginLeft + col * (labelWidth + gapX)) / paperWidth) * 100),
          top: clampPercent(((marginTop + row * (labelHeight + gapY)) / paperHeight) * 100),
          width: clampPercent((labelWidth / paperWidth) * 100),
          height: clampPercent((labelHeight / paperHeight) * 100),
          emphasis: row === 0 && col === 0 ? "primary" : "secondary",
          index: row * cols + col + 1,
        });
      }
    }

    return items;
  }

  function getTemplatePreviewMode(template) {
    if (template.kind === "blank" && template.labelType === "flat" && template.paper && !template.paper.matchLabel) {
      return "sheet";
    }
    return "content";
  }

  function buildPreviewItemForDescriptor(descriptor, template) {
    const templateWidth = Math.max(template.widthMm || 0, 0.001);
    const templateHeight = Math.max(template.heightMm || 0, 0.001);
    const scaleX = 100 / templateWidth;
    const scaleY = 100 / templateHeight;

    if (descriptor.type === "text" || descriptor.type === "textbox") {
      return {
        type: "text",
        left: clampPercent((descriptor.leftMm || 0) * scaleX),
        top: clampPercent((descriptor.topMm || 0) * scaleY),
        width: clampPercent((descriptor.widthMm || template.widthMm * 0.4) * scaleX),
        height: clampPercent(Math.max((descriptor.fontSizeMm || 4) * 1.8, 4) * scaleY),
        text: descriptor.text || "",
        align: descriptor.textAlign || "left",
      };
    }

    if (descriptor.type === "barcode") {
      return {
        type: "barcode",
        left: clampPercent((descriptor.leftMm || 0) * scaleX),
        top: clampPercent((descriptor.topMm || 0) * scaleY),
        width: clampPercent((descriptor.widthMm || template.widthMm * 0.6) * scaleX),
        height: clampPercent((descriptor.heightMm || template.heightMm * 0.2) * scaleY),
      };
    }

    if (descriptor.type === "qrcode") {
      const sizeMm = descriptor.sizeMm || 20;
      return {
        type: "qrcode",
        left: clampPercent((descriptor.leftMm || 0) * scaleX),
        top: clampPercent((descriptor.topMm || 0) * scaleY),
        width: clampPercent(sizeMm * scaleX),
        height: clampPercent(sizeMm * scaleY),
      };
    }

    if (descriptor.type === "rect") {
      return {
        type: "rect",
        left: clampPercent((descriptor.leftMm || 0) * scaleX),
        top: clampPercent((descriptor.topMm || 0) * scaleY),
        width: clampPercent((descriptor.widthMm || template.widthMm * 0.5) * scaleX),
        height: clampPercent((descriptor.heightMm || template.heightMm * 0.4) * scaleY),
      };
    }

    if (descriptor.type === "line") {
      const x1 = (descriptor.x1Mm || 0) * scaleX;
      const y1 = (descriptor.y1Mm || 0) * scaleY;
      const x2 = (descriptor.x2Mm || 0) * scaleX;
      const y2 = (descriptor.y2Mm || 0) * scaleY;
      return {
        type: "line",
        left: clampPercent(Math.min(x1, x2)),
        top: clampPercent(Math.min(y1, y2)),
        width: Math.max(Math.abs(x2 - x1), 0.6),
        height: Math.max(Math.abs(y2 - y1), 0.6),
      };
    }

    if (descriptor.type === "circle") {
      const diameter = descriptor.diameterMm || 0;
      return {
        type: "circle",
        left: clampPercent((descriptor.leftMm || 0) * scaleX),
        top: clampPercent((descriptor.topMm || 0) * scaleY),
        width: clampPercent(diameter * scaleX),
        height: clampPercent(diameter * scaleY),
      };
    }

    return null;
  }

  function buildTemplatePreviewItems(templateOrId) {
    const template =
      typeof templateOrId === "string" ? getLabelTemplateById(templateOrId) : clone(templateOrId);
    if (!template) return [];
    if (getTemplatePreviewMode(template) === "sheet") {
      return buildSheetPreviewItems(template);
    }
    if (!Array.isArray(template.content)) return [];

    return template.content
      .map((descriptor) => buildPreviewItemForDescriptor(descriptor, template))
      .filter(Boolean);
  }

  const api = {
    LABEL_TEMPLATES: getLabelTemplates(),
    getLabelTemplates,
    getLabelTemplatesByKind,
    getLabelTemplateById,
    buildTemplateFormState,
    getTemplatePreviewMode,
    buildTemplatePreviewItems,
  };

  if (typeof module !== "undefined" && module.exports) {
    module.exports = api;
  }

  global.LabelNovaTemplates = api;
})(
  typeof window !== "undefined"
    ? window
    : typeof globalThis !== "undefined"
      ? globalThis
      : typeof global !== "undefined"
        ? global
        : this
);
