// HelperMatch Admin — Shared UI kit (icons, badges, modal, drawer, toasts, common controls)
const { useState, useEffect, useRef, useMemo, useLayoutEffect, createContext, useContext, Fragment } = React;

// ========= Icons =========
const AIconPaths = {
  dashboard: <><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></>,
  users: <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></>,
  user: <><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></>,
  employer: <><path d="M3 21h18"/><path d="M5 21V7l8-4v18"/><path d="M19 21V11l-6-4"/><path d="M9 9v.01"/><path d="M9 12v.01"/><path d="M9 15v.01"/><path d="M9 18v.01"/></>,
  clipboardCheck: <><rect x="8" y="4" width="8" height="4" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="m9 14 2 2 4-4"/></>,
  video: <><rect x="3" y="6" width="12" height="12" rx="2"/><path d="m15 10 6-3v10l-6-3Z"/></>,
  card: <><rect x="2" y="5" width="20" height="14" rx="2"/><line x1="2" y1="10" x2="22" y2="10"/></>,
  article: <><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="14" y2="17"/></>,
  gift: <><polyline points="20 12 20 22 4 22 4 12"/><rect x="2" y="7" width="20" height="5"/><line x1="12" y1="22" x2="12" y2="7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></>,
  wallet: <><path d="M20 12V8H6a2 2 0 0 1-2-2c0-1.1.9-2 2-2h12v4"/><path d="M4 6v12c0 1.1.9 2 2 2h14v-4"/><path d="M18 12a2 2 0 0 0 0 4h4v-4z"/></>,
  coins: <><circle cx="8" cy="8" r="6"/><path d="M18.09 10.37A6 6 0 1 1 10.34 18"/><path d="M7 6h1v4"/><path d="m16.71 13.88.7.71-2.82 2.82"/></>,
  arrows: <><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></>,
  settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3h0a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5h0a1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8v0a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z"/></>,
  search: <><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></>,
  filter: <><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></>,
  plus: <><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></>,
  check: <polyline points="20 6 9 17 4 12"/>,
  checkCircle: <><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></>,
  x: <><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></>,
  xCircle: <><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></>,
  chevRight: <polyline points="9 18 15 12 9 6"/>,
  chevLeft: <polyline points="15 18 9 12 15 6"/>,
  chevDown: <polyline points="6 9 12 15 18 9"/>,
  chevUp: <polyline points="18 15 12 9 6 15"/>,
  arrowRight: <><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></>,
  arrowLeft: <><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></>,
  arrowUp: <><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></>,
  arrowDown: <><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></>,
  clock: <><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></>,
  calendar: <><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></>,
  alert: <><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></>,
  info: <><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></>,
  eye: <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>,
  eyeOff: <><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></>,
  edit: <><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></>,
  trash: <><polyline points="3 6 5 6 21 6"/><path d="M19 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"/></>,
  save: <><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></>,
  download: <><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></>,
  upload: <><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></>,
  copy: <><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></>,
  external: <><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></>,
  dots: <><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></>,
  dotsH: <><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></>,
  lock: <><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>,
  flag: <><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></>,
  shield: <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>,
  bell: <><path d="M6 8a6 6 0 1 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></>,
  globe: <><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></>,
  logout: <><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></>,
  history: <><path d="M3 3v5h5"/><path d="M3.05 13A9 9 0 1 0 6 5.3L3 8"/><polyline points="12 7 12 12 15 14"/></>,
  link: <><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></>,
  refresh: <><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></>,
  play: <polygon points="5 3 19 12 5 21 5 3" fill="currentColor"/>,
  message: <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>,
  heart: <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>,
  star: <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" fill="currentColor"/>,
  briefcase: <><rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/></>,
  location: <><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z"/><circle cx="12" cy="10" r="3"/></>,
  ban: <><circle cx="12" cy="12" r="10"/><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/></>,
  phone: <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 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-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/>,
  mail: <><rect x="2" y="4" width="20" height="16" rx="2"/><polyline points="22 6 12 13 2 6"/></>,
  file: <><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></>,
  bold: <><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/></>,
  italic: <><line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/></>,
  list: <><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></>,
  h1: <><path d="M4 12h8"/><path d="M4 18V6"/><path d="M12 18V6"/><path d="m17 12 3-2v8"/></>,
  h2: <><path d="M4 12h8"/><path d="M4 18V6"/><path d="M12 18V6"/><path d="M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1"/></>,
  h3: <><path d="M4 12h8"/><path d="M4 18V6"/><path d="M12 18V6"/><path d="M17.5 10.5h3l-2 3a2 2 0 1 1-1.5 3.4"/></>,
  code: <><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></>,
  listNum: <><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></>,
  hr: <><line x1="3" y1="12" x2="21" y2="12"/></>,
  archive: <><polyline points="21 8 21 21 3 21 3 8"/><rect x="1" y="3" width="22" height="5"/><line x1="10" y1="12" x2="14" y2="12"/></>,
  chat: <><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></>,
  quote: <><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.76-2.017-2-2H4c-1.24 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z"/><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.76-2.017-2-2h-4c-1.24 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c1 0 1.25.25 1.25 1.25v1.5C18 16.75 17 17 15.75 17H15c-1 0-1 .008-1 1.031V20c0 1 0 1 1 1z"/></>,
  image: <><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></>,
  menu: <><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="18" x2="20" y2="18"/></>,
  idCard: <><rect x="2" y="5" width="20" height="14" rx="2"/><circle cx="9" cy="12" r="2.5"/><line x1="14" y1="10" x2="19" y2="10"/><line x1="14" y1="13" x2="19" y2="13"/><path d="M6 17c0-2 1.5-3 3-3s3 1 3 3"/></>,
  passport: <><rect x="4" y="2" width="16" height="20" rx="2"/><circle cx="12" cy="11" r="3.5"/><path d="M12 7.5v7M8.5 11h7"/><line x1="9" y1="18" x2="15" y2="18"/></>,
  award: <><circle cx="12" cy="9" r="6"/><polyline points="8.5 13.5 7 21 12 18 17 21 15.5 13.5"/></>,
  book: <><path d="M4 4v16a2 2 0 0 0 2 2h14V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2z"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/></>,
  paperclip: <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/>,
  send: <><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></>,
  barChart: <><line x1="4" y1="20" x2="4" y2="10"/><line x1="10" y1="20" x2="10" y2="4"/><line x1="16" y1="20" x2="16" y2="13"/><line x1="22" y1="20" x2="2" y2="20"/></>,
  pieChart: <><path d="M21.21 15.89A10 10 0 1 1 8 2.83"/><path d="M22 12A10 10 0 0 0 12 2v10z"/></>,
  lineChart: <><polyline points="3 17 8 11 12 14 21 5"/><polyline points="21 5 21 10 16 10"/><line x1="3" y1="20" x2="21" y2="20"/></>,
  trendUp: <><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></>,
  trendDown: <><polyline points="23 18 13.5 8.5 8.5 13.5 1 6"/><polyline points="17 18 23 18 23 12"/></>,
  activity: <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>,
  megaphone: <><path d="M3 11v4l12 5V6L3 11z"/><path d="M15 8v9"/><path d="M18 10a3 3 0 0 1 0 5"/></>,
  smile: <><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></>,
  user2: <><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></>,
  sparkles: <><path d="M12 3l2 6 6 2-6 2-2 6-2-6-6-2 6-2z"/></>,
  filter: <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>,
  grid: <><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></>,
  alert: <><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></>,
  lock2: <><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>,
  play: <polygon points="5 3 19 12 5 21 5 3"/>,
  pause: <><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></>,
  flash: <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>,
};

const AIcon = ({ name, size = 16, className = '', stroke = 1.75 }) => (
  <svg className={`a-icon ${className}`} width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={{flexShrink:0}}>
    {AIconPaths[name]}
  </svg>
);

// ========= Toast system =========
const ToastCtx = createContext(null);
const useToast = () => useContext(ToastCtx);

const ToastProvider = ({ children }) => {
  const [toasts, setToasts] = useState([]);
  const push = (msg, kind = 'default') => {
    const id = Math.random().toString(36).slice(2);
    setToasts(t => [...t, { id, msg, kind }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 4500);
  };
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="a-toast-stack">
        {toasts.map(t => (
          <div key={t.id} className={`a-toast ${t.kind !== 'default' ? 'a-toast-' + t.kind : ''}`}>
            {t.kind === 'success' && <AIcon name="check" size={15} />}
            {t.kind === 'danger' && <AIcon name="alert" size={15} />}
            {t.kind === 'warn' && <AIcon name="alert" size={15} />}
            <span>{t.msg}</span>
          </div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
};

// ========= Modal / Drawer =========
const AModal = ({ open, onClose, title, children, footer, size = '', icon }) => {
  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="a-modal-backdrop" onClick={(e) => { if (e.target === e.currentTarget) onClose?.(); }}>
      <div className={`a-modal ${size === 'lg' ? 'a-modal-lg' : size === 'xl' ? 'a-modal-xl' : ''}`}>
        {(title || icon) && (
          <div className="a-modal-header">
            {icon}
            <h3 className="a-modal-title">{title}</h3>
            <button className="a-icon-btn" onClick={onClose}><AIcon name="x" size={16}/></button>
          </div>
        )}
        <div className="a-modal-body">{children}</div>
        {footer && <div className="a-modal-footer">{footer}</div>}
      </div>
    </div>
  );
};

const ADrawer = ({ open, onClose, title, children, footer, size = '' }) => {
  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="a-drawer-backdrop" onClick={onClose} />
      <div className={`a-drawer ${size === 'lg' ? 'a-drawer-lg' : size === 'xl' ? 'a-drawer-xl' : ''}`}>
        {title && (
          <div className="a-drawer-header">
            <h3 className="a-modal-title">{title}</h3>
            <button className="a-icon-btn" onClick={onClose}><AIcon name="x" size={16}/></button>
          </div>
        )}
        <div className="a-drawer-body">{children}</div>
        {footer && <div className="a-drawer-footer">{footer}</div>}
      </div>
    </>
  );
};

// ========= Status → Badge helpers =========
const StatusBadge = ({ status, map }) => {
  const m = map || STATUS_MAP;
  const conf = m[status] || { label: status, kind: 'neutral' };
  return <span className={`a-badge a-badge-${conf.kind}`}>{conf.dot && <span className="a-dot"/>}{conf.label}</span>;
};

const STATUS_MAP = {
  // Candidate
  DRAFT:           { label: '草稿', kind: 'neutral' },
  PENDING_REVIEW:  { label: '待審核', kind: 'warn' },
  ACTIVE:          { label: '已上架', kind: 'success' },
  REJECTED:        { label: '已駁回', kind: 'danger' },
  SUSPENDED:       { label: '停權', kind: 'danger' },
  // Subscription
  EXPIRED:         { label: '已過期', kind: 'neutral' },
  CANCELLED:       { label: '已取消', kind: 'neutral' },
  // Assessment
  PENDING_SIGNOFF: { label: '待簽核', kind: 'warn' },
  SIGNED:          { label: '已簽核', kind: 'success' },
  // Video moderation
  PENDING:         { label: '待審核', kind: 'warn' },
  APPROVED:        { label: '已通過', kind: 'success' },
  // Article
  PUBLISHED:       { label: '已發佈', kind: 'success' },
  SCHEDULED:       { label: '已排程', kind: 'info' },
  ARCHIVED:        { label: '已封存', kind: 'neutral' },
  // Referral
  QUALIFIED:       { label: '已達標', kind: 'info' },
  HOLD:            { label: '觀察中', kind: 'warn' },
  PAYABLE:         { label: '可發放', kind: 'info' },
  PAID:            { label: '已發放', kind: 'success' },
  VOID:            { label: '作廢', kind: 'neutral' },
  // Generic
  READY:           { label: 'Ready', kind: 'success' },
  PROCESSING:      { label: 'Processing…', kind: 'info' },
  FAILED:          { label: 'Failed', kind: 'danger' },
  CLOSED:          { label: '已關閉', kind: 'neutral' },
};

// ========= Common inline bits =========
const Tier = ({ t }) => t ? <span className={`a-tier a-tier-${t}`}>{t}</span> : <span className="text-faint">—</span>;
// Verification chip — official / agency / self
const VERIFICATION_CHIP_SPEC = {
  official: { label: 'Official', cls: 'a-badge-primary' },
  agency:   { label: 'Agency',   cls: 'a-badge-success' },
  self:     { label: 'Self',     cls: 'a-badge-violet'  },
};
const VerificationChip = ({ v }) => {
  const s = VERIFICATION_CHIP_SPEC[v];
  return s ? <span className={`a-badge ${s.cls}`} style={{fontSize:10,padding:'1px 7px'}}>{s.label}</span> : null;
};
const Flag = ({ code, size = 16 }) => {
  const map = { ID: '🇮🇩', PH: '🇵🇭', VN: '🇻🇳', TH: '🇹🇭', TW: '🇹🇼', HK: '🇭🇰', SG: '🇸🇬', MY: '🇲🇾' };
  return <span style={{ fontSize: size }}>{map[code] || '🏳'}</span>;
};
const Mono = ({ children, className = '' }) => <span className={`a-mono ${className}`}>{children}</span>;

// ========= Candidate avatar (initials over hashed color) =========
const avatarColor = (seed) => {
  const colors = ['#E8856A','#48B8A0','#7A5AC2','#3D7EF0','#D4A554','#B85A6B','#5A7B47','#4A8BB0'];
  let h = 0;
  for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) & 0xffffff;
  return colors[Math.abs(h) % colors.length];
};
const Initials = (name) => name.split(/\s+/).filter(Boolean).slice(0,2).map(s=>s[0]).join('').toUpperCase();
const AAvatar = ({ name, id, size = 32, square = false }) => {
  const color = avatarColor(id || name);
  return (
    <div style={{
      width: size, height: size,
      borderRadius: square ? 6 : '50%',
      background: `linear-gradient(135deg, ${color}, ${color}cc)`,
      color: '#fff',
      display: 'grid', placeItems: 'center',
      fontWeight: 600, fontSize: size * 0.38,
      flexShrink: 0,
      letterSpacing: '-0.02em',
    }}>{Initials(name)}</div>
  );
};

// Candidate identity cell — avatar + name + sub-line
const CandidateCell = ({ c, sub, onClick }) => (
  <div className="flex items-center gap-10" style={{cursor: onClick ? 'pointer' : 'default'}} onClick={onClick}>
    <AAvatar name={c.name} id={c.id} size={34} square />
    <div style={{minWidth:0}}>
      <div className="fw-600 fs-13" style={{color:'var(--a-ink)'}}>
        {c.name}
        {c.verified && <span style={{display:'inline-flex',marginLeft:5,verticalAlign:'middle',color:'var(--a-info)'}}><AIcon name="checkCircle" size={12}/></span>}
      </div>
      <div className="text-muted fs-12 flex items-center gap-4">
        <Flag code={c.nationality} size={12}/> {sub || (c.city + ', ' + window.ADMIN.nat[c.nationality].name)}
      </div>
    </div>
  </div>
);

// Empty state
const AEmpty = ({ icon = 'search', title = '沒有資料', sub, action }) => (
  <div className="a-empty">
    <div className="a-empty-ic"><AIcon name={icon} size={20}/></div>
    <div className="a-empty-title">{title}</div>
    {sub && <div className="a-empty-sub">{sub}</div>}
    {action && <div style={{marginTop:14}}>{action}</div>}
  </div>
);

// ========= Export =========
// Audit log helper — adds an entry to ADMIN.auditLogs
const pushLog = (action, targetType, targetId, diff) => {
  const actor = (JSON.parse(localStorage.getItem('hm_admin_user') || 'null') || {}).name || 'Unknown';
  const entry = {
    id: 'log_' + Math.random().toString(36).slice(2, 10),
    at: new Date(),
    actor, action, targetType, targetId, diff: diff || null,
  };
  ADMIN.auditLogs.unshift(entry);
  return entry;
};

Object.assign(window, {
  AIcon, AModal, ADrawer, StatusBadge, STATUS_MAP, Tier, VerificationChip, Flag, Mono, AAvatar, CandidateCell, AEmpty,
  ToastProvider, useToast, Initials, avatarColor,
  pushLog,
});
