// Shared UI primitives + chrome (sidebar, topbar, modal, toast, badges, tooltips)
const { useState, useEffect, useRef, useMemo, useCallback, createContext, useContext } = React;

// ---------- Button ----------
const Button = ({ variant="primary", size="md", icon, iconRight, children, disabled, className="", ...rest }) => {
  const base = "inline-flex items-center justify-center gap-1.5 font-medium rounded-lg transition-all select-none whitespace-nowrap";
  const sizes = {
    sm: "h-7 px-2.5 text-xs",
    md: "h-9 px-3.5 text-[13px]",
    lg: "h-10 px-4 text-sm",
    icon: "h-9 w-9 text-[13px]",
    iconSm: "h-7 w-7 text-xs",
  };
  const variants = {
    primary: "bg-brand-600 text-white hover:bg-brand-700 active:bg-brand-800 shadow-sm",
    indigo:  "bg-indigo-600 text-white hover:bg-indigo-700 active:bg-indigo-800 shadow-sm",
    navy:    "bg-ink-900 text-white hover:bg-ink-800 active:bg-ink-950 shadow-sm",
    secondary:"bg-white border border-ink-200 text-ink-700 hover:bg-ink-50 hover:border-ink-300",
    ghost:   "text-ink-600 hover:bg-ink-100 hover:text-ink-800",
    danger:  "bg-rose-600 text-white hover:bg-rose-700",
    warn:    "bg-amber-500 text-white hover:bg-amber-600",
    success: "bg-emerald-600 text-white hover:bg-emerald-700",
    soft:    "bg-brand-50 text-brand-700 hover:bg-brand-100 border border-brand-100",
    outline: "bg-transparent border border-ink-300 text-ink-700 hover:bg-ink-50",
  };
  return (
    <button
      className={`${base} ${sizes[size]} ${variants[variant]} ${disabled?"opacity-50 pointer-events-none":""} ${className}`}
      disabled={disabled}
      {...rest}
    >
      {icon && <Icon name={icon} size={size==="sm"?13:14} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size==="sm"?13:14} />}
    </button>
  );
};

// ---------- Badge / chip ----------
const Badge = ({ color="slate", children, className="", icon }) => {
  const m = {
    slate:"bg-slate-100 text-slate-700 border-slate-200",
    indigo:"bg-indigo-50 text-indigo-700 border-indigo-100",
    blue:"bg-blue-50 text-blue-700 border-blue-100",
    violet:"bg-violet-50 text-violet-700 border-violet-100",
    amber:"bg-amber-50 text-amber-700 border-amber-100",
    emerald:"bg-emerald-50 text-emerald-700 border-emerald-100",
    rose:"bg-rose-50 text-rose-700 border-rose-100",
    sky:"bg-sky-50 text-sky-700 border-sky-100",
    dark:"bg-ink-900 text-ink-100 border-ink-800",
  };
  return (
    <span className={`inline-flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium border rounded-md ${m[color]} ${className}`}>
      {icon && <Icon name={icon} size={11}/>}{children}
    </span>
  );
};

// ---------- Avatar ----------
const Avatar = ({ name="", size=28, color }) => {
  const initials = (name||"").split(/\s+/).filter(Boolean).slice(0,2).map(s=>s[0]).join("").toUpperCase() || "?";
  const colors = ["bg-rose-500","bg-amber-500","bg-emerald-500","bg-sky-500","bg-indigo-500","bg-violet-500","bg-fuchsia-500"];
  const hash = (name||"").split("").reduce((a,c)=>a+c.charCodeAt(0),0);
  const c = color || colors[hash % colors.length];
  return (
    <div className={`${c} text-white font-semibold flex items-center justify-center rounded-full shrink-0`} style={{width:size,height:size,fontSize:size*0.38}}>
      {initials}
    </div>
  );
};

// ---------- Modal ----------
const Modal = ({ open, onClose, title, subtitle, children, width=520, footer, hideClose, tone="white" }) => {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose?.(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [open]);
  if (!open) return null;
  return (
    <div className="fixed inset-0 z-[80] flex items-center justify-center p-4 fade-in" style={{background:"rgba(20,24,55,.45)"}} onClick={onClose}>
      <div
        className={`relative ${tone==="dark"?"bg-ink-900 text-white":"bg-white"} rounded-2xl shadow-2xl pop overflow-hidden`}
        style={{ width, maxWidth:"95vw", maxHeight:"90vh" }}
        onClick={(e) => e.stopPropagation()}
      >
        {(title || !hideClose) && (
          <div className={`flex items-start gap-4 px-5 pt-4 pb-3 ${tone==="dark"?"":"border-b border-ink-100"}`}>
            <div className="flex-1 min-w-0">
              {title && <div className={`text-[15px] font-semibold ${tone==="dark"?"text-white":"text-ink-900"}`}>{title}</div>}
              {subtitle && <div className={`text-xs mt-0.5 ${tone==="dark"?"text-ink-300":"text-ink-500"}`}>{subtitle}</div>}
            </div>
            {!hideClose && (
              <button onClick={onClose} className={`shrink-0 -mr-1 -mt-1 p-1.5 rounded-lg hover:bg-ink-100 ${tone==="dark"?"text-ink-300 hover:bg-ink-800":"text-ink-500"}`}>
                <Icon name="x" size={16}/>
              </button>
            )}
          </div>
        )}
        <div className="px-5 py-4 max-h-[60vh] overflow-y-auto thin-scroll">{children}</div>
        {footer && <div className={`px-5 py-3 ${tone==="dark"?"border-t border-ink-800 bg-ink-950/40":"border-t border-ink-100 bg-ink-50/60"} flex items-center justify-end gap-2`}>{footer}</div>}
      </div>
    </div>
  );
};

// ---------- Drawer (right side) ----------
const Drawer = ({ open, onClose, title, subtitle, children, width=460, footer }) => {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") onClose?.(); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [open]);
  return (
    <div className={`fixed inset-0 z-[70] ${open?"pointer-events-auto":"pointer-events-none"}`}>
      <div className={`absolute inset-0 transition-opacity ${open?"opacity-100":"opacity-0"}`}
           style={{background:"rgba(20,24,55,.4)"}} onClick={onClose}/>
      <div
        className={`absolute top-0 right-0 h-full bg-white shadow-2xl flex flex-col transition-transform duration-300 ${open?"translate-x-0":"translate-x-full"}`}
        style={{width, maxWidth:"95vw"}}>
        <div className="flex items-start gap-3 px-5 py-4 border-b border-ink-100">
          <div className="flex-1 min-w-0">
            <div className="text-[14px] font-semibold text-ink-900">{title}</div>
            {subtitle && <div className="text-xs text-ink-500 mt-0.5">{subtitle}</div>}
          </div>
          <button onClick={onClose} className="p-1.5 rounded-lg hover:bg-ink-100 text-ink-500"><Icon name="x" size={16}/></button>
        </div>
        <div className="flex-1 overflow-y-auto thin-scroll">{children}</div>
        {footer && <div className="border-t border-ink-100 px-5 py-3 bg-ink-50/60">{footer}</div>}
      </div>
    </div>
  );
};

// ---------- Toast context ----------
const ToastContext = createContext(null);
const useToast = () => useContext(ToastContext);

const ToastProvider = ({ children }) => {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts(prev => [...prev, { id, kind:"info", ...t }]);
    setTimeout(() => setToasts(prev => prev.filter(x => x.id !== id)), 3600);
  }, []);
  return (
    <ToastContext.Provider value={push}>
      {children}
      <div className="fixed bottom-5 right-5 z-[120] flex flex-col gap-2 items-end">
        {toasts.map(t => {
          const tones = {
            success: "bg-emerald-600",
            error:"bg-rose-600",
            warn:"bg-amber-500",
            info:"bg-ink-900",
          };
          const icon = { success:"checkCircle", error:"alert", warn:"alert", info:"info" }[t.kind];
          return (
            <div key={t.id} className={`toast-in ${tones[t.kind]} text-white rounded-xl shadow-2xl flex items-start gap-2.5 px-3.5 py-2.5 max-w-sm`}>
              <Icon name={icon} size={16} className="mt-0.5 shrink-0"/>
              <div className="text-[13px] leading-snug">{t.msg}</div>
            </div>
          );
        })}
      </div>
    </ToastContext.Provider>
  );
};

// ---------- Form bits ----------
const Field = ({ label, hint, required, error, children, className="" }) => (
  <label className={`block ${className}`}>
    <div className="text-[12px] font-medium text-ink-700 mb-1 flex items-center gap-1">
      {label}{required && <span className="text-rose-500">*</span>}
      {hint && <span className="text-ink-400 font-normal">· {hint}</span>}
    </div>
    {children}
    {error && <div className="text-[11px] text-rose-600 mt-1">{error}</div>}
  </label>
);

const Input = ({ className="", ...props }) => (
  <input {...props} className={`w-full h-9 px-3 text-[13px] border border-ink-200 rounded-lg bg-white text-ink-900 placeholder-ink-400 focus:border-brand-500 ring-focus transition ${className}`} />
);
const Textarea = ({ className="", rows=3, ...props }) => (
  <textarea rows={rows} {...props} className={`w-full px-3 py-2 text-[13px] border border-ink-200 rounded-lg bg-white text-ink-900 placeholder-ink-400 focus:border-brand-500 ring-focus transition ${className}`} />
);
const Select = ({ className="", children, ...props }) => (
  <div className="relative">
    <select {...props} className={`w-full h-9 pl-3 pr-8 text-[13px] border border-ink-200 rounded-lg bg-white text-ink-900 appearance-none focus:border-brand-500 ring-focus transition ${className}`}>
      {children}
    </select>
    <Icon name="chevronDown" size={14} className="absolute right-2.5 top-1/2 -translate-y-1/2 text-ink-400 pointer-events-none"/>
  </div>
);

const Checkbox = ({ checked, onChange, label, className="" }) => (
  <button type="button" onClick={onChange} className={`inline-flex items-center gap-2 cursor-pointer select-none ${className}`}>
    <span className={`relative w-4 h-4 rounded border ${checked?"bg-brand-600 border-brand-600":"bg-white border-ink-300"} transition`}>
      {checked && <Icon name="check" size={12} className="text-white absolute inset-0 m-auto"/>}
    </span>
    {label && <span className="text-[13px] text-ink-700">{label}</span>}
  </button>
);

const Toggle = ({ checked, onChange, label, className="" }) => (
  <button type="button" onClick={onChange} className={`inline-flex items-center gap-2 cursor-pointer select-none ${className}`}>
    <span className={`relative w-8 h-4 rounded-full transition ${checked?"bg-brand-600":"bg-ink-200"}`}>
      <span className={`absolute top-0.5 left-0.5 w-3 h-3 rounded-full bg-white shadow transition-transform ${checked?"translate-x-4":""}`}/>
    </span>
    {label && <span className="text-[12px] text-ink-700">{label}</span>}
  </button>
);

// ---------- Segmented control ----------
const Segmented = ({ value, onChange, options, size="md" }) => {
  const h = size==="sm" ? "h-7 text-[11.5px]" : "h-8 text-xs";
  return (
    <div className={`inline-flex items-center bg-ink-100 rounded-lg p-0.5 ${h}`}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)}
          className={`px-2.5 rounded-md font-medium transition ${value===o.value?"bg-white text-ink-900 shadow-sm":"text-ink-500 hover:text-ink-800"}`}>
          {o.label}
        </button>
      ))}
    </div>
  );
};

// ---------- Empty state ----------
const EmptyState = ({ icon="inbox", title, subtitle, action }) => (
  <div className="flex flex-col items-center justify-center text-center py-16 px-6">
    <div className="w-14 h-14 rounded-2xl bg-ink-100 text-ink-400 flex items-center justify-center mb-3">
      <Icon name={icon} size={22}/>
    </div>
    <div className="text-[14px] font-semibold text-ink-800">{title}</div>
    {subtitle && <div className="text-xs text-ink-500 mt-1 max-w-sm">{subtitle}</div>}
    {action && <div className="mt-3">{action}</div>}
  </div>
);

// ---------- Confirmation w/ reason ----------
const ReasonModal = ({ open, onClose, onConfirm, title, subtitle, confirmLabel="ยืนยัน", tone="danger", placeholder="โปรดระบุเหตุผล…" }) => {
  const [reason, setReason] = useState("");
  useEffect(() => { if (open) setReason(""); }, [open]);
  const toneBtn = tone==="danger" ? "danger" : tone==="warn" ? "warn" : "primary";
  return (
    <Modal open={open} onClose={onClose} title={title} subtitle={subtitle} width={520}
      footer={<>
        <Button variant="secondary" onClick={onClose}>ยกเลิก</Button>
        <Button variant={toneBtn} disabled={!reason.trim()} onClick={() => { onConfirm(reason.trim()); onClose(); }}>{confirmLabel}</Button>
      </>}
    >
      <Field label="เหตุผล" required hint="จะถูกบันทึกใน Audit Log อัตโนมัติ">
        <Textarea rows={4} placeholder={placeholder} value={reason} onChange={e=>setReason(e.target.value)} autoFocus/>
      </Field>
    </Modal>
  );
};

// ---------- Sidebar item ----------
const SidebarItem = ({ icon, label, active, onClick, badge, collapsed, dark }) => (
  <button onClick={onClick}
    className={`group w-full flex items-center gap-3 ${collapsed?"justify-center px-2":"px-3"} h-9 rounded-lg transition text-[13px] font-medium
      ${active
        ? dark ? "bg-white/10 text-white" : "bg-brand-50 text-brand-700"
        : dark ? "text-ink-300 hover:bg-white/5 hover:text-white" : "text-ink-600 hover:bg-ink-100 hover:text-ink-900"}`}>
    <Icon name={icon} size={16} className={active ? (dark?"text-white":"text-brand-600") : ""}/>
    {!collapsed && <span className="flex-1 text-left truncate">{label}</span>}
    {!collapsed && badge != null && (
      <span className={`text-[10px] px-1.5 py-0.5 rounded-md font-semibold ${active ? (dark?"bg-white/20 text-white":"bg-brand-600 text-white") : "bg-ink-200 text-ink-600"}`}>{badge}</span>
    )}
  </button>
);

// ---------- RACI badge ----------
const RaciBadge = ({ kind, size="md", style="default" }) => {
  const meta = RACI_META[kind];
  if (!meta) return null;
  const sz = size==="sm" ? "w-5 h-5 text-[10px]" : "w-6 h-6 text-[11px]";
  if (style === "outlined") {
    return (
      <span title={meta.label} className={`inline-flex items-center justify-center ${sz} rounded-md border ${meta.text} border-current font-bold bg-transparent`}>
        {meta.short}
      </span>
    );
  }
  if (style === "dot") {
    const dotColor = { R:"#2563eb", A:"#7c3aed", C:"#d97706", I:"#059669" }[kind];
    return (
      <span title={meta.label} className="inline-flex items-center justify-center" style={{width:14, height:14}}>
        <span style={{width:9, height:9, borderRadius:9, background:dotColor}}/>
      </span>
    );
  }
  return (
    <span title={meta.label} className={`inline-flex items-center justify-center font-bold ${sz} ${meta.bg} ${meta.text} rounded-md ring-1 ${meta.ring}`}>
      {meta.short}
    </span>
  );
};

// ---------- Status pill / button ----------
const StatusPill = ({ status }) => {
  const m = STATUS_META[status] || STATUS_META.blank;
  return (
    <span className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md border ${m.bg} ${m.text} ${m.border} text-[11.5px] font-medium`}>
      <span className="w-1.5 h-1.5 rounded-full" style={{ background:m.dot }}/>
      <span className="font-semibold">{m.short !== "-" ? m.short : ""}</span>
      <span>{m.label}</span>
    </span>
  );
};

// ---------- KPI card ----------
const KpiCard = ({ icon, label, value, trend, tone="indigo", onClick, active }) => {
  const tones = {
    indigo:"from-indigo-500 to-indigo-600",
    emerald:"from-emerald-500 to-emerald-600",
    amber:"from-amber-500 to-amber-600",
    rose:"from-rose-500 to-rose-600",
    sky:"from-sky-500 to-sky-600",
    violet:"from-violet-500 to-violet-600",
    slate:"from-slate-500 to-slate-600",
  };
  return (
    <button onClick={onClick}
      className={`text-left w-full bg-white rounded-2xl border ${active?"border-brand-400 ring-2 ring-brand-100":"border-ink-100"} p-4 transition hover:shadow-lg hover:-translate-y-0.5`}>
      <div className="flex items-start gap-3">
        <div className={`shrink-0 w-9 h-9 rounded-xl bg-gradient-to-br ${tones[tone]} text-white flex items-center justify-center`}>
          <Icon name={icon} size={16}/>
        </div>
        <div className="min-w-0 flex-1">
          <div className="text-[11.5px] text-ink-500">{label}</div>
          <div className="text-[22px] font-bold text-ink-900 leading-tight font-mono">{value}</div>
          {trend && <div className="text-[11px] text-ink-500 mt-0.5">{trend}</div>}
        </div>
      </div>
    </button>
  );
};

// ---------- Tooltip wrapper ----------
const Tip = ({ tip, children, className="" }) => (
  <span data-tip={tip} className={className}>{children}</span>
);

// ---------- Section title ----------
const PageHeader = ({ title, subtitle, right, tabs, tab, onTab, eyebrow }) => (
  <div className="flex flex-col gap-3 mb-4">
    <div className="flex items-end justify-between gap-4 flex-wrap">
      <div>
        {eyebrow && <div className="text-[11px] tracking-[.18em] font-semibold text-brand-600 uppercase mb-1">{eyebrow}</div>}
        <h1 className="text-[22px] font-bold text-ink-900 leading-tight">{title}</h1>
        {subtitle && <div className="text-[13px] text-ink-500 mt-0.5">{subtitle}</div>}
      </div>
      <div className="flex items-center gap-2 flex-wrap">{right}</div>
    </div>
    {tabs && (
      <div className="flex items-center gap-1 border-b border-ink-200">
        {tabs.map(t => (
          <button key={t.value} onClick={() => onTab(t.value)}
            className={`relative px-3 py-2 text-[13px] font-medium transition ${tab===t.value?"text-ink-900":"text-ink-500 hover:text-ink-800"}`}>
            {t.label}
            {tab===t.value && <span className="absolute -bottom-px left-0 right-0 h-0.5 bg-brand-600 rounded-t"/>}
          </button>
        ))}
      </div>
    )}
  </div>
);

Object.assign(window, {
  Button, Badge, Avatar, Modal, Drawer, ToastProvider, ToastContext, useToast,
  Field, Input, Textarea, Select, Checkbox, Toggle, Segmented, EmptyState, ReasonModal,
  SidebarItem, RaciBadge, StatusPill, KpiCard, Tip, PageHeader,
});

// ---------- CSV Export ----------
const downloadCsv = (filename, headers, rows) => {
  const escape = (v) => {
    if (v == null) return "";
    const s = String(v).replace(/"/g, '""');
    return /[",\n]/.test(s) ? `"${s}"` : s;
  };
  const csv = [headers.map(escape).join(","), ...rows.map(r => r.map(escape).join(","))].join("\n");
  // Add BOM so Excel reads UTF-8 (Thai) correctly
  const blob = new Blob(["\uFEFF" + csv], { type: "text/csv;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(url), 1000);
};

window.downloadCsv = downloadCsv;
