// Shared UI primitives

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// Sparkline
function Sparkline({ data, w = 76, h = 20, stroke = "var(--accent-500)", fill = "transparent", strokeWidth = 1.3 }) {
  if (!data || !data.length) return null;
  const max = Math.max(...data, 1);
  const min = Math.min(...data, 0);
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * (w - 2) + 1;
    const y = h - 1 - ((v - min) / (max - min || 1)) * (h - 2);
    return [x, y];
  });
  const d = pts.map((p,i) => (i ? "L" : "M") + p[0].toFixed(1) + "," + p[1].toFixed(1)).join(" ");
  const area = d + ` L ${w-1},${h-1} L 1,${h-1} Z`;
  return (
    <svg className="spark" width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      <path d={area} fill={fill} />
      <path d={d} fill="none" stroke={stroke} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function StatusPill({ status }) {
  const map = {
    ACTIVE:  { c: "var(--green-400)", bg: "color-mix(in oklab, var(--green-500) 18%, transparent)", t: "Active" },
    PAUSED:  { c: "var(--text-3)",    bg: "var(--chip)", t: "Paused" },
    ARCHIVED:{ c: "var(--text-4)",    bg: "var(--chip)", t: "Archived" },
  };
  const s = map[status] || map.PAUSED;
  return (
    <span className="inline-flex items-center gap-1.5 px-1.5 py-0.5 rounded text-[11px] font-medium tnum"
      style={{ color: s.c, background: s.bg }}>
      <span style={{ width: 6, height: 6, borderRadius: 3, background: s.c, display: "inline-block" }}
        className={status === "ACTIVE" ? "live-dot" : ""}/>
      {s.t}
    </span>
  );
}

function SevDot({ level }) {
  const c = level === "red" ? "var(--red-500)" : level === "amber" ? "var(--amber-500)" : "var(--green-500)";
  return <span style={{width:8, height:8, borderRadius:8, background:c, display:"inline-block"}} className={level==="red"?"live-dot":""}/>;
}

function Ratio({ ratio }) {
  // ratio = current daily / 30d avg
  const pct = Math.round(ratio * 100);
  let color = "var(--text-2)";
  let bg = "var(--chip)";
  if (ratio > 3) { color = "var(--red-400)"; bg = "color-mix(in oklab, var(--red-500) 18%, transparent)"; }
  else if (ratio > 2) { color = "var(--amber-400)"; bg = "color-mix(in oklab, var(--amber-500) 18%, transparent)"; }
  else if (ratio > 1.2) { color = "var(--text-2)"; }
  else if (ratio > 0) { color = "var(--green-400)"; bg = "color-mix(in oklab, var(--green-500) 14%, transparent)"; }
  return (
    <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded tnum mono text-[11px]"
      style={{color, background: bg}}>
      {ratio > 0 ? pct : 0}%
    </span>
  );
}

function Button({ children, kind = "ghost", size="sm", icon, onClick, className="", ...rest }) {
  const sizes = {
    xs: "h-6 px-2 text-[11px]",
    sm: "h-8 px-2.5 text-[12px]",
    md: "h-9 px-3 text-[13px]",
  };
  const kinds = {
    ghost:   "border border-soft hover:bg-[var(--surface-2)]",
    subtle:  "bg-[var(--chip)] hover:bg-[var(--surface-2)] border border-transparent",
    primary: "accent-bg hover:brightness-110 border border-transparent font-medium",
    danger:  "bg-[color-mix(in_oklab,var(--red-500)_18%,transparent)] text-[var(--red-400)] hover:bg-[color-mix(in_oklab,var(--red-500)_26%,transparent)] border border-transparent",
  };
  return (
    <button onClick={onClick}
      className={`inline-flex items-center gap-1.5 rounded-md ${sizes[size]} ${kinds[kind]} ${className}`}
      {...rest}>
      {icon && <Icon name={icon} size={14} />}
      {children}
    </button>
  );
}

function SearchInput({ value, onChange, placeholder = "Search…", kbd, className="" }) {
  return (
    <div className={`relative ${className}`}>
      <Icon name="search" size={14} className="absolute left-2.5 top-1/2 -translate-y-1/2 text-3" />
      <input
        value={value}
        onChange={e => onChange(e.target.value)}
        placeholder={placeholder}
        className="w-full h-8 pl-8 pr-12 rounded-md bg-[var(--surface)] border border-soft text-[12px] placeholder:text-[var(--text-3)]"
      />
      {kbd && <span className="kbd absolute right-2 top-1/2 -translate-y-1/2">{kbd}</span>}
    </div>
  );
}

function Select({ value, onChange, options, className="" }) {
  return (
    <div className={`relative ${className}`}>
      <select value={value} onChange={e => onChange(e.target.value)}
        className="h-8 pl-2.5 pr-7 rounded-md bg-[var(--surface)] border border-soft text-[12px] appearance-none">
        {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
      <Icon name="chevron-down" size={12} className="absolute right-2 top-1/2 -translate-y-1/2 text-3 pointer-events-none"/>
    </div>
  );
}

function Chip({ children, tone="default", className="" }) {
  const tones = {
    default: { color:"var(--text-2)", bg:"var(--chip)" },
    accent:  { color:"var(--accent-400)", bg:"color-mix(in oklab, var(--accent-500) 14%, transparent)" },
    red:     { color:"var(--red-400)", bg:"color-mix(in oklab, var(--red-500) 16%, transparent)" },
    amber:   { color:"var(--amber-400)", bg:"color-mix(in oklab, var(--amber-500) 16%, transparent)" },
    green:   { color:"var(--green-400)", bg:"color-mix(in oklab, var(--green-500) 16%, transparent)" },
  };
  const t = tones[tone];
  return (
    <span className={`inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] font-medium ${className}`}
      style={{ color: t.color, background: t.bg }}>{children}</span>
  );
}

function Tabs({ tabs, value, onChange }) {
  return (
    <div className="flex gap-5 border-b border-soft">
      {tabs.map(t => (
        <button key={t.value} className={`tab ${value === t.value ? "active" : ""}`} onClick={() => onChange(t.value)}>
          {t.label}{t.count != null && <span className="ml-1.5 text-3 tnum">({t.count})</span>}
        </button>
      ))}
    </div>
  );
}

// Context menu
function ContextMenu({ x, y, items, onClose }) {
  const ref = useRef(null);
  useEffect(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    const onEsc = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onEsc);
    return () => { document.removeEventListener("mousedown", onDoc); document.removeEventListener("keydown", onEsc); };
  }, [onClose]);
  return (
    <div ref={ref} className="ctx-menu slide-in" style={{ left: x, top: y }}>
      {items.map((it, i) => it.sep
        ? <div key={i} style={{height:1, background:"var(--border)", margin:"4px 6px"}}/>
        : (
          <button key={i} onClick={() => { it.onClick && it.onClick(); onClose(); }}>
            {it.icon && <Icon name={it.icon} size={14} className="text-3"/>}
            <span className="flex-1">{it.label}</span>
            {it.hint && <span className="hint">{it.hint}</span>}
          </button>
        ))}
    </div>
  );
}

// Toast
function Toast({ text, onDone }) {
  useEffect(() => {
    const t = setTimeout(onDone, 2400);
    return () => clearTimeout(t);
  }, []);
  return (
    <div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 slide-in">
      <div className="px-3 py-2 rounded-lg bg-[var(--bg-raised)] border border-strong text-[12px] flex items-center gap-2 shadow-lg" style={{boxShadow:"var(--shadow-lg)"}}>
        <Icon name="check" size={14} className="accent-text"/>
        {text}
      </div>
    </div>
  );
}

function Breadcrumbs({ items, onNav }) {
  return (
    <nav className="flex items-center gap-1 text-[12px]">
      {items.map((it, i) => (
        <React.Fragment key={i}>
          {i > 0 && <Icon name="chevron-right" size={12} className="text-4"/>}
          {it.onClick || onNav ? (
            <button onClick={() => it.onClick ? it.onClick() : onNav(it)} className={`px-1 rounded hover:bg-[var(--surface-2)] ${i === items.length-1 ? "text-1 font-medium" : "text-3"}`}>
              {it.label}
            </button>
          ) : (
            <span className={i === items.length-1 ? "text-1 font-medium" : "text-3"}>{it.label}</span>
          )}
        </React.Fragment>
      ))}
    </nav>
  );
}

// Diff view inline
function Diff({ oldV, newV, money, ccy }) {
  const fmt = (v) => {
    if (money) return (ccy ? window.fmtCCY(v, ccy) : window.fmtHKD(v));
    if (typeof v === "string" && v.length > 40) return v.slice(0, 40) + "…";
    return String(v);
  };
  return (
    <span className="mono text-[11.5px]">
      <span className="diff-old">{fmt(oldV)}</span>
      <span className="diff-arrow">→</span>
      <span className="diff-new">{fmt(newV)}</span>
    </span>
  );
}

Object.assign(window, {
  Sparkline, StatusPill, SevDot, Ratio, Button, SearchInput, Select, Chip, Tabs,
  ContextMenu, Toast, Breadcrumbs, Diff,
});
