/* ============================================================
   Serabi CRM — Shared components, icons, i18n
   ============================================================ */
const { useState, useEffect, useRef, useMemo, createContext, useContext } = React;

/* ---------------- i18n ---------------- */
const STRINGS = {
  // nav
  dashboard:   ["Beranda", "Dashboard"],
  inbox:       ["Pesan", "Inbox"],
  contacts:    ["Kontak", "Contacts"],
  knowledge:   ["Knowledge Base", "Knowledge Base"],
  broadcast:   ["Broadcast", "Broadcast"],
  credits:     ["Token AI", "AI Tokens"],
  settings:    ["Pengaturan", "Settings"],
  // generic
  search:      ["Cari", "Search"],
  save:        ["Simpan", "Save"],
  cancel:      ["Batal", "Cancel"],
  send:        ["Kirim", "Send"],
  add:         ["Tambah", "Add"],
  connected:   ["Tersambung", "Connected"],
  notConnected:["Belum tersambung", "Not connected"],
  online:      ["Aktif", "Active"],
  needHuman:   ["Perlu Manusia", "Needs Human"],
  aiOn:        ["AI Aktif", "AI On"],
  aiOff:       ["AI Mati", "AI Off"],
  today:       ["Hari ini", "Today"],
  viewAll:     ["Lihat semua", "View all"],
};
const I18N = createContext({ lang: "id", t: (k) => k });
function useI18n() { return useContext(I18N); }
function tr(lang, k) {
  const e = STRINGS[k];
  if (!e) return k;
  return lang === "en" ? e[1] : e[0];
}

/* ---------------- Icons (feather-style stroke set) ---------------- */
const ICONS = {
  home:       "M3 10.5 12 3l9 7.5M5 9.5V21h14V9.5",
  chat:       "M21 11.5a8.38 8.38 0 0 1-9 8.34 9.5 9.5 0 0 1-4-1L3 20l1.2-4A8.5 8.5 0 1 1 21 11.5Z",
  users:      "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM22 21v-2a4 4 0 0 0-3-3.87M16 3.13A4 4 0 0 1 16 11",
  book:       "M4 19.5A2.5 2.5 0 0 1 6.5 17H20M4 19.5A2.5 2.5 0 0 0 6.5 22H20V2H6.5A2.5 2.5 0 0 0 4 4.5v15Z",
  megaphone:  "M3 11v2a1 1 0 0 0 1 1h2l3.5 4V6L6 10H4a1 1 0 0 0-1 1ZM14 8a4 4 0 0 1 0 8M9.5 18v2.5a1.5 1.5 0 0 0 3 0V18",
  coin:       "M12 8v8M9.5 14.2c0 1 .9 1.8 2.5 1.8s2.5-.7 2.5-1.7-1-1.5-2.5-1.8-2.5-.8-2.5-1.8.9-1.7 2.5-1.7 2.5.8 2.5 1.8M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Z",
  gear:       "M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z|M19.4 13a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-2.82 1.17V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 6.6 19.4l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 13H4a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 5.4 6.6l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 11 4.6V4a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 2.4 1.51l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 11H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z",
  search:     "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.3-4.3",
  bell:       "M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 0 1-3.4 0",
  plus:       "M12 5v14M5 12h14",
  check:      "M20 6 9 17l-5-5",
  checkDouble:"M1 13l4 4L13 9|M9 13l4 4L23 5",
  x:          "M18 6 6 18M6 6l12 12",
  send:       "M22 2 11 13M22 2l-7 20-4-9-9-4 20-7Z",
  sparkle:    "M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9L12 3ZM19 3v4M21 5h-4M5 17v3M6.5 18.5h-3",
  bot:        "M12 7V4M8 7h8a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2ZM2 13h2M20 13h2M9.5 12.5v1M14.5 12.5v1M9 17h6",
  user:       "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z",
  arrowRight: "M5 12h14M13 6l6 6-6 6",
  arrowLeft:  "M19 12H5M11 18l-6-6 6-6",
  chevDown:   "M6 9l6 6 6-6",
  chevRight:  "M9 6l6 6-6 6",
  logout:     "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9",
  phone:      "M22 16.92v3a2 2 0 0 1-2.18 2 19.8 19.8 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.9.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92Z",
  qr:         "M3 3h7v7H3V3ZM14 3h7v7h-7V3ZM3 14h7v7H3v-7ZM14 14h3v3h-3v-3ZM18 18h3v3h-3v-3ZM14 18h1M18 14h3",
  image:      "M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5ZM9 10a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM21 15l-5-5L5 21",
  mic:        "M12 2a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3ZM5 10v1a7 7 0 0 0 14 0v-1M12 18v4",
  file:       "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6ZM14 2v6h6",
  paperclip:  "M21 11.5 12 20.5a5 5 0 0 1-7-7l9-9a3.5 3.5 0 0 1 5 5l-9 9a1.5 1.5 0 0 1-2-2l8-8",
  smile:      "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM8 14s1.5 2 4 2 4-2 4-2M9 9h.01M15 9h.01",
  clock:      "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM12 7v5l3 2",
  trend:      "M22 7 13.5 15.5 8.5 10.5 2 17M22 7h-6M22 7v6",
  trendDown:  "M22 17 13.5 8.5 8.5 13.5 2 7M22 17h-6M22 17v-6",
  alert:      "M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0ZM12 9v4M12 17h.01",
  shield:     "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z",
  shieldCheck:"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10ZM9 12l2 2 4-4",
  upload:     "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12",
  download:   "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3",
  tag:        "M20.6 13.4 12 22l-9-9V3h10l7.6 7.6a2 2 0 0 1 0 2.8ZM7.5 7.5h.01",
  filter:     "M22 3H2l8 9.5V19l4 2v-8.5L22 3Z",
  edit:       "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7M18.5 2.5a2.1 2.1 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5Z",
  trash:      "M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",
  copy:       "M9 9h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2V11a2 2 0 0 1 2-2ZM5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1",
  globe:      "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM3 12h18M12 3a14 14 0 0 1 0 18 14 14 0 0 1 0-18Z",
  google:     "G",
  menu:       "M3 6h18M3 12h18M3 18h18",
  pause:      "M6 4h4v16H6zM14 4h4v16h-4z",
  play:       "M5 3l16 9-16 9V3Z",
  zap:        "M13 2 3 14h7l-1 8 10-12h-7l1-8Z",
  doc:        "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6ZM14 2v6h6M9 13h6M9 17h4",
  location:   "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0ZM12 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z",
  refresh:    "M21 12a9 9 0 1 1-3-6.7M21 4v5h-5",
  info:       "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM12 16v-4M12 8h.01",
  star:       "M12 2l3 6.5 7 .9-5 4.8 1.3 7L12 18l-6.3 3.2L7 14.2 2 9.4l7-.9L12 2Z",
  external:   "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14 21 3",
  sticker:    "M21 3v8a10 10 0 0 1-10 10H3V3h18ZM13 21v-6a2 2 0 0 1 2-2h6",
  list:       "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01",
};
function Icon({ name, size = 20, className = "", style = {}, fill = false }) {
  if (name === "google") return <GoogleG size={size} />;
  const d = ICONS[name] || ICONS.info;
  const paths = d.split("|");
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill ? "currentColor" : "none"}
      stroke="currentColor" strokeWidth={fill ? 0 : 1.9} strokeLinecap="round" strokeLinejoin="round"
      className={className} style={style} aria-hidden="true">
      {paths.map((p, i) => <path key={i} d={p} />)}
    </svg>
  );
}
function GoogleG({ size = 20 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
      <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1Z"/>
      <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84A11 11 0 0 0 12 23Z"/>
      <path fill="#FBBC05" d="M5.84 14.1a6.6 6.6 0 0 1 0-4.2V7.06H2.18a11 11 0 0 0 0 9.88l3.66-2.84Z"/>
      <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1A11 11 0 0 0 2.18 7.06l3.66 2.84C6.71 7.3 9.14 5.38 12 5.38Z"/>
    </svg>
  );
}

/* ---------------- Avatar ---------------- */
const AVATAR_COLORS = [
  "oklch(0.6 0.13 156)","oklch(0.62 0.14 40)","oklch(0.58 0.14 295)",
  "oklch(0.6 0.13 240)","oklch(0.64 0.13 76)","oklch(0.58 0.15 350)",
  "oklch(0.6 0.13 195)","oklch(0.58 0.14 130)",
];
function colorFor(str) {
  let h = 0; for (let i = 0; i < str.length; i++) h = (h * 31 + str.charCodeAt(i)) >>> 0;
  return AVATAR_COLORS[h % AVATAR_COLORS.length];
}
function initials(name) {
  const p = name.trim().split(/\s+/);
  return ((p[0]?.[0] || "") + (p[1]?.[0] || "")).toUpperCase();
}
function Avatar({ name = "?", size = 40, className = "" }) {
  return (
    <span className={"avatar " + className} style={{ width: size, height: size, background: colorFor(name), fontSize: size * 0.36 }}>
      {initials(name)}
    </span>
  );
}

/* ---------------- Toggle switch ---------------- */
function Switch({ on, onChange, size = "", color = "" }) {
  return (
    <button className={`switch ${size} ${color} ${on ? "on" : ""}`} onClick={(e) => { e.stopPropagation(); onChange?.(!on); }} aria-pressed={on} />
  );
}

/* ---------------- Toast system ---------------- */
const ToastCtx = createContext(() => {});
function useToast() { return useContext(ToastCtx); }
function ToastHost({ children }) {
  const [items, setItems] = useState([]);
  const push = (msg, icon = "check") => {
    const id = Math.random();
    setItems((s) => [...s, { id, msg, icon }]);
    setTimeout(() => setItems((s) => s.filter((i) => i.id !== id)), 2600);
  };
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="toast-wrap">
        {items.map((i) => (
          <div className="toast" key={i.id}>
            <Icon name={i.icon} className="t-ok" /> {i.msg}
          </div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
}

/* ---------------- Modal ---------------- */
function Modal({ open, onClose, children, max = 480 }) {
  useEffect(() => {
    if (!open) return;
    const h = (e) => e.key === "Escape" && onClose?.();
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="scrim" onClick={onClose}>
      <div className="modal" style={{ maxWidth: max }} onClick={(e) => e.stopPropagation()}>
        {children}
      </div>
    </div>
  );
}

/* ---------------- Stat / Sparkline ---------------- */
function Sparkline({ data, color = "var(--green)", w = 120, h = 36, fill = true }) {
  const max = Math.max(...data), min = Math.min(...data);
  const rng = max - min || 1;
  const pts = data.map((v, i) => [ (i / (data.length - 1)) * w, h - 4 - ((v - min) / rng) * (h - 8) ]);
  const line = pts.map((p, i) => (i ? "L" : "M") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" ");
  const area = line + ` L${w} ${h} L0 ${h} Z`;
  const gid = "spark" + useMemo(() => Math.random().toString(36).slice(2), []);
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} style={{ display: "block", overflow: "visible" }}>
      <defs>
        <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor={color} stopOpacity="0.22" />
          <stop offset="1" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      {fill && <path d={area} fill={`url(#${gid})`} />}
      <path d={line} fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ---------------- Donut ring ---------------- */
function Ring({ pct, size = 64, stroke = 8, color = "var(--green)", track = "var(--bg-2)", children }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  return (
    <div style={{ position: "relative", width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={track} strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={color} strokeWidth={stroke}
          strokeDasharray={c} strokeDashoffset={c * (1 - pct/100)} strokeLinecap="round"
          style={{ transition: "stroke-dashoffset .6s cubic-bezier(.3,1,.4,1)" }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column" }}>
        {children}
      </div>
    </div>
  );
}

/* ---------------- Logo ---------------- */
function Logo({ size = 32, mono = false }) {
  return (
    <div className="row" style={{ gap: 9 }}>
      <span style={{
        width: size, height: size, borderRadius: size * 0.3, flex: "none",
        background: mono ? "white" : "linear-gradient(135deg, var(--green) 0%, var(--green-700) 100%)",
        display: "flex", alignItems: "center", justifyContent: "center",
        boxShadow: mono ? "none" : "0 4px 10px oklch(0.55 0.13 156 / 0.35)",
      }}>
        <svg width={size*0.6} height={size*0.6} viewBox="0 0 24 24" fill="none"
          stroke={mono ? "var(--green-700)" : "white"} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M21 11.5a8.38 8.38 0 0 1-9 8.34 9.5 9.5 0 0 1-4-1L3 20l1.2-4A8.5 8.5 0 1 1 21 11.5Z" />
          <path d="M9 11.5h.01M12 11.5h.01M15 11.5h.01" />
        </svg>
      </span>
      <span style={{ fontWeight: 800, fontSize: size * 0.56, letterSpacing: "-0.03em", color: mono ? "white" : "var(--ink)" }}>
        Serabi
      </span>
    </div>
  );
}

/* ---------------- Empty state ---------------- */
function Empty({ icon = "inbox", title, sub, children }) {
  return (
    <div className="center" style={{ flexDirection: "column", padding: "48px 24px", textAlign: "center", color: "var(--ink-3)" }}>
      <div className="center" style={{ width: 56, height: 56, borderRadius: 16, background: "var(--bg-2)", color: "var(--ink-3)", marginBottom: 14 }}>
        <Icon name={icon} size={26} />
      </div>
      <div style={{ fontWeight: 700, color: "var(--ink)", fontSize: 16 }}>{title}</div>
      {sub && <div className="muted" style={{ marginTop: 5, maxWidth: 320 }}>{sub}</div>}
      {children && <div style={{ marginTop: 16 }}>{children}</div>}
    </div>
  );
}

/* ---------------- QR code (generated pattern placeholder) ---------------- */
function QRCode({ size = 200, seed = 7 }) {
  const n = 25;
  const cells = useMemo(() => {
    let s = seed * 9301 + 49297;
    const rnd = () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
    const g = Array.from({ length: n }, () => Array.from({ length: n }, () => rnd() > 0.52));
    // finder patterns
    const finder = (r, c) => {
      for (let i = -1; i <= 7; i++) for (let j = -1; j <= 7; j++) {
        const rr = r + i, cc = c + j;
        if (rr < 0 || cc < 0 || rr >= n || cc >= n) continue;
        const border = i === 0 || i === 6 || j === 0 || j === 6;
        const inner = i >= 2 && i <= 4 && j >= 2 && j <= 4;
        const out = i < 0 || i > 6 || j < 0 || j > 6;
        g[rr][cc] = out ? false : (border || inner);
      }
    };
    finder(0, 0); finder(0, n - 7); finder(n - 7, 0);
    return g;
  }, [seed]);
  const cell = size / n;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ borderRadius: 8, display: "block" }}>
      <rect width={size} height={size} fill="white" />
      {cells.map((row, r) => row.map((v, c) => v ? (
        <rect key={r + "-" + c} x={c * cell} y={r * cell} width={cell + 0.5} height={cell + 0.5} fill="#111b14" rx={cell * 0.2} />
      ) : null))}
    </svg>
  );
}

Object.assign(window, {
  useState, useEffect, useRef, useMemo, createContext, useContext,
  STRINGS, I18N, useI18n, tr,
  Icon, GoogleG, Avatar, colorFor, initials, Switch,
  ToastHost, useToast, Modal, Sparkline, Ring, Logo, Empty, QRCode,
});
