/* mSamex Card — shared kit: icons, mesh mark, card art (6 finishes), charts, atoms.
 * Everything exports via window.CardKit.
 */

const CK = {};

/* ---------- formatting ---------- */
CK.fmtNum = (n, dec = 2) =>
  n.toLocaleString("en-US", { minimumFractionDigits: dec, maximumFractionDigits: dec });
CK.eur = (n, dec = 2) => "€" + CK.fmtNum(Math.abs(n), dec);
CK.money = (n, sym = "€", dec = 2) => sym + CK.fmtNum(Math.abs(n), dec);
CK.signed = (n, sym = "€", dec = 2) =>
  (n < 0 ? "−" : "+") + sym + CK.fmtNum(Math.abs(n), dec);

/* ---------- icons (simple geometric strokes) ---------- */
const IPATHS = {
  back: "M15 5l-7 7 7 7",
  chev: "M9 5l7 7-7 7",
  chevD: "M5 9l7 7 7-7",
  plus: "M12 4v16M4 12h16",
  close: "M6 6l12 12M18 6L6 18",
  check: "M4 12.5l5.5 5.5L20 7",
  up: "M6 18L18 6M9 6h9v9",
  down: "M18 6L6 18M15 18H6V9",
  swap: "M4 8h13l-3.5-3.5M20 16H7l3.5 3.5",
  search: "M10.5 4a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zM15.5 15.5L20 20",
  bell: "M6 16V11a6 6 0 0 1 12 0v5l1.5 2.5h-15L6 16zM10 21h4",
  dots: "M5 12h.01M12 12h.01M19 12h.01",
  copy: "M9 9h10v11H9zM5 15V4h10",
  share: "M12 15V4M8 8l4-4 4 4M5 12v8h14v-8",
  snow: "M12 3v18M4.2 7.5l15.6 9M19.8 7.5l-15.6 9",
  card: "M3 6.5h18v12H3zM3 10.5h18",
  home: "M4 11l8-7 8 7v9h-5v-6h-6v6H4z",
  pulse: "M3 12h4l2.5-6 4.5 12 2.5-6H21",
  user: "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM4 20c1.4-3.4 4.4-5 8-5s6.6 1.6 8 5)".replace(")",""),
  qr: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h3v3h-3zM20 17v3h-3",
  globe: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM3 12h18M12 3c-2.6 2.4-4 5.5-4 9s1.4 6.6 4 9c2.6-2.4 4-5.5 4-9s-1.4-6.6-4-9z",
  cal: "M4 6h16v14H4zM4 10h16M8 4v4M16 4v4",
  dl: "M12 4v10M8 10l4 4 4-4M5 19h14",
  shield: "M12 3l8 3v6c0 4.4-3.2 7.6-8 9-4.8-1.4-8-4.6-8-9V6l8-3z",
  gear: "M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6zM12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9L17 7M7 17l-2.1 2.1",
  pin: "M12 21s-6-5.2-6-10a6 6 0 1 1 12 0c0 4.8-6 10-6 10zM12 12.5a1.8 1.8 0 1 0 0-3.6 1.8 1.8 0 0 0 0 3.6z",
  doc: "M6 3h9l3 3v15H6zM9 10h6M9 14h6",
  split: "M12 4v6M12 10l-6 8M12 10l6 8",
  repeat: "M4 9a8 8 0 0 1 14-3l2 2M20 4v4h-4M20 15a8 8 0 0 1-14 3l-2-2M4 20v-4h4",
  tag: "M4 4h7l9 9-7 7-9-9V4zM8.5 8.5h.01",
  filter: "M4 6h16M7 12h10M10 18h4",
  wallet: "M4 7h15a1 1 0 0 1 1 1v10H4V7zM4 7V5.5A1.5 1.5 0 0 1 5.5 4H17M15.5 12.5h.01",
  bank: "M4 9l8-5 8 5M5 9v8M12 9v8M19 9v8M3 20h18",
  contact: "M12 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7zM5 20a7 7 0 0 1 14 0",
  at: "M12 16a4 4 0 1 1 4-4v1.5a2 2 0 0 0 4 0V12a8 8 0 1 0-3 6.2",
  chain: "M9 15l6-6M7.5 12.5l-2 2a3.5 3.5 0 0 0 5 5l2-2M16.5 11.5l2-2a3.5 3.5 0 0 0-5-5l-2 2",
  face: "M4 8V4h4M16 4h4v4M20 16v4h-4M8 20H4v-4M8.5 9.5v1.5M15.5 9.5v1.5M9 15.5c.9.7 1.9 1 3 1s2.1-.3 3-1)".replace(")",""),
  eye: "M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12zM12 14.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z",
  camera: "M4 8h4l2-2.5h4L16 8h4v11H4zM12 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",
  moon: "M19 14.5A7.5 7.5 0 0 1 9.5 5 7.5 7.5 0 1 0 19 14.5z",
};

CK.Icon = function Icon({ name, size = 20, w = 1.6, color = "currentColor", style }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" style={style} aria-hidden="true">
      <path d={IPATHS[name] || IPATHS.dots} stroke={color} strokeWidth={w}
        strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
};

/* ---------- brand mesh mark (per brief: hex R64, nodes r10, core r16, 2pt @45%) ---------- */
const HEX = [[100,36],[155.4,68],[155.4,132],[100,164],[44.6,132],[44.6,68]];
CK.MeshMark = function MeshMark({ size = 28, color = "#00D68F", nodeOnly = false, coreColor }) {
  return (
    <svg width={size} height={size} viewBox="0 0 200 200" aria-hidden="true">
      <g stroke={color} strokeWidth="4" opacity="0.45">
        {HEX.map((p, i) => {
          const q = HEX[(i + 1) % 6];
          return <line key={"p" + i} x1={p[0]} y1={p[1]} x2={q[0]} y2={q[1]} />;
        })}
        {!nodeOnly && HEX.map((p, i) => (
          <line key={"s" + i} x1={p[0]} y1={p[1]} x2="100" y2="100" />
        ))}
      </g>
      {HEX.map((p, i) => <circle key={"n" + i} cx={p[0]} cy={p[1]} r="10" fill={color} />)}
      <circle cx="100" cy="100" r="16" fill={coreColor || color} />
    </svg>
  );
};

CK.Wordmark = function Wordmark({ size = 16, dark = false }) {
  return (
    <span style={{ fontWeight: 700, fontSize: size, letterSpacing: "-0.04em",
      color: dark ? "var(--m3-ink)" : "var(--m3-snow)", fontFamily: "var(--m3-font)" }}>
      m<span style={{ color: "var(--m3-mint)" }}>S</span>amex
    </span>
  );
};

/* ---------- card art: 6 finishes ---------- */
/* large decorative mesh crop — dual-pass emboss (light offset under dark) */
function MeshCrop({ light, dark, core, op = 1 }) {
  const pass = (color) => (<>
    <g stroke={color} strokeWidth="2" opacity="0.45">
      {HEX.map((p, i) => {
        const q = HEX[(i + 1) % 6];
        return <line key={"p" + i} x1={p[0]} y1={p[1]} x2={q[0]} y2={q[1]} />;
      })}
      {HEX.map((p, i) => <line key={"s" + i} x1={p[0]} y1={p[1]} x2="100" y2="100" />)}
    </g>
    {HEX.map((p, i) => <circle key={"n" + i} cx={p[0]} cy={p[1]} r="10" fill={color} />)}
  </>);
  return (
    <svg viewBox="0 0 200 200" style={{ position: "absolute", width: "72%", right: "-18%",
      top: "-26%", opacity: op }} aria-hidden="true">
      {light && <g transform="translate(1.2,1.5)">{pass(light)}<circle cx="100" cy="100" r="16" fill={light} /></g>}
      {pass(dark)}
      <circle cx="100" cy="100" r="16" fill={core || dark} />
    </svg>
  );
}

/* Sam mini face for the Teen "Spark" finish (brand geometry: pebble + visor + mint eyes) */
function SamFace({ size = 44 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 64 64" aria-hidden="true">
      <rect x="6" y="8" width="52" height="48" rx="18" fill="#1C2127" stroke="#252A33" />
      <rect x="14" y="20" width="36" height="20" rx="10" fill="#0B0E11" />
      <circle cx="26" cy="30" r="3.4" fill="#00D68F" />
      <circle cx="38" cy="30" r="3.4" fill="#00D68F" />
    </svg>
  );
}

/* generic network mark: two interlocked outline circles (no real scheme branding) */
function NetworkMark({ light }) {
  const c = light ? "rgba(11,14,17,.5)" : "rgba(255,255,255,.5)";
  return (
    <svg width="34" height="22" viewBox="0 0 34 22" aria-hidden="true">
      <circle cx="12" cy="11" r="8" fill="none" stroke={c} strokeWidth="1.6" />
      <circle cx="22" cy="11" r="8" fill="none" stroke={c} strokeWidth="1.6" />
    </svg>
  );
}

CK.CardArt = function CardArt({ finish = "sterling", w = 320, holder = "KERTU LAANEMETS",
  last4 = "4417", exp = "09/29", cur, virtual = false, frozen = false, sheen = true, style }) {
  const h = Math.round(w / 1.586);
  const FIN = {
    sterling: {
      bg: "linear-gradient(160deg,#DDE1E6 0%,#B3B9C1 26%,#D2D6DC 46%,#969DA7 72%,#C3C8CF 100%)",
      ink: "#22262C", mute: "rgba(20,24,30,.6)", s: "#008A5C", brush: true, darkText: true,
      meshL: "rgba(255,255,255,.5)", meshD: "rgba(0,0,0,.2)", core: "rgba(0,0,0,.3)" },
    aurum: {
      bg: "linear-gradient(160deg,#E6D6B2 0%,#C2A671 28%,#DCC99C 48%,#A68C58 74%,#CDB37F 100%)",
      ink: "#2B2416", mute: "rgba(43,36,22,.6)", s: "#00744E", brush: true, darkText: true,
      meshL: "rgba(255,246,220,.5)", meshD: "rgba(56,40,12,.22)", core: "rgba(56,40,12,.32)" },
    pulse: {
      bg: "#101318", ink: "var(--m3-snow)", mute: "rgba(255,255,255,.55)", s: "var(--m3-mint)",
      meshD: "rgba(0,214,143,.42)", core: "#00D68F" },
    graphite: {
      bg: "linear-gradient(160deg,#2B3037 0%,#1E2228 34%,#272C33 58%,#181C21 82%,#232830 100%)",
      ink: "var(--m3-snow)", mute: "rgba(255,255,255,.55)", s: "var(--m3-mint)", brush: true,
      meshL: "rgba(0,0,0,.35)", meshD: "rgba(255,255,255,.14)", core: "rgba(255,255,255,.24)" },
    void: {
      bg: "radial-gradient(120% 160% at 26% 0%, #16191E 0%, #0A0C0F 55%, #060709 100%)",
      ink: "rgba(255,255,255,.92)", mute: "rgba(255,255,255,.42)", s: "var(--m3-mint)", brush: true,
      meshD: "rgba(255,255,255,.075)", core: "#00D68F", numberless: true },
    paper: {
      bg: "#FFFFFF", ink: "var(--m3-ink)", mute: "rgba(11,14,17,.55)", s: "var(--m3-mint)",
      meshD: "rgba(11,14,17,.22)", core: "#00D68F" },
  };
  const F = FIN[finish] || FIN.sterling;
  const scale = w / 320;

  return (
    <div className={"m-card f-" + finish + (sheen ? " sheen" : "") + (frozen ? " is-frozen" : "")}
      style={{ width: w, height: h, background: F.bg, fontSize: 12 * scale, ...style }}>
      {F.brush && <div className="brushed" />}
      <MeshCrop light={F.meshL} dark={F.meshD} core={F.core} />

      {/* chrome */}
      <div className="m-card-top" style={{ padding: 16 * scale }}>
        <span style={{ fontWeight: 700, fontSize: 15 * scale, letterSpacing: "-0.04em", color: F.ink }}>
          m<span style={{ color: F.s }}>S</span>amex
        </span>
        <span style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 5 * scale }}>
          <span className="mono" style={{ fontSize: 8 * scale, letterSpacing: "0.3em", color: F.mute, textTransform: "uppercase" }}>{finish}</span>
          {cur && <span className="mono" style={{ fontSize: 7.5 * scale, letterSpacing: "0.22em", color: F.mute }}>{cur}</span>}
          {virtual && <span className="m-card-vbadge" style={{ color: F.mute, borderColor: F.mute }}>VIRTUAL</span>}
        </span>
      </div>
      {!F.numberless && (
        <div className="m-card-num mono" style={{ left: 16 * scale, bottom: 44 * scale, fontSize: 13.5 * scale, color: F.ink }}>
          ••••&nbsp;&nbsp;••••&nbsp;&nbsp;••••&nbsp;&nbsp;{last4}
        </div>
      )}
      <div className="m-card-bottom" style={{ padding: 16 * scale }}>
        <div>
          <div className="mono" style={{ fontSize: 8.5 * scale, letterSpacing: ".12em", color: F.numberless ? F.mute : F.ink, opacity: F.numberless ? 1 : 0.85 }}>
            {F.numberless ? "DETAILS IN-APP" : holder.toUpperCase()}
          </div>
          {!F.numberless && (
            <div className="mono" style={{ fontSize: 9.5 * scale, color: F.mute, marginTop: 2 }}>{exp}</div>
          )}
        </div>
        <NetworkMark light={F.darkText} />
      </div>
      {frozen && <div className="m-card-frost"><CK.Icon name="snow" size={18 * scale} color="#fff" /></div>}
    </div>
  );
};

/* ---------- charts ---------- */
function norm(data, w, h, pad = 2) {
  const mn = Math.min(...data), mx = Math.max(...data), r = mx - mn || 1;
  return data.map((v, i) => [
    pad + (i / (data.length - 1)) * (w - pad * 2),
    h - pad - ((v - mn) / r) * (h - pad * 2),
  ]);
}
CK.Spark = function Spark({ data, w = 64, h = 22, color = "var(--m3-mint)" }) {
  const pts = norm(data, w, h).map((p) => p.join(",")).join(" ");
  return (
    <svg width={w} height={h} aria-hidden="true">
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.5" strokeLinejoin="round" />
    </svg>
  );
};
CK.Area = function Area({ data, w = 326, h = 110, color = "var(--m3-mint)" }) {
  const pts = norm(data, w, h, 4);
  const line = pts.map((p) => p.join(",")).join(" ");
  const fill = `${pts[0][0]},${h} ` + line + ` ${pts[pts.length - 1][0]},${h}`;
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" aria-hidden="true">
      <polygon points={fill} fill={color} opacity="0.10" />
      <polyline points={line} fill="none" stroke={color} strokeWidth="1.8" strokeLinejoin="round" />
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="3" fill={color} />
    </svg>
  );
};
CK.Bars = function Bars({ data, w = 326, h = 64, color = "var(--m3-mint)", active = -1, dim = "rgba(255,255,255,.14)" }) {
  const mx = Math.max(...data) || 1, n = data.length, bw = Math.max(2, w / n - 4);
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" aria-hidden="true">
      {data.map((v, i) => {
        const bh = Math.max(2, (v / mx) * (h - 4));
        return <rect key={i} x={(i * w) / n + 2} y={h - bh} width={bw} height={bh} rx="1.5"
          fill={active === -1 || active === i ? color : dim} opacity={v === 0 ? 0.25 : 1} />;
      })}
    </svg>
  );
};
const CAT_COLORS = ["#00D68F", "rgba(0,214,143,.5)", "rgba(255,255,255,.85)", "rgba(255,255,255,.45)", "rgba(255,255,255,.2)"];
CK.catColor = (i) => CAT_COLORS[i % CAT_COLORS.length];
CK.Donut = function Donut({ parts, size = 128, width = 12 }) {
  const total = parts.reduce((s, p) => s + p.amt, 0) || 1;
  const r = (size - width) / 2, C = 2 * Math.PI * r;
  let off = 0;
  return (
    <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }} aria-hidden="true">
      <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="rgba(255,255,255,.07)" strokeWidth={width} />
      {parts.map((p, i) => {
        const len = (p.amt / total) * (C - parts.length * 3);
        const el = (
          <circle key={i} cx={size / 2} cy={size / 2} r={r} fill="none"
            stroke={CK.catColor(p.c)} strokeWidth={width} strokeLinecap="round"
            strokeDasharray={`${len} ${C - len}`} strokeDashoffset={-off} />
        );
        off += len + 3;
        return el;
      })}
    </svg>
  );
};

/* ---------- atoms ---------- */
CK.Pill = ({ tone = "dim", children }) => <span className={"pill pill-" + tone}>{children}</span>;
CK.Chip = ({ on, onClick, children }) => (
  <button className={"chip" + (on ? " on" : "")} onClick={onClick}>{children}</button>
);
CK.Tgl = ({ on, onChange }) => (
  <button className={"tgl" + (on ? " on" : "")} onClick={() => onChange && onChange(!on)}
    role="switch" aria-checked={on}><i></i></button>
);
CK.Bar = ({ v, max, tone = "mint", h = 4 }) => (
  <div className="bar" style={{ height: h }}>
    <i className={"bar-" + tone} style={{ width: Math.min(100, (v / max) * 100) + "%" }}></i>
  </div>
);
CK.Avatar = ({ name, size = 36, tone = "el" }) => (
  <span className={"avatar av-" + tone} style={{ width: size, height: size, fontSize: size * 0.34 }}>
    {name.split(" ").map((s) => s[0]).slice(0, 2).join("")}
  </span>
);
CK.Row = ({ icon, iconEl, label, sub, right, rightSub, chevron, onClick, danger }) => (
  <button className={"lrow" + (danger ? " danger" : "")} onClick={onClick}>
    {iconEl || (icon && <span className="lrow-ic"><CK.Icon name={icon} size={17} /></span>)}
    <span className="lrow-main">
      <span className="lrow-label">{label}</span>
      {sub && <span className="lrow-sub">{sub}</span>}
    </span>
    <span className="lrow-right">
      {right && <span className="lrow-r1">{right}</span>}
      {rightSub && <span className="lrow-r2">{rightSub}</span>}
    </span>
    {chevron && <CK.Icon name="chev" size={15} style={{ opacity: 0.35, flexShrink: 0 }} />}
  </button>
);
CK.Sect = ({ title, action, onAction }) => (
  <div className="sect-head">
    <span className="k">{title}</span>
    {action && <button className="sect-act" onClick={onAction}>{action}</button>}
  </div>
);
CK.TxRow = function TxRow({ tx, onClick, sym = "€" }) {
  return (
    <button className="lrow" onClick={onClick}>
      <span className={"mavatar" + (tx.in ? " in" : "") + (tx.swap ? " swp" : "")}>
        {tx.in ? <CK.Icon name="down" size={15} /> : tx.swap ? <CK.Icon name="swap" size={15} /> :
          tx.m.split(" ").map((s) => s[0]).slice(0, 2).join("")}
      </span>
      <span className="lrow-main">
        <span className="lrow-label">{tx.m}</span>
        <span className="lrow-sub">{tx.cat} · {tx.when}</span>
      </span>
      <span className="lrow-right">
        <span className={"lrow-r1 mono " + (tx.amt > 0 ? "up" : "")}>{CK.signed(tx.amt, sym)}</span>
        {tx.sub && <span className="lrow-r2 mono">{tx.sub}</span>}
      </span>
    </button>
  );
};

CK.SamFace = SamFace;
Object.assign(window, { CardKit: CK });
