// ui.jsx — small UI atoms shared across screens

const { useState: useState_ui, useEffect: useEffect_ui, useRef: useRef_ui, useMemo: useMemo_ui } = React;

// Animated number that bumps when value changes
function AnimNum({ value, format = (n) => fmtNum(n) }) {
  const prev = useRef_ui(value);
  const [bump, setBump] = useState_ui(false);
  useEffect_ui(() => {
    if (prev.current !== value) {
      setBump(true);
      const t = setTimeout(() => setBump(false), 400);
      prev.current = value;
      return () => clearTimeout(t);
    }
  }, [value]);
  return <span className={"tick" + (bump ? " bump" : "")}>{format(value)}</span>;
}

// Sparkline SVG
function Sparkline({ data, width = 110, height = 32, color = "var(--accent)" }) {
  if (!data || data.length < 2) return null;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const step = width / (data.length - 1);
  const pts = data.map((v, i) => [i * step, height - ((v - min) / range) * (height - 4) - 2]);
  const path = pts.map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(1) + "," + p[1].toFixed(1)).join(" ");
  const area = path + ` L ${width},${height} L 0,${height} Z`;
  const gid = "spk-" + Math.random().toString(36).slice(2, 7);
  return (
    <svg width={width} height={height}>
      <defs>
        <linearGradient id={gid} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.45"/>
          <stop offset="100%" stopColor={color} stopOpacity="0"/>
        </linearGradient>
      </defs>
      <path d={area} fill={`url(#${gid})`}/>
      <path d={path} stroke={color} strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
      <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r="2.2" fill={color}/>
    </svg>
  );
}

// Modal
function Modal({ open, title, subtitle, children, onClose, footer, width }) {
  useEffect_ui(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose && onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={width ? { width } : null} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div style={{display:"flex", alignItems:"center", justifyContent:"space-between"}}>
            <h2>{title}</h2>
            <button className="icon-btn" onClick={onClose} style={{width:30,height:30}}><Icon name="x" size={16}/></button>
          </div>
          {subtitle && <p>{subtitle}</p>}
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
}

// Drawer
function Drawer({ open, title, subtitle, children, onClose, footer, width }) {
  useEffect_ui(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose && onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <React.Fragment>
      <div className="drawer-backdrop" onClick={onClose}/>
      <div className="drawer" style={width ? { width } : null}>
        <div className="drawer-head">
          <div style={{flex:1}}>
            <div style={{fontSize:15, fontWeight:700}}>{title}</div>
            {subtitle && <div className="muted" style={{fontSize:12, marginTop:2}}>{subtitle}</div>}
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16}/></button>
        </div>
        <div className="drawer-body">{children}</div>
        {footer && <div className="drawer-foot">{footer}</div>}
      </div>
    </React.Fragment>
  );
}

// QtyStepper
function QtyStepper({ value, onChange, min = 1, max = 99999 }) {
  const dec = () => onChange(Math.max(min, value - 1));
  const inc = () => onChange(Math.min(max, value + 1));
  return (
    <div className="qty-step">
      <button onClick={dec}>−</button>
      <input
        value={value}
        onChange={(e) => {
          const n = parseInt(e.target.value.replace(/[^0-9]/g, "") || "0", 10);
          onChange(Math.max(min, Math.min(max, n)));
        }}
      />
      <button onClick={inc}>+</button>
    </div>
  );
}

// Donut
function Donut({ segments, size = 180, thickness = 22 }) {
  // segments: [{value, color, label}]
  const total = segments.reduce((a, b) => a + b.value, 0) || 1;
  const radius = (size - thickness) / 2;
  const circ = 2 * Math.PI * radius;
  let acc = 0;
  return (
    <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
      <circle cx={size/2} cy={size/2} r={radius} stroke="rgba(255,255,255,0.05)" strokeWidth={thickness} fill="none"/>
      {segments.map((s, i) => {
        const len = (s.value / total) * circ;
        const dash = `${len} ${circ - len}`;
        const offset = -acc;
        acc += len;
        return (
          <circle key={i}
            cx={size/2} cy={size/2} r={radius}
            stroke={s.color} strokeWidth={thickness} fill="none"
            strokeDasharray={dash} strokeDashoffset={offset}
            strokeLinecap="butt"
            style={{ transition: "stroke-dasharray 600ms cubic-bezier(.2,.7,.2,1)" }}
          />
        );
      })}
    </svg>
  );
}

// Bar chart
function BarChart({ data, height = 180, color = "var(--accent)", maxBars = 30 }) {
  const slice = data.slice(-maxBars);
  const max = Math.max(...slice.map(d => Math.max(d.in || 0, d.out || 0)), 1);
  return (
    <div style={{display:"flex", alignItems:"flex-end", gap: 4, height, padding: "10px 4px 0"}}>
      {slice.map((d, i) => {
        const hIn = ((d.in || 0) / max) * (height - 28);
        const hOut = ((d.out || 0) / max) * (height - 28);
        return (
          <div key={i} style={{flex:1, display:"flex", flexDirection:"column", alignItems:"center", gap:2, position:"relative"}} title={`${d.label}: เข้า ${d.in}, ออก ${d.out}`}>
            <div style={{display:"flex", gap:2, alignItems:"flex-end", height: height - 22}}>
              <div style={{width: 6, height: hIn, background: "linear-gradient(180deg, var(--accent-2), rgba(56,211,163,0.4))", borderRadius:"3px 3px 0 0", transition:"height 500ms cubic-bezier(.2,.7,.2,1)"}}/>
              <div style={{width: 6, height: hOut, background: "linear-gradient(180deg, #ff8089, rgba(255,107,120,0.4))", borderRadius:"3px 3px 0 0", transition:"height 500ms cubic-bezier(.2,.7,.2,1)"}}/>
            </div>
            <div style={{fontSize: 9.5, color: "var(--text-dim)", fontFamily:"'JetBrains Mono', monospace"}}>{d.label}</div>
          </div>
        );
      })}
    </div>
  );
}

// Empty state
function EmptyState({ icon = "package", title, hint, action }) {
  return (
    <div style={{textAlign:"center", padding:"40px 20px", color:"var(--text-mute)"}}>
      <div style={{width:54, height:54, margin:"0 auto 12px", borderRadius:"50%", background:"rgba(255,255,255,0.04)", display:"grid", placeItems:"center", color:"var(--text-dim)"}}>
        <Icon name={icon} size={26}/>
      </div>
      <div style={{fontSize:14, color:"var(--text)", fontWeight:600}}>{title}</div>
      {hint && <div style={{fontSize:12.5, marginTop:6}}>{hint}</div>}
      {action && <div style={{marginTop:14}}>{action}</div>}
    </div>
  );
}

Object.assign(window, { AnimNum, Sparkline, Modal, Drawer, QtyStepper, Donut, BarChart, EmptyState });
