// catalog.jsx — WQL Light Pipe Clamp catalog, series G2–G30.

const { useState: useStateK, useMemo: useMemoK } = React;

// ── Series ────────────────────────────────────────────────────────────────
const SERIES = [
  // Welded base plate
  { id: "G2",  label: "WQL·G2",  kind: "standard", bolt: "Hex socket", baseType: "welded",      hasCover: false,
    descZH: "内六角螺栓 + 管夹体 + 焊接底板",               descEN: "Hex socket screw + clamp body + welded base plate" },
  { id: "G3",  label: "WQL·G3",  kind: "twin",     bolt: "Outer hex",  baseType: "welded",      hasCover: true,
    descZH: "外六角螺栓 + 管夹体 + 盖板 + 焊接底板",         descEN: "Outer-hex screw + clamp body + cover plate + welded base plate" },
  // Long welded base plate
  { id: "G4",  label: "WQL·G4",  kind: "heavy",    bolt: "Slotted",    baseType: "long-welded", hasCover: false,
    descZH: "开槽螺栓 + 管夹体 + 长焊接底板",               descEN: "Slotted bolt + clamp body + long welded base plate" },
  { id: "G5",  label: "WQL·G5",  kind: "standard", bolt: "Hex socket", baseType: "long-welded", hasCover: false,
    descZH: "内六角螺栓 + 管夹体 + 长焊接底板",             descEN: "Hex socket screw + clamp body + long welded base plate" },
  { id: "G6",  label: "WQL·G6",  kind: "twin",     bolt: "Outer hex",  baseType: "long-welded", hasCover: true,
    descZH: "外六角螺栓 + 管夹体 + 盖板 + 长焊接底板",       descEN: "Outer-hex screw + clamp body + cover plate + long welded base plate" },
  // Rail nut
  { id: "G9",  label: "WQL·G9",  kind: "heavy",    bolt: "Slotted",    baseType: "rail-nut",    hasCover: false,
    descZH: "开槽螺栓 + 管夹体 + 导轨螺母",                 descEN: "Slotted bolt + clamp body + rail nut" },
  { id: "G10", label: "WQL·G10", kind: "standard", bolt: "Hex socket", baseType: "rail-nut",    hasCover: false,
    descZH: "内六角螺栓 + 管夹体 + 导轨螺母",               descEN: "Hexagon socket screw + clamp body + rail nut" },
  { id: "G12", label: "WQL·G12", kind: "twin",     bolt: "Outer hex",  baseType: "rail-nut",    hasCover: true,
    descZH: "外六角螺栓 + 管夹体 + 盖板 + 导轨螺母",         descEN: "Outer-hex screw + clamp body + cover plate + rail nut" },
  // Clamp body only (no base)
  { id: "G13", label: "WQL·G13", kind: "heavy",    bolt: "Slotted",    baseType: "none",        hasCover: false,
    descZH: "开槽螺栓 + 管夹体",                           descEN: "Slotted bolt + clamp body" },
  { id: "G14", label: "WQL·G14", kind: "standard", bolt: "Hex socket", baseType: "none",        hasCover: false,
    descZH: "内六角螺栓 + 管夹体",                         descEN: "Hexagon socket screw + clamp body" },
  { id: "G16", label: "WQL·G16", kind: "twin",     bolt: "Outer hex",  baseType: "none",        hasCover: true,
    descZH: "外六角螺栓 + 管夹体 + 盖板",                   descEN: "Outer-hex screw + clamp body + cover plate" },
  // Stacking bolt (叠装型)
  { id: "G18", label: "WQL·G18", kind: "standard", bolt: "Stacking",   baseType: "stacking",    hasCover: false,
    descZH: "长头螺栓 + 管夹体 + 保险板",                   descEN: "Stacking bolt + clamp body + safety guard" },
  // Shockproof (防震，limited OD range)
  { id: "G30", label: "WQL·G30", kind: "twin",     bolt: "Outer hex",  baseType: "shockproof",  hasCover: true,
    descZH: "外六角螺栓 + 管夹体 + 盖板 + 防震圈 + 焊接底板", descEN: "Outer-hex + clamp body + cover plate + shockproof ring + welded base plate" },
];

// ── Pipe ODs per group (L0–L8) ────────────────────────────────────────────
const GROUP_ODS = {
  L0: [6, 6.4, 8, 9.5, 10, 12],
  L1: [6, 6.4, 8, 9.5, 10, 12],
  L2: [12.7, 13.5, 14, 15, 16, 17.2, 18],
  L3: [19, 20, 21.3, 22, 25],
  L4: [26.9, 28, 30],
  L5: [32, 33.7, 35, 38, 40, 42],
  L6: [44.5, 48.3, 50.8],
  L7: [57.2, 60.3, 63.5, 70, 73],
  L8: [76.1, 88.9, 102],
};

// G30 shockproof: limited OD range (ø6–ø32 mm)
const G30_GROUP_ODS = {
  L1: [6, 8, 10, 12],
  L2: [12.7, 14, 15, 16, 18],
  L3: [19, 20, 21.3, 22, 25],
  L4: [28, 30],
  L5: [32],
};

// ── Clamp body dims: L1, L2, H, S, B  (identical across all series) ───────
const CLAMP_BODY = {
  L0: { L1: 28,  L2: null, H: 27,  S: 0.4, B: 30 },
  L1: { L1: 37,  L2: 20,   H: 27,  S: 0.4, B: 30 },
  L2: { L1: 42,  L2: 26,   H: 33,  S: 0.6, B: 30 },
  L3: { L1: 50,  L2: 33,   H: 36,  S: 0.6, B: 30 },
  L4: { L1: 59,  L2: 40,   H: 42,  S: 0.6, B: 30 },
  L5: { L1: 71,  L2: 52,   H: 58,  S: 0.8, B: 30 },
  L6: { L1: 86,  L2: 66,   H: 66,  S: 0.8, B: 30 },
  L7: { L1: 121, L2: 94,   H: 93,  S: 0.8, B: 30 },
  L8: { L1: 147, L2: 120,  H: 118, S: 0.8, B: 30 },
};

// ── Welded base plate dims: L1, L2, B, S, H, D  (G2, G3, G30) ─────────────
const WELDED_BASE = {
  L0: { L1: 28,  L2: null, B: 30, S: 3, H: 6.5, D: 12 },
  L1: { L1: 36,  L2: 20,   B: 30, S: 3, H: 6.5, D: 12 },
  L2: { L1: 42,  L2: 26,   B: 30, S: 3, H: 6.5, D: 12 },
  L3: { L1: 50,  L2: 33,   B: 30, S: 3, H: 6.5, D: 12 },
  L4: { L1: 60,  L2: 40,   B: 30, S: 3, H: 6.5, D: 12 },
  L5: { L1: 71,  L2: 52,   B: 30, S: 3, H: 6.5, D: 12 },
  L6: { L1: 88,  L2: 66,   B: 30, S: 3, H: 6.5, D: 12 },
  L7: { L1: 122, L2: 94,   B: 30, S: 5, H: 6.5, D: 12 },
  L8: { L1: 148, L2: 120,  B: 30, S: 5, H: 6.5, D: 12 },
};

// ── Long welded base plate dims: L1, L2, L3, S, D  (G4, G5) ─────────────
const LONG_BASE = {
  L0: { L1: 58,  L2: null, L3: 44,  S: 3, D: 12 },
  L1: { L1: 64,  L2: 20,   L3: 50,  S: 3, D: 12 },
  L2: { L1: 70,  L2: 26,   L3: 56,  S: 3, D: 12 },
  L3: { L1: 78,  L2: 33,   L3: 64,  S: 3, D: 12 },
  L4: { L1: 87,  L2: 40,   L3: 73,  S: 3, D: 12 },
  L5: { L1: 100, L2: 52,   L3: 86,  S: 3, D: 12 },
  L6: { L1: 115, L2: 66,   L3: 100, S: 3, D: 12 },
  L7: { L1: 150, L2: 94,   L3: 136, S: 5, D: 12 },
  L8: { L1: 178, L2: 120,  L3: 162, S: 3, D: 12 },
};

// G6 differs from G4/G5 only at L8 (plate thickness S: 5)
const LONG_BASE_G6 = { ...LONG_BASE, L8: { L1: 178, L2: 120, L3: 162, S: 5, D: 12 } };

// ── Rail nut dims (G9, G10, G12 — constant for all groups) ───────────────
const RAIL_NUT = { L: 26, B: 10.4, H1: 13, H2: 5, D: 12 };

// ── Cover plate dims: L1, L2, S  (G3, G6, G12, G16, G30) ─────────────────
const COVER_PLATE = {
  L0: { L1: 28,   L2: null, S: 3 },
  L1: { L1: 36,   L2: 20,   S: 3 },
  L2: { L1: 40.5, L2: 26,   S: 3 },
  L3: { L1: 48,   L2: 33,   S: 3 },
  L4: { L1: 57,   L2: 40,   S: 3 },
  L5: { L1: 70,   L2: 52,   S: 3 },
  L6: { L1: 86,   L2: 66,   S: 3 },
  L7: { L1: 121,  L2: 94,   S: 5 },
  L8: { L1: 147,  L2: 120,  S: 5 },
};

// ── G18 safety locking plate dims: L, S  (per group) ─────────────────────
const SAFETY_PLATE = {
  L0: { L: 28,  S: 3 }, L1: { L: 34,  S: 3 }, L2: { L: 40,  S: 3 },
  L3: { L: 47,  S: 3 }, L4: { L: 56,  S: 3 }, L5: { L: 69,  S: 3 },
  L6: { L: 85,  S: 3 }, L7: { L: 117, S: 3 }, L8: { L: 143, S: 3 },
};

// ── G18 stacking bolt dims: L1, L2, L3  (per group) ──────────────────────
const STACKING_BOLT = {
  L0: { L1: 20,  L2: 34,  L3: 12 }, L1: { L1: 20,  L2: 34,  L3: 12 },
  L2: { L1: 25,  L2: 39,  L3: 12 }, L3: { L1: 30,  L2: 44,  L3: 12 },
  L4: { L1: 35,  L2: 49,  L3: 12 }, L5: { L1: 50,  L2: 64,  L3: 12 },
  L6: { L1: 60,  L2: 74,  L3: 12 }, L7: { L1: 85,  L2: 99,  L3: 12 },
  L8: { L1: 110, L2: 124, L3: 12 },
};

// ── Bolt size per series per group ────────────────────────────────────────
const BOLTS_STD  = { L0:"M6×20", L1:"M6×20", L2:"M6×25", L3:"M6×30", L4:"M6×35", L5:"M6×50", L6:"M6×60", L7:"M6×90",  L8:"M6×110" };
const BOLTS_CVR  = { L0:"M6×30", L1:"M6×30", L2:"M6×35", L3:"M6×40", L4:"M6×45", L5:"M6×60", L6:"M6×70", L7:"M6×90",  L8:"M6×110" };
const BOLTS_STCK = { L0:"Stack", L1:"Stack", L2:"Stack", L3:"Stack", L4:"Stack", L5:"Stack", L6:"Stack", L7:"Stack", L8:"Stack" };

const BOLTS = {
  G2: BOLTS_STD, G4: BOLTS_STD, G5: BOLTS_STD,
  G9: BOLTS_STD, G10:BOLTS_STD, G13:BOLTS_STD, G14:BOLTS_STD,
  G3: BOLTS_CVR, G6: BOLTS_CVR, G12:BOLTS_CVR, G16:BOLTS_CVR,
  G18:BOLTS_STCK,
  // G30 bolt determined by housing group in makeProducts()
};

// ── Order-code generator ──────────────────────────────────────────────────
function makePN(seriesId, group, od) {
  const g = group.replace("L", "");
  const intPart  = Math.floor(od);
  const fracPart = od % 1;
  let odStr;
  if (fracPart === 0) {
    odStr = intPart < 100 ? String(intPart).padStart(2, "0") : String(intPart);
  } else {
    const intFmt = intPart < 10 ? "0" + intPart : String(intPart);
    odStr = intFmt + String(Math.round(fracPart * 10) / 10).slice(1);
  }
  return `WQL*${seriesId}-${g}${odStr}`;
}

function makeProducts() {
  const out = [];

  // ── Standard series (all groups L0–L8) ─────────────────────────────────
  for (const s of SERIES.filter(s => s.id !== "G30")) {
    for (const grp of ["L0","L1","L2","L3","L4","L5","L6","L7","L8"]) {
      const ods  = GROUP_ODS[grp];
      const cb   = CLAMP_BODY[grp];
      const bolt = BOLTS[s.id][grp];
      const base =
        s.baseType === "welded"      ? WELDED_BASE[grp] :
        s.baseType === "long-welded" ? (s.id === "G6" ? LONG_BASE_G6[grp] : LONG_BASE[grp]) :
        s.baseType === "rail-nut"    ? RAIL_NUT :
        null;
      const cover = s.hasCover ? COVER_PLATE[grp] : null;

      for (const od of ods) {
        const extra = s.id === "G18"
          ? { safetyPlate: SAFETY_PLATE[grp], stackingBolt: STACKING_BOLT[grp] }
          : {};
        out.push({
          pn:          makePN(s.id, grp, od),
          series:      s.id,
          seriesLabel: s.label,
          seriesKind:  s.kind,
          group:       grp,
          od,
          bolt,
          boltType:    s.bolt,
          baseType:    s.baseType,
          hasCover:    s.hasCover,
          clampBody:   cb,
          base,
          cover,
          descZH:      s.descZH,
          descEN:      s.descEN,
          stock:       Math.max(20, (150 - Math.floor(od)) * 4 + 100),
          leadDays:    od >= 60 ? 14 : 0,
          ...extra,
        });
      }
    }
  }

  // ── G30 shockproof (housing-based, limited OD range ø6–ø32) ────────────
  const g30 = SERIES.find(s => s.id === "G30");
  for (const [grp, ods] of Object.entries(G30_GROUP_ODS)) {
    for (const od of ods) {
      const housing  = od <= 19 ? "L4" : "L6";
      const bolt     = housing === "L4" ? "M6×45" : "M6×70";
      out.push({
        pn:          makePN("G30", grp, od),
        series:      "G30",
        seriesLabel: g30.label,
        seriesKind:  g30.kind,
        group:       grp,
        od,
        bolt,
        boltType:    g30.bolt,
        baseType:    g30.baseType,
        hasCover:    true,
        clampBody:   CLAMP_BODY[housing],
        base:        WELDED_BASE[housing],
        cover:       COVER_PLATE[housing],
        descZH:      g30.descZH,
        descEN:      g30.descEN,
        housingGroup: housing,
        stock:       Math.max(20, (150 - Math.floor(od)) * 4 + 100),
        leadDays:    0,
      });
    }
  }

  return out;
}

const PRODUCTS = makeProducts();

// ── Display labels ────────────────────────────────────────────────────────
const BASE_LABELS = {
  "welded":      "Welded · 焊接底板",
  "long-welded": "Long welded · 长焊接底板",
  "rail-nut":    "Rail nut · 导轨螺母",
  "none":        "Body only · 纯管夹",
  "stacking":    "Stacking · 长头螺栓",
  "shockproof":  "Shockproof · 防震型",
};
const BASE_LABEL_SHORT = {
  "welded":      "Welded",
  "long-welded": "Long welded",
  "rail-nut":    "Rail nut",
  "none":        "Body only",
  "stacking":    "Stacking",
  "shockproof":  "Shockproof",
};

// ── Accessory components ──────────────────────────────────────────────────
const ACCESSORIES = [
  // WQL-C: Twin welded base plate 双联焊接底板
  { pn:"WQL-C0", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:0, d:null, a:30, e:61,  δ:3 },
  { pn:"WQL-C1", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:1, d:20,   a:35, e:69,  δ:3 },
  { pn:"WQL-C2", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:2, d:26,   a:43, e:86,  δ:3 },
  { pn:"WQL-C3", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:3, d:33,   a:52, e:104, δ:3 },
  { pn:"WQL-C4", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:4, d:40,   a:60, e:117, δ:3 },
  { pn:"WQL-C5", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:5, d:52,   a:75, e:145, δ:3 },
  { pn:"WQL-C6", type:"twin-base",  nameEN:"Twin welded base plate",     nameZH:"双联焊接底板", size:6, d:66,   a:90, e:176, δ:3 },
  // WQL-D: Multiple welded base plate 多联焊接底板
  { pn:"WQL-D0", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:0, links:10, d:null, a:30, e:298, δ:3 },
  { pn:"WQL-D1", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:1, links:10, d:20,   a:35, e:349, δ:3 },
  { pn:"WQL-D2", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:2, links:10, d:26,   a:43, e:427, δ:3 },
  { pn:"WQL-D3", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:3, links:10, d:33,   a:52, e:516, δ:3 },
  { pn:"WQL-D4", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:4, links:5,  d:40,   a:60, e:297, δ:3 },
  { pn:"WQL-D5", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:5, links:5,  d:52,   a:75, e:370, δ:3 },
  { pn:"WQL-D6", type:"multi-base", nameEN:"Multiple welded base plate", nameZH:"多联焊接底板", size:6, links:5,  d:66,   a:90, e:446, δ:3 },
  // WQL-E: Mounting rail 安装导轨
  { pn:"WQL-E1", type:"rail",       nameEN:"Mounting rail",              nameZH:"安装导轨",     h:11 },
  { pn:"WQL-E2", type:"rail",       nameEN:"Mounting rail",              nameZH:"安装导轨",     h:14 },
  { pn:"WQL-E3", type:"rail",       nameEN:"Mounting rail",              nameZH:"安装导轨",     h:30 },
  // WQL-F: Rail nut 导轨螺母
  { pn:"WQL-F",  type:"rail-nut",   nameEN:"Rail nut",                   nameZH:"导轨螺母",     L:26, B:10.4, H1:13, H2:5 },
  // WQL-G: Cover plate 盖板
  { pn:"WQL-G0", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:0, L1:28,   L2:null, S:3 },
  { pn:"WQL-G1", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:1, L1:36,   L2:20,   S:3 },
  { pn:"WQL-G2", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:2, L1:40.5, L2:26,   S:3 },
  { pn:"WQL-G3", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:3, L1:48,   L2:33,   S:3 },
  { pn:"WQL-G4", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:4, L1:57,   L2:40,   S:3 },
  { pn:"WQL-G5", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:5, L1:70,   L2:52,   S:3 },
  { pn:"WQL-G6", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:6, L1:86,   L2:66,   S:3 },
  { pn:"WQL-G7", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:7, L1:121,  L2:94,   S:5 },
  { pn:"WQL-G8", type:"cover",      nameEN:"Cover plate",                nameZH:"盖板",         size:8, L1:147,  L2:120,  S:5 },
  // WQL-H: Overlapping bolt 叠加螺栓
  { pn:"WQL-H0", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:0, L1:20,  L2:34  },
  { pn:"WQL-H1", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:1, L1:20,  L2:34  },
  { pn:"WQL-H2", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:2, L1:25,  L2:39  },
  { pn:"WQL-H3", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:3, L1:30,  L2:44  },
  { pn:"WQL-H4", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:4, L1:35,  L2:49  },
  { pn:"WQL-H5", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:5, L1:50,  L2:64  },
  { pn:"WQL-H6", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:6, L1:60,  L2:74  },
  { pn:"WQL-H7", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:7, L1:85,  L2:99  },
  { pn:"WQL-H8", type:"bolt-stack", nameEN:"Overlapping bolt",           nameZH:"叠加螺栓",     size:8, L1:110, L2:124 },
  // WQL-1: Locking plate 防松盖板
  { pn:"WQL-1",  type:"locking",    nameEN:"Locking plate",              nameZH:"防松盖板" },
];

// ── WQT Twin Pipe Clamp ───────────────────────────────────────────────────
const WQT_SERIES = [
  { id: "G1", label: "WQT·G1", bolt: "Outer hex",
    descZH: "外六角螺栓 + 双管夹体 + 盖板 + 焊接底板",
    descEN: "Outer-hex screw + twin body + cover plate + welded base" },
  { id: "G3", label: "WQT·G3", bolt: "Hex socket",
    descZH: "内六角螺栓 + 双管夹体 + 盖板 + 焊接底板",
    descEN: "Hex socket screw + twin body + cover plate + welded base" },
];

const WQT_MATERIALS = [
  { code: "PG", nameEN: "PP grooved",       nameZH: "聚丙烯凸槽型",   temp: "−30 to +90 °C" },
  { code: "PS", nameEN: "PP smooth",         nameZH: "聚丙烯光滑型",   temp: "−30 to +90 °C" },
  { code: "NG", nameEN: "Nylon grooved",     nameZH: "增强尼龙凸槽型", temp: "−40 to +120 °C" },
  { code: "NS", nameEN: "Nylon smooth",      nameZH: "增强尼龙光滑型", temp: "−40 to +120 °C" },
  { code: "LG", nameEN: "Al alloy grooved",  nameZH: "铝合金凸槽型",   temp: "−50 to +300 °C" },
  { code: "GG", nameEN: "Steel grooved",     nameZH: "钢制凸槽型",     temp: "−80 to +500 °C" },
  { code: "BG", nameEN: "SS grooved",        nameZH: "不锈钢凸槽型",   temp: "−80 to +500 °C" },
];

const WQT_GROUP_ODS = {
  T1: [6, 6.4, 8, 9.5, 10, 12],
  T2: [12.7, 13.5, 14, 16, 17.2, 18],
  T3: [19, 20, 21.3, 22, 25],
  T4: [26.9, 28, 30],
  T5: [32, 33.7, 35, 38, 40, 42],
};

// Twin clamp body: L1, L2, H, S, B
const WQT_CLAMP_BODY = {
  T1: { L1: 36,  L2: 20, H: 27, S: 0.8, B: 30 },
  T2: { L1: 53,  L2: 29, H: 27, S: 0.8, B: 30 },
  T3: { L1: 67,  L2: 36, H: 37, S: 0.8, B: 30 },
  T4: { L1: 80,  L2: 45, H: 40, S: 0.8, B: 30 },
  T5: { L1: 106, L2: 56, H: 53, S: 0.8, B: 30 },
};

// Cover plate: L, H, S, D
const WQT_COVER = {
  T1: { L: 34,  H: 7, S: 3, D: 7 },
  T2: { L: 52,  H: 7, S: 3, D: 9 },
  T3: { L: 65,  H: 7, S: 3, D: 9 },
  T4: { L: 79,  H: 7, S: 3, D: 9 },
  T5: { L: 102, H: 7, S: 3, D: 9 },
};

// Welded base: L, S, H, D, G (bolt thread)
const WQT_BASE = {
  T1: { L: 37,  S: 3, H: 6, D: 12, G: "M6" },
  T2: { L: 55,  S: 5, H: 6, D: 14, G: "M8" },
  T3: { L: 70,  S: 5, H: 6, D: 14, G: "M8" },
  T4: { L: 85,  S: 5, H: 6, D: 14, G: "M8" },
  T5: { L: 110, S: 5, H: 6, D: 14, G: "M8" },
};

const WQT_BOLTS = { T1: "M6×35", T2: "M8×35", T3: "M8×45", T4: "M8×50", T5: "M8×60" };

function makeWQTPN(seriesId, group, od) {
  const g = group.replace("T", "");
  const intPart  = Math.floor(od);
  const fracPart = od % 1;
  let odStr;
  if (fracPart === 0) {
    odStr = intPart < 100 ? String(intPart).padStart(2, "0") : String(intPart);
  } else {
    const intFmt = intPart < 10 ? "0" + intPart : String(intPart);
    odStr = intFmt + String(Math.round(fracPart * 10) / 10).slice(1);
  }
  return `WQT*${seriesId}-${g}${odStr}`;
}

function makeWQTProducts() {
  const out = [];
  for (const s of WQT_SERIES) {
    for (const [grp, ods] of Object.entries(WQT_GROUP_ODS)) {
      const cb   = WQT_CLAMP_BODY[grp];
      const cvr  = WQT_COVER[grp];
      const base = WQT_BASE[grp];
      const bolt = WQT_BOLTS[grp];
      for (const od of ods) {
        out.push({
          pn:          makeWQTPN(s.id, grp, od),
          family:      "WQT",
          series:      s.id,
          seriesLabel: s.label,
          group:       grp,
          od,
          bolt,
          boltType:    s.bolt,
          clampBody:   cb,
          cover:       cvr,
          base,
          descZH:      s.descZH,
          descEN:      s.descEN,
        });
      }
    }
  }
  return out;
}

const PRODUCTS_WQT = makeWQTProducts();

// ── Initial filter state ──────────────────────────────────────────────────
const INIT_SERIES_F = Object.fromEntries(SERIES.map(s => [s.id, true]));

function Catalog({ go }) {
  const t = useT();
  const [seriesF, setSeriesF] = useStateK(INIT_SERIES_F);
  const [groups,  setGroups]  = useStateK({});
  const [baseF,   setBaseF]   = useStateK({});
  const [coverF,  setCoverF]  = useStateK(false);
  const [view,    setView]    = useStateK("grid");
  const [sort,    setSort]    = useStateK("od-asc");
  const [page,    setPage]    = useStateK(1);
  const [odMin,   setOdMin]   = useStateK("");
  const [odMax,   setOdMax]   = useStateK("");

  const filtered = useMemoK(() => {
    let r = PRODUCTS.filter(p => seriesF[p.series]);
    const gKeys = Object.keys(groups).filter(k => groups[k]);
    if (gKeys.length) r = r.filter(p => gKeys.includes(p.group));
    const bKeys = Object.keys(baseF).filter(k => baseF[k]);
    if (bKeys.length) r = r.filter(p => bKeys.includes(p.baseType));
    if (coverF)  r = r.filter(p => p.hasCover);
    if (odMin)   r = r.filter(p => p.od >= Number(odMin));
    if (odMax)   r = r.filter(p => p.od <= Number(odMax));
    r = r.slice();
    if (sort === "od-asc")  r.sort((a, b) => a.od - b.od);
    if (sort === "od-desc") r.sort((a, b) => b.od - a.od);
    if (sort === "pn")      r.sort((a, b) => a.pn.localeCompare(b.pn));
    return r;
  }, [seriesF, groups, baseF, coverF, sort, odMin, odMax]);

  const perPage   = view === "grid" ? 9 : 14;
  const pageCount = Math.max(1, Math.ceil(filtered.length / perPage));
  const pageItems = filtered.slice((page - 1) * perPage, page * perPage);

  function toggle(setter, key) {
    setter(s => ({ ...s, [key]: !s[key] }));
    setPage(1);
  }

  function resetAll() {
    setSeriesF(INIT_SERIES_F);
    setGroups({});
    setBaseF({});
    setCoverF(false);
    setOdMin("");
    setOdMax("");
    setPage(1);
  }

  return (
    <>
      <div className="wrap-wide">
        <div className="crumb">
          <a href="#" onClick={(e) => { e.preventDefault(); go("home"); }}>{t("cg.home")}</a>
          <span className="sep">/</span>
          <a href="#">{t("cg.products")}</a>
          <span className="sep">/</span>
          <span style={{ color: "var(--ink)" }}>WQL Light Pipe Clamp</span>
        </div>

        <section className="cat-hero">
          <span className="chip chip--accent" style={{ marginBottom: 20 }}>
            <span className="dot"></span> G2 · G3 · G4 · G5 · G6 · G9 · G10 · G12 · G13 · G14 · G16 · G18 · G30
          </span>
          <h1 className="display-1">WQL Light Pipe Clamp — 轻型管夹</h1>
          <p className="blurb">
            {PRODUCTS.length} SKUs across {SERIES.length} series. Pipe OD ø6–ø102 mm (G30: ø6–ø32 mm).
            Mounting: welded base · long welded · rail nut · body only · stacking · shockproof.
          </p>
          <div className="summary">
            <div className="item"><div className="k">Total SKUs</div><div className="v">{PRODUCTS.length}</div></div>
            <div className="item"><div className="k">OD Range</div><div className="v">6 – 102<span className="mono" style={{ fontWeight:500, fontSize:13, color:"var(--muted)" }}> mm</span></div></div>
            <div className="item"><div className="k">Groups</div><div className="v">L0 – L8</div></div>
            <div className="item"><div className="k">Series</div><div className="v">{SERIES.length}</div></div>
          </div>
        </section>

        <section className="catalog-body">
          <aside>
            <div className="filter-block">
              <div className="row between center" style={{ marginBottom: 8 }}>
                <h5 style={{ margin: 0 }}>{t("cg.refine")}</h5>
                <button className="mono" onClick={resetAll}
                  style={{ background:"none", border:"none", color:"var(--accent)", fontSize:11, letterSpacing:".04em", padding:0, cursor:"pointer" }}
                >{t("cg.reset")}</button>
              </div>
              <div className="mono" style={{ fontSize:11, color:"var(--muted)" }}>
                {filtered.length} {t("cg.matches_of")} {PRODUCTS.length} {t("cg.match")}
              </div>
            </div>

            <div className="filter-block">
              <h5>{t("cg.f_series")}</h5>
              <div className="filter-list">
                {SERIES.map(s => (
                  <label key={s.id}>
                    <input type="checkbox" checked={!!seriesF[s.id]} onChange={() => toggle(setSeriesF, s.id)} />
                    {s.label}
                    <span className="ct">{PRODUCTS.filter(p => p.series === s.id).length}</span>
                  </label>
                ))}
              </div>
            </div>

            <div className="filter-block">
              <h5>{t("cg.f_od")}</h5>
              <div className="range-row">
                <input type="number" placeholder="min" value={odMin} onChange={(e) => { setOdMin(e.target.value); setPage(1); }} />
                <span className="dash">—</span>
                <input type="number" placeholder="max" value={odMax} onChange={(e) => { setOdMax(e.target.value); setPage(1); }} />
              </div>
              <div className="mono" style={{ fontSize:10, color:"var(--muted)", marginTop:8 }}>mm · 6 – 102</div>
            </div>

            <div className="filter-block">
              <h5>{t("cg.f_group")}</h5>
              <div className="filter-list">
                {["L0","L1","L2","L3","L4","L5","L6","L7","L8"].map(g => (
                  <label key={g}>
                    <input type="checkbox" checked={!!groups[g]} onChange={() => toggle(setGroups, g)} />
                    {g}
                    <span className="ct">{PRODUCTS.filter(p => p.group === g).length}</span>
                  </label>
                ))}
              </div>
            </div>

            <div className="filter-block">
              <h5>Mounting type</h5>
              <div className="filter-list">
                {Object.entries(BASE_LABELS).map(([v, l]) => (
                  <label key={v}>
                    <input type="checkbox" checked={!!baseF[v]} onChange={() => toggle(setBaseF, v)} />
                    {l}
                    <span className="ct">{PRODUCTS.filter(p => p.baseType === v).length}</span>
                  </label>
                ))}
              </div>
            </div>

            <div className="filter-block">
              <h5>Accessories</h5>
              <div className="filter-list">
                <label>
                  <input type="checkbox" checked={coverF} onChange={() => { setCoverF(v => !v); setPage(1); }} />
                  With cover plate · 带盖板
                  <span className="ct">{PRODUCTS.filter(p => p.hasCover).length}</span>
                </label>
              </div>
            </div>
          </aside>

          <div className="catalog-main">
            <div className="catalog-toolbar">
              <div className="catalog-count">
                {t("cg.showing")} <strong>{(page-1)*perPage+1}–{Math.min(page*perPage, filtered.length)}</strong> {t("cg.of")} <strong>{filtered.length}</strong> · {t("cg.sorted")}
              </div>
              <div className="right">
                <select className="select" value={sort} onChange={(e) => setSort(e.target.value)}>
                  <option value="od-asc">{t("cg.sort_od_asc")}</option>
                  <option value="od-desc">{t("cg.sort_od_desc")}</option>
                  <option value="pn">{t("cg.sort_pn")}</option>
                </select>
                <div className="view-toggle">
                  <button className={view==="grid"?"on":""} onClick={()=>{setView("grid");setPage(1);}} title="Grid"><IconGrid /></button>
                  <button className={view==="list"?"on":""} onClick={()=>{setView("list");setPage(1);}} title="Table"><IconList /></button>
                </div>
              </div>
            </div>

            {view === "grid" ? (
              <div className="prod-grid">
                {pageItems.map(p => (
                  <div key={p.pn} className="prod-card" onClick={() => go("product")}>
                    <div className="tags">
                      {p.leadDays === 0 && <span className="chip">{t("cg.in_stock")}</span>}
                      {p.hasCover && <span className="chip">Cover</span>}
                      {p.baseType === "shockproof" && <span className="chip">防震</span>}
                    </div>
                    <div className="pic"><ClampArt kind={p.seriesKind} /></div>
                    <div className="pn">{p.pn}</div>
                    <div className="name">{p.seriesLabel} · {p.group} · ø{p.od} mm</div>
                    <div className="specs">
                      <div className="k">Mounting</div>
                      <div className="v">{BASE_LABEL_SHORT[p.baseType]}</div>
                      <div className="k">Bolt</div>
                      <div className="v">{p.bolt}</div>
                      <div className="k">CB L1×H</div>
                      <div className="v">{p.clampBody.L1}×{p.clampBody.H}</div>
                      <div className="k">OD</div>
                      <div className="v">ø{p.od} mm</div>
                    </div>
                    <div className="bottom">
                      <span className="price">{t("cg.stock")} · {p.stock} {t("cg.pcs")}</span>
                      <span className="link-arrow" style={{ fontSize:12, padding:0 }}>{t("cat.view")} <IconArrow size={12} /></span>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <table className="prod-table">
                <thead>
                  <tr>
                    <th></th>
                    <th>{t("cg.th_pn")}</th>
                    <th>Series</th>
                    <th>Group</th>
                    <th style={{ textAlign:"right" }}>OD (mm)</th>
                    <th>Mounting</th>
                    <th>Bolt</th>
                    <th style={{ textAlign:"right" }}>{t("cg.th_stock")}</th>
                    <th></th>
                  </tr>
                </thead>
                <tbody>
                  {pageItems.map(p => (
                    <tr key={p.pn} onClick={() => go("product")}>
                      <td className="mini-pic"><div className="mp"><ClampArt kind={p.seriesKind} /></div></td>
                      <td><span className="pn">{p.pn}</span></td>
                      <td>{p.seriesLabel}</td>
                      <td>{p.group}</td>
                      <td className="num">ø{p.od}</td>
                      <td>{BASE_LABEL_SHORT[p.baseType]}</td>
                      <td className="mono">{p.bolt}</td>
                      <td className="num">{p.stock}</td>
                      <td><span className="link-arrow" style={{ fontSize:12, padding:0 }}>{t("cat.view")} <IconArrow size={12} /></span></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}

            {pageCount > 1 && (
              <div className="pager">
                <button onClick={() => setPage(Math.max(1, page-1))} disabled={page===1}>{t("cg.prev")}</button>
                {Array.from({ length: Math.min(pageCount, 7) }).map((_, i) => {
                  const n = i + 1;
                  return <button key={n} className={n===page?"on":""} onClick={()=>setPage(n)}>{n}</button>;
                })}
                {pageCount > 7 && <button>···</button>}
                <button onClick={() => setPage(Math.min(pageCount, page+1))} disabled={page===pageCount}>{t("cg.next")}</button>
              </div>
            )}
          </div>
        </section>

        {/* ── Accessories & Components ── */}
        <section style={{ marginTop: 64, paddingTop: 48, borderTop: "1px solid var(--rule)" }}>
          <h2 style={{ fontSize: 22, fontWeight: 700, marginBottom: 6 }}>Accessories &amp; Components · 配件与组件</h2>
          <p style={{ color: "var(--muted)", fontSize: 14, marginBottom: 36 }}>
            Individual components for custom assembly. Standard mounting width B = 30 mm.
          </p>

          {/* WQL-C: Twin welded base plate */}
          <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-C · Twin welded base plate · 双联焊接底板</h4>
          <div style={{ overflowX: "auto", marginBottom: 36 }}>
            <table className="prod-table" style={{ minWidth: 420 }}>
              <thead><tr><th>Order code</th><th style={{textAlign:"right"}}>d</th><th style={{textAlign:"right"}}>a</th><th style={{textAlign:"right"}}>e</th><th style={{textAlign:"right"}}>δ (mm)</th></tr></thead>
              <tbody>{ACCESSORIES.filter(a => a.type==="twin-base").map(a => (
                <tr key={a.pn}><td><span className="pn">{a.pn}</span></td><td className="num">{a.d ?? "—"}</td><td className="num">{a.a}</td><td className="num">{a.e}</td><td className="num">{a.δ}</td></tr>
              ))}</tbody>
            </table>
          </div>

          {/* WQL-D: Multiple welded base plate */}
          <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-D · Multiple welded base plate · 多联焊接底板</h4>
          <div style={{ overflowX: "auto", marginBottom: 36 }}>
            <table className="prod-table" style={{ minWidth: 480 }}>
              <thead><tr><th>Order code</th><th>Links</th><th style={{textAlign:"right"}}>d</th><th style={{textAlign:"right"}}>a</th><th style={{textAlign:"right"}}>e</th><th style={{textAlign:"right"}}>δ (mm)</th></tr></thead>
              <tbody>{ACCESSORIES.filter(a => a.type==="multi-base").map(a => (
                <tr key={a.pn}><td><span className="pn">{a.pn}</span></td><td>{a.links}联</td><td className="num">{a.d ?? "—"}</td><td className="num">{a.a}</td><td className="num">{a.e}</td><td className="num">{a.δ}</td></tr>
              ))}</tbody>
            </table>
          </div>

          {/* WQL-E + WQL-F side by side */}
          <div style={{ display:"flex", gap: 32, flexWrap:"wrap", marginBottom: 36 }}>
            <div style={{ flex:"1 1 240px" }}>
              <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-E · Mounting rail · 安装导轨</h4>
              <table className="prod-table">
                <thead><tr><th>Order code</th><th style={{textAlign:"right"}}>h (mm)</th></tr></thead>
                <tbody>{ACCESSORIES.filter(a => a.type==="rail").map(a => (
                  <tr key={a.pn}><td><span className="pn">{a.pn}</span></td><td className="num">{a.h}</td></tr>
                ))}</tbody>
              </table>
            </div>
            <div style={{ flex:"1 1 300px" }}>
              <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-F · Rail nut · 导轨螺母</h4>
              <table className="prod-table">
                <thead><tr><th>Order code</th><th style={{textAlign:"right"}}>L</th><th style={{textAlign:"right"}}>B</th><th style={{textAlign:"right"}}>H1</th><th style={{textAlign:"right"}}>H2</th></tr></thead>
                <tbody>{ACCESSORIES.filter(a => a.type==="rail-nut").map(a => (
                  <tr key={a.pn}><td><span className="pn">{a.pn}</span></td><td className="num">{a.L}</td><td className="num">{a.B}</td><td className="num">{a.H1}</td><td className="num">{a.H2}</td></tr>
                ))}</tbody>
              </table>
            </div>
          </div>

          {/* WQL-G: Cover plate */}
          <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-G · Cover plate · 盖板</h4>
          <div style={{ overflowX: "auto", marginBottom: 36 }}>
            <table className="prod-table" style={{ minWidth: 380 }}>
              <thead><tr><th>Order code</th><th style={{textAlign:"right"}}>L1</th><th style={{textAlign:"right"}}>L2</th><th style={{textAlign:"right"}}>S (mm)</th></tr></thead>
              <tbody>{ACCESSORIES.filter(a => a.type==="cover").map(a => (
                <tr key={a.pn}><td><span className="pn">{a.pn}</span></td><td className="num">{a.L1}</td><td className="num">{a.L2 ?? "—"}</td><td className="num">{a.S}</td></tr>
              ))}</tbody>
            </table>
          </div>

          {/* WQL-H + WQL-1 side by side */}
          <div style={{ display:"flex", gap: 32, flexWrap:"wrap", marginBottom: 36 }}>
            <div style={{ flex:"1 1 300px" }}>
              <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-H · Overlapping bolt · 叠加螺栓</h4>
              <table className="prod-table">
                <thead><tr><th>Order code</th><th style={{textAlign:"right"}}>L1</th><th style={{textAlign:"right"}}>L2 (mm)</th></tr></thead>
                <tbody>{ACCESSORIES.filter(a => a.type==="bolt-stack").map(a => (
                  <tr key={a.pn}><td><span className="pn">{a.pn}</span></td><td className="num">{a.L1}</td><td className="num">{a.L2}</td></tr>
                ))}</tbody>
              </table>
            </div>
            <div style={{ flex:"1 1 240px" }}>
              <h4 style={{ fontWeight: 600, marginBottom: 8 }}>WQL-1 · Locking plate · 防松盖板</h4>
              <table className="prod-table">
                <thead><tr><th>Order code</th><th>Note</th></tr></thead>
                <tbody>
                  <tr><td><span className="pn">WQL-1</span></td><td style={{fontSize:12,color:"var(--muted)"}}>Type B L1 = cover plate length · B型L1同盖板</td></tr>
                </tbody>
              </table>
            </div>
          </div>
        </section>
        {/* ── WQT Twin Pipe Clamp ── */}
        <section style={{ marginTop: 64, paddingTop: 48, borderTop: "1px solid var(--rule)" }}>
          <h2 style={{ fontSize: 22, fontWeight: 700, marginBottom: 6 }}>WQT Twin Pipe Clamp · 双联管夹</h2>
          <p style={{ color: "var(--muted)", fontSize: 14, marginBottom: 20 }}>
            Twin series single bolt fixed type · 双联系列单螺栓固定式 · PN ≤ 8 MPa · ø6–ø42 mm
          </p>

          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 24 }}>
            {WQT_MATERIALS.map(m => (
              <span key={m.code} style={{ display:"inline-flex", alignItems:"center", gap:6, padding:"4px 10px", background:"var(--surface-alt,#f5f5f5)", borderRadius:4, fontSize:12 }}>
                <span className="mono" style={{ fontWeight:700 }}>{m.code}</span>
                {m.nameEN} · {m.nameZH}
                <span style={{ color:"var(--muted)", fontSize:11 }}>{m.temp}</span>
              </span>
            ))}
          </div>
          <p style={{ fontSize: 12, color: "var(--muted)", marginBottom: 32, lineHeight: 1.7 }}>
            Standard metal parts (cover, base plate, rail, rail nut, bolt): carbon steel.
            SS304 / SS316L available on request. Specify material code + surface treatment (C1–C5) + mounting type (A/B/C) when ordering.
            Mixed OD assemblies (D1 ≠ D2) available — state both ODs in order code.
          </p>

          {WQT_SERIES.map(s => (
            <div key={s.id} style={{ marginBottom: 44 }}>
              <h4 style={{ fontWeight: 600, marginBottom: 2 }}>WQT*{s.id} · {s.descEN}</h4>
              <div style={{ fontSize: 12, color: "var(--muted)", marginBottom: 12 }}>{s.descZH}</div>
              <div style={{ overflowX: "auto" }}>
                <table className="prod-table" style={{ minWidth: 680 }}>
                  <thead>
                    <tr>
                      <th>Group</th>
                      <th>Order code (WQT*{s.id}-…)</th>
                      <th style={{textAlign:"right"}}>D1/D2 mm</th>
                      <th style={{textAlign:"right"}}>Body L1×L2×H</th>
                      <th style={{textAlign:"right"}}>Cover L</th>
                      <th style={{textAlign:"right"}}>Base L</th>
                      <th>Bolt</th>
                    </tr>
                  </thead>
                  <tbody>
                    {Object.entries(WQT_GROUP_ODS).flatMap(([grp, ods]) => {
                      const cb   = WQT_CLAMP_BODY[grp];
                      const cvr  = WQT_COVER[grp];
                      const base = WQT_BASE[grp];
                      const bolt = WQT_BOLTS[grp];
                      return ods.map((od, i) => (
                        <tr key={`${s.id}-${grp}-${od}`}>
                          <td>{i === 0 ? <strong>{grp}</strong> : ""}</td>
                          <td><span className="pn">{makeWQTPN(s.id, grp, od)}</span></td>
                          <td className="num">ø{od}</td>
                          <td className="num mono" style={{fontSize:11}}>{cb.L1}×{cb.L2}×{cb.H}</td>
                          <td className="num">{cvr.L}</td>
                          <td className="num">{base.L}</td>
                          <td className="mono">{i === 0 ? bolt : ""}</td>
                        </tr>
                      ));
                    })}
                  </tbody>
                </table>
              </div>
            </div>
          ))}
        </section>

      </div>
    </>
  );
}

Object.assign(window, { Catalog, PRODUCTS, ACCESSORIES, PRODUCTS_WQT, WQT_SERIES, WQT_MATERIALS });
