/* Custex editor — product, craft, fabric, yarn node bodies. */
const { useState: uS, useRef: uR, useEffect: uE, useMemo: uM } = React;
const { NODE_W, PORT_FIRST, PORT_STRIDE } = window.CxGeom;

function ProductBody({ node, updateNode, changeProduct }) {
  const cs = node.data.customSize || { w: 42, h: 42, unit: 'cm' };
  const setSize = (patch) => updateNode(node.id, { customSize: { ...cs, ...patch } });
  return (
    <>
      <div className="cx-grid2">
        {window.CxSchema.PRODUCTS.slice(0, 6).map(p => (
          <button key={p.id}
            className={`cx-tile ${node.data.selected===p.id?'sel':''}`}
            onClick={() => changeProduct(p.id)}>
            <svg viewBox="0 0 80 80" className="cx-tile-icon"><path d={p.icon} stroke="currentColor" strokeWidth="1.6" fill="none"/></svg>
            <span>{p.name}</span>
          </button>
        ))}
        {(() => {
          const u = window.CxSchema.PRODUCTS.find((p) => p.id === 'unfinished_material');
          if (!u) return null;
          return (
            <button
              key={u.id}
              type="button"
              className={`cx-tile cx-tile-span ${node.data.selected === u.id ? 'sel' : ''}`}
              onClick={() => changeProduct(u.id)}
            >
              <svg viewBox="0 0 80 80" className="cx-tile-icon"><path d={u.icon} stroke="currentColor" strokeWidth="1.6" fill="none"/></svg>
              <span>{u.name}</span>
            </button>
          );
        })()}
      </div>
      <label className="cx-field-l cx-mt">Custom size <span className="cx-field-v">{cs.w} × {cs.h} {cs.unit}</span></label>
      <div className="cx-size-row">
        <input className="cx-size-input" type="number" min="1" value={cs.w} onChange={(e) => setSize({ w: Math.max(1, Number(e.target.value) || 1) })} />
        <span className="cx-size-x">×</span>
        <input className="cx-size-input" type="number" min="1" value={cs.h} onChange={(e) => setSize({ h: Math.max(1, Number(e.target.value) || 1) })} />
        <select className="cx-size-unit" value={cs.unit} onChange={(e) => setSize({ unit: e.target.value })}>
          <option value="cm">cm</option>
          <option value="mm">mm</option>
          <option value="inch">inch</option>
        </select>
      </div>
    </>
  );
}

function CraftBody({ node, updateCraftParam, changeCraftType, graph }) {
  const productId = graph.nodes.product.data.selected;
  const allowed   = window.CxSchema.availableProcesses(productId);
  const allowedIds = allowed.map(c => c.id);
  const currentCraft = window.CxSchema.CRAFTS.find(c => c.id === node.data.type);
  const params = node.data.params || {};
  const craftAddGbp =
    typeof window.CxPricing?.cnyToGbp === 'function'
      ? window.CxPricing.cnyToGbp(currentCraft?.priceAdd ?? 0)
      : Math.round((Number(currentCraft?.priceAdd) || 0) / 10 * 100) / 100;
  return (
    <>
      <div className="cx-craft-row">
        {window.CxSchema.CRAFTS.map(c => {
          const isAllowed = allowedIds.includes(c.id);
          return (
            <button key={c.id}
              disabled={!isAllowed}
              title={isAllowed ? c.note : `${c.short} not allowed for ${productId}`}
              className={`cx-chip ${node.data.type===c.id?'sel':''} ${!isAllowed?'dis':''}`}
              onClick={() => isAllowed && changeCraftType(c.id)}>
              {c.short}
            </button>
          );
        })}
      </div>
      <div className="cx-craft-note">{sentenceCaseLabel(currentCraft?.note)}</div>
      {currentCraft && Object.entries(currentCraft.params).map(([key, def]) => (
        <ParamControl key={key} k={key} def={def} value={params[key]} onChange={(v) => updateCraftParam(key, v)} />
      ))}
      <div className="cx-mini-stat">
        <div className="cx-mini-stat-v">+£{craftAddGbp.toFixed(2)}</div>
        <div className="cx-mini-stat-k">Added per unit</div>
      </div>
    </>
  );
}

function sentenceCaseLabel(s) {
  const t = String(s ?? '').trim();
  if (!t) return t;
  return t.charAt(0).toUpperCase() + t.slice(1);
}

function paramFieldLabel(k, def) {
  return sentenceCaseLabel(def?.label || String(k).replace(/_/g, ' '));
}

function normalizeEnumOptions(def) {
  return (def.options || []).map((o) =>
    typeof o === 'string'
      ? { value: o, label: sentenceCaseLabel(o) }
      : { value: o.value, label: sentenceCaseLabel(o.label || o.value) }
  );
}

function ParamControl({ k, def, value, onChange }) {
  const label = paramFieldLabel(k, def);
  if (def.kind === 'enum') {
    const opts = normalizeEnumOptions(def);
    return (
      <>
        <label className="cx-field-l">{label}</label>
        <select className="cx-select" value={value ?? def.default} onChange={e => onChange(e.target.value)}>
          {opts.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
        </select>
      </>
    );
  }
  if (def.kind === 'int') {
    return (
      <>
        <label className="cx-field-l">{label}
          <span className="cx-field-v">{value ?? def.default}{def.unit||''}</span></label>
        <input type="range" min={def.min} max={def.max} step={1}
               value={value ?? def.default}
               onChange={e => onChange(Number(e.target.value))}
               className="cx-range" />
      </>
    );
  }
  if (def.kind === 'range') {
    return (
      <>
        <label className="cx-field-l">{label}
          <span className="cx-field-v">{((value ?? def.default)*100).toFixed(0)}%</span></label>
        <input type="range" min={def.min} max={def.max} step={def.step}
               value={value ?? def.default}
               onChange={e => onChange(Number(e.target.value))}
               className="cx-range" />
      </>
    );
  }
  return null;
}

function FabricBody({ node, updateNode, graph }) {
  const productId = graph.nodes.product.data.selected;
  const craftId   = graph.nodes.craft.data.type;
  const allowed   = window.CxSchema.availableMaterials(productId, craftId);
  const allowedIds = allowed.map(m => m.id);
  return (
    <div className="cx-fabric-list">
      {window.CxSchema.MATERIALS.map(m => {
        const isAllowed = allowedIds.includes(m.id);
        return (
          <button key={m.id}
            disabled={!isAllowed}
            title={isAllowed ? `${m.gsm}gsm · ${m.hand}` : `${m.name} not compatible`}
            className={`cx-fabric-row ${node.data.materialId===m.id?'sel':''} ${!isAllowed?'dis':''}`}
            onClick={() => isAllowed && updateNode(node.id, { materialId: m.id })}>
            <div className="cx-fabric-sw" style={{ background: m.swatch }} />
            <div className="cx-fabric-info">
              <div className="cx-fabric-name">{m.name}</div>
              <div className="cx-fabric-meta">{m.gsm} gsm · {m.hand}</div>
            </div>
          </button>
        );
      })}
    </div>
  );
}

function YarnBody({ node, updateNode, graph }) {
  const craftId = graph.nodes.craft.data.type;
  const allowed = window.CxSchema.availableYarns(craftId);
  const sel = new Set(node.data.selected || []);
  const toggle = (id) => {
    const next = new Set(sel);
    if (next.has(id)) next.delete(id); else next.add(id);
    updateNode(node.id, { selected: [...next] });
  };
  return (
    <>
      <div className="cx-craft-note">multi-select · feeds craft directly</div>
      <div className="cx-fabric-list">
        {allowed.map(y => (
          <button key={y.id}
            className={`cx-fabric-row ${sel.has(y.id)?'sel':''}`}
            onClick={() => toggle(y.id)}>
            <div className="cx-fabric-sw" style={{ background: y.swatch,
              backgroundImage: `repeating-linear-gradient(45deg, rgba(58,47,38,0.2) 0 1px, transparent 1px 3px)` }} />
            <div className="cx-fabric-info">
              <div className="cx-fabric-name">{y.name} <span className="cx-yarn-spin">{y.spin}</span></div>
              <div className="cx-fabric-meta">{y.note}</div>
            </div>
          </button>
        ))}
      </div>
    </>
  );
}
window.CxNodeBodiesParams = {
  ProductBody, CraftBody, FabricBody, YarnBody, ParamControl,
  normalizeEnumOptions, sentenceCaseLabel, paramFieldLabel,
};
