/* IMACX primitives — Price, QuantityStepper, OptionSelector, Badge, Rating, Facets, Accordion, icons */
const { useState, useEffect, useMemo, useRef, useCallback } = React;

/* tiny inline icon set (stroke, monochrome) */
function Icon({ d, size = 18, fill = "none" }) {
  return (
    <svg viewBox="0 0 24 24" width={size} height={size} fill={fill} stroke="currentColor"
         strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      {d}
    </svg>
  );
}
const Icons = {
  search: <Icon d={<><circle cx="11" cy="11" r="7"/><path d="m20 20-3.2-3.2"/></>} />,
  bag:    <Icon d={<><path d="M6 8h12l-1 12H7L6 8Z"/><path d="M9 8a3 3 0 0 1 6 0"/></>} />,
  cart:   <Icon d={<><path d="M3 4h2l2.4 12.4a1 1 0 0 0 1 .8h7.7a1 1 0 0 0 1-.78L19.5 8H6"/><circle cx="9" cy="20" r="1.4"/><circle cx="17" cy="20" r="1.4"/></>} />,
  phone:  <Icon d={<path d="M6.8 3.5H10l1.3 4.2-2.1 1.4a11.5 11.5 0 0 0 5 5l1.4-2.1 4.2 1.3v3.2a1.6 1.6 0 0 1-1.7 1.6A15.7 15.7 0 0 1 5.2 5.2 1.6 1.6 0 0 1 6.8 3.5z"/>} />,
  arrow:  <Icon d={<><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></>} size={16} />,
  plus:   <Icon d={<><path d="M12 5v14M5 12h14"/></>} size={16} />,
  x:      <Icon d={<><path d="M6 6l12 12M18 6 6 18"/></>} size={16} />,
  check:  <Icon d={<path d="M5 12.5 10 17 19 6"/>} size={13} />,
  grid:   <Icon d={<><rect x="4" y="4" width="7" height="7"/><rect x="13" y="4" width="7" height="7"/><rect x="4" y="13" width="7" height="7"/><rect x="13" y="13" width="7" height="7"/></>} size={15} />,
  rows:   <Icon d={<><rect x="4" y="5" width="16" height="5"/><rect x="4" y="14" width="16" height="5"/></>} size={15} />,
  upload: <Icon d={<><path d="M12 16V4"/><path d="m7 9 5-5 5 5"/><path d="M5 20h14"/></>} />,
  spark:  <Icon d={<path d="M12 3v6m0 6v6m9-9h-6m-6 0H3m13.5-5.5-4 4m-5 5-4 4m13 0-4-4m-5-5-4-4"/>} size={16} />,
};

/* IMACX wordmark — foreground inherits currentColor, the X box uses the accent.
   Works on light/dark contexts and follows the accent tweak. */
function BrandLogo({ className, title = "IMACX" }) {
  return (
    <svg className={className} viewBox="0 0 100 38.1" role="img" aria-label={title} xmlns="http://www.w3.org/2000/svg">
      <g fill="currentColor">
        <rect y="9.4" width="3.8" height="18.3" />
        <polygon points="10.1 8.9 10.1 27.8 13.7 27.8 13.7 20.4 19.2 28.4 24.8 20.4 24.8 27.8 28.4 27.8 28.4 8.9 19.2 22 10.1 8.9" />
        <path d="M32.3,27.8h4l1.1-2.2h7.5l1,2.2h4.1l-8.9-18.9-8.9,18.9h0ZM39.1,21.9l2.1-4.4,2.1,4.4h-4.2Z" />
        <path d="M62.5,12.8c1.7,0,3,.6,4.2,1.7l2.6-2.6c-1.8-1.8-4.1-2.8-6.7-2.8s-4.8,1-6.7,2.8c-1.8,1.8-2.8,4.1-2.8,6.7s1,4.8,2.8,6.6c1.8,1.8,4.1,2.8,6.7,2.8s4.9-1,6.7-2.8l-2.6-2.6c-1.1,1.1-2.5,1.8-4.2,1.8s-3-.6-4.1-1.8-1.8-2.5-1.8-4.1.6-3,1.8-4.2,2.5-1.7,4.1-1.7h0Z" />
        <polygon points="100 0 98.6 0 92.2 9.9 89.3 9.9 85.7 15.5 82.1 9.9 77.8 9.9 83.5 18.9 76.5 29.9 75 29.9 75 8.3 90.4 8.3 91.6 6.3 73 6.3 73 31.8 75.2 31.8 71.2 38.1 72.7 38.1 75.4 34 75.4 34 75.9 33.2 79.2 28 82.1 28 85.7 22.3 89.4 28 93.7 28 87.9 18.9 94.2 9.1 94.7 8.3 96.6 8.3 96.6 29.9 80.9 29.9 79.7 31.8 98.6 31.8 98.6 6.3 95.9 6.3 100 0" />
      </g>
      <g fill="var(--accent)">
        <polygon points="76.5 29.9 75 29.9 75 8.3 90.4 8.3 85.7 15.5 82.1 9.9 77.8 9.9 83.5 18.9 76.5 29.9" />
        <polygon points="82.1 28 85.7 22.3 89.4 28 93.7 28 87.9 18.9 94.2 9.1 94.7 8.3 96.6 8.3 96.6 29.9 80.9 29.9 82.1 28" />
      </g>
    </svg>
  );
}

function Price({ tiers, qty, single, quoteOnly }) {
  // show unit price at current qty tier (or base)
  const firstTier = Object.keys(tiers || {}).map(Number).sort((a, b) => a - b)[0];
  const unit = single != null ? single : tiers[qty] != null ? tiers[qty] : tiers[firstTier];
  if (quoteOnly || !Number(unit)) {
    return (
      <span className="price">
        <span className="from">preço</span>
        <span className="val">Sob orçamento</span>
      </span>
    );
  }
  return (
    <span className="price">
      <span className="from">desde</span>
      <span className="val">{eur(unit)}</span>
      <span className="unit">/un</span>
    </span>
  );
}

function Rating({ value, count }) {
  return (
    <span className="rating" title={`${(value*5).toFixed(1)} / 5 · ${count} avaliações`}>
      <span className="bar"><i style={{ width: (value*100) + "%" }} /></span>
      <b className="num">{(value*5).toFixed(1)}</b>
      <span className="cnt">({count})</span>
    </span>
  );
}

function Badge({ children, tone = "accent" }) {
  return <span className={"chipx " + (tone === "solid" ? "solid" : tone === "line" ? "" : "accent")}>{children}</span>;
}

function QuantityStepper({ value, onChange, step = 25, min = 1 }) {
  return (
    <div className="stepper">
      <button onClick={() => onChange(Math.max(min, value - step))} aria-label="Menos">−</button>
      <input value={value} onChange={(e) => { const v = parseInt(e.target.value.replace(/\D/g, ""), 10); onChange(isNaN(v) ? min : v); }} />
      <button onClick={() => onChange(value + step)} aria-label="Mais">+</button>
    </div>
  );
}

function OptionSelector({ options, value, onChange, swatch }) {
  return (
    <div className="opts">
      {options.map((o) => {
        const on = value === o.id;
        if (swatch) {
          return (
            <button key={o.id} className={"opt" + (on ? "" : "")} data-on={on} onClick={() => onChange(o.id)} title={o.name}>
              <span className="sw" style={{ background: o.hex }} />
              {o.name}
            </button>
          );
        }
        return (
          <button key={o.id} className={"opt" + (o.disabled ? " disabled" : "")} data-on={on}
                  onClick={() => !o.disabled && onChange(o.id)} title={o.label || o.name}>
            {o.label || o.name}{o.sub ? <em style={{ fontStyle: "normal", color: "var(--muted)", fontWeight: 400 }}>· {o.sub}</em> : null}
          </button>
        );
      })}
    </div>
  );
}

/* --- Facet controls --- */
function FacetCheck({ opt, on, onToggle }) {
  return (
    <div className="facet-opt" data-on={on} onClick={onToggle}>
      <span className="box">{on ? Icons.check : null}</span>
      <span>{opt.label}</span>
      {opt.cnt != null ? <span className="cnt">{opt.cnt}</span> : null}
    </div>
  );
}

function FacetGroup({ group, selected, onToggle, onClear, priceValue, onPriceChange }) {
  if (group.type === "range") {
    return <PriceRange title={group.title} value={priceValue} min={group.min} max={group.max} step={group.step} onChange={onPriceChange} />;
  }
  const sel = selected[group.id] || [];
  return (
    <div className="facet">
      <h4>
        {group.title}
        {sel.length ? <span className="clr" onClick={() => onClear(group.id)}>Limpar</span> : null}
      </h4>
      {group.type === "swatch" ? (
        <div className="swatch-row">
          {group.options.map((o) => (
            <button key={o.id} className="swatch" data-on={sel.includes(o.id)}
                    style={{ background: o.hex }} title={o.name} onClick={() => onToggle(group.id, o.id)} />
          ))}
        </div>
      ) : group.type === "chip" ? (
        <div className="facet-chips">
          {group.options.map((o) => (
            <button key={o.id} className="chipx" data-on={sel.includes(o.id)}
                    style={sel.includes(o.id) ? { borderColor: "var(--accent)", color: "var(--accent)", background: "var(--accent-tint)" } : null}
                    onClick={() => onToggle(group.id, o.id)}>{o.label}</button>
          ))}
        </div>
      ) : (
        group.options.map((o) => (
          <FacetCheck key={o.id} opt={o} on={sel.includes(o.id)} onToggle={() => onToggle(group.id, o.id)} />
        ))
      )}
    </div>
  );
}

function Accordion({ items }) {
  const [open, setOpen] = useState(0);
  return (
    <div className="acc">
      {items.map((it, i) => (
        <div className="acc-item" key={i}>
          <button className="acc-head" onClick={() => setOpen(open === i ? -1 : i)}>
            {it.q}
            <span className="ic">{open === i ? "−" : "+"}</span>
          </button>
          {open === i ? <div className="acc-body">{it.a}</div> : null}
        </div>
      ))}
    </div>
  );
}

/* Colour-count indicator — overlapping ink dots (one per colour) */
function Droplets({ n }) {
  if (!n) return null;
  return (
    <span className="inkdots" aria-hidden="true">
      {Array.from({ length: n }).map((_, i) => <span className="inkdot" key={i} />)}
    </span>
  );
}

/* Step card — collapsible "Passo N"; header toggles the body open/closed */
function StepCard({ n, title, hint, open, onToggle, children }) {
  return (
    <div className="stepc" data-open={open}>
      <button className="stepc-hd" type="button" onClick={onToggle} aria-expanded={open}>
        <span className="stepc-n">{n}</span>
        <div className="stepc-t">
          <span className="stepc-title">{title}</span>
          {hint ? <span className="stepc-hint">{hint}</span> : null}
        </div>
        <span className="stepc-tog">{open ? "−" : "+"}</span>
      </button>
      {open ? <div className="stepc-body">{children}</div> : null}
    </div>
  );
}

/* Radio row group (shipping method) */
function RadioRows({ options, value, onChange }) {
  return (
    <div className="radio-rows">
      {options.map(o => (
        <label className="radio-row" key={o.id} data-on={value === o.id}>
          <span className="radio-dot" />
          <input type="radio" name={"rr-" + (options[0]?.id || "x")} checked={value === o.id}
                 onChange={() => onChange(o.id)} style={{ position: "absolute", opacity: 0, pointerEvents: "none" }} />
          <span className="radio-main">
            <b>{o.label}</b>
            {o.sub ? <em>{o.sub}</em> : null}
          </span>
          {o.right != null ? <span className="radio-right num">{o.right}</span> : null}
        </label>
      ))}
    </div>
  );
}

/* Tabbed detail panel */
function Tabs({ tabs }) {
  const [act, setAct] = useState(0);
  return (
    <div className="tabsx">
      <div className="tabsx-bar" role="tablist">
        {tabs.map((t, i) => (
          <button key={i} className="tabsx-tab" data-on={act === i} role="tab"
                  aria-selected={act === i} onClick={() => setAct(i)}>{t.label}</button>
        ))}
      </div>
      <div className="tabsx-panel" role="tabpanel">{tabs[act]?.body}</div>
    </div>
  );
}

/* Dual-handle min–max price slider (per-unit price). Two stacked range inputs
   share one track; the active span is filled in accent. */
function PriceRange({ title, value, min, max, step = 0.5, onChange }) {
  const [lo, hi] = value;
  const setLo = (v) => onChange([Math.min(v, hi - step), hi]);
  const setHi = (v) => onChange([lo, Math.max(v, lo + step)]);
  const pct = (v) => ((v - min) / (max - min)) * 100;
  const active = lo > min || hi < max;
  return (
    <div className="facet">
      <h4>
        {title}
        {active ? <span className="clr" onClick={() => onChange([min, max])}>Limpar</span> : null}
      </h4>
      <div className="prange">
        <div className="prange-track">
          <div className="prange-fill" style={{ left: pct(lo) + "%", right: (100 - pct(hi)) + "%" }} />
          <input className="prange-input" type="range" min={min} max={max} step={step} value={lo}
                 aria-label="Preço mínimo" onChange={(e) => setLo(+e.target.value)} />
          <input className="prange-input" type="range" min={min} max={max} step={step} value={hi}
                 aria-label="Preço máximo" onChange={(e) => setHi(+e.target.value)} />
        </div>
        <div className="prange-vals">
          <span className="num">{eur(lo)}</span>
          <span className="num">{hi >= max ? eur(max) + "+" : eur(hi)}</span>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Icon, Icons, BrandLogo, Price, Rating, Badge, QuantityStepper, OptionSelector, FacetGroup, FacetCheck, PriceRange, Accordion, Droplets, StepCard, RadioRows, Tabs });
