// Shared UI primitives used by every portal.

const StatusBadge = ({ status }) => {
  const m = STATUS_META[status] || { label: status, icon: "clock", tone: "offen" };
  return (
    <span className={`badge-pill ${m.tone}`}>
      <Icon name={m.icon} size={11} />
      {m.label}
    </span>
  );
};

const TypBadge = ({ typ }) => {
  const m = TYP_META[typ] || { label: typ, icon: "pill" };
  return (
    <span className="badge-pill">
      <Icon name={m.icon} size={11} /> {m.label}
    </span>
  );
};

const Prio = ({ level }) => (
  <span className={`prio ${level}`} title={level === "H" ? "Hoch" : level === "M" ? "Mittel" : "Normal"}>
    {level}
  </span>
);

const Avatar = ({ name, size = 22, hue }) => {
  const initials = (name || "?").split(/[\s,]+/).filter(Boolean).slice(0, 2).map(s => s[0]?.toUpperCase()).join("");
  const h = hue ?? (name ? (name.charCodeAt(0) * 13) % 360 : 220);
  return (
    <span
      className="avatar-sm"
      style={{
        width: size, height: size, fontSize: size * 0.42,
        background: `oklch(92% 0.03 ${h})`, color: `oklch(35% 0.08 ${h})`,
        borderColor: `oklch(85% 0.04 ${h})`,
      }}
    >
      {initials}
    </span>
  );
};

const Sparkline = ({ points = [], color = "var(--accent)" }) => {
  if (!points.length) return null;
  const max = Math.max(...points), min = Math.min(...points);
  const w = 80, h = 22;
  const d = points.map((p, i) => {
    const x = (i / (points.length - 1)) * w;
    const y = h - ((p - min) / (max - min || 1)) * h;
    return `${i === 0 ? "M" : "L"}${x.toFixed(1)} ${y.toFixed(1)}`;
  }).join(" ");
  return (
    <svg className="spark" width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      <path d={d} fill="none" stroke={color} strokeWidth="1.4" />
    </svg>
  );
};

const Kpi = ({ label, value, icon, trend, points }) => {
  const AN = window.AnimatedNumber;
  return (
    <div className="kpi">
      <div className="label"><Icon name={icon} size={13} /> {label}</div>
      <div className="value">{AN ? <AN value={value} /> : value}</div>
      <div className="trend">
        <span>{trend}</span>
        <Sparkline points={points} />
      </div>
    </div>
  );
};

// Topbar pieces
const Topbar = ({
  brand = "MedLink", portal, portalIcon, onBrand,
  crumbs = [], onSearchClick,
  userName, userRole, userEmail, onToggleSidebar,
  onLogout, onAdmin,
  heim,
  showHeimTabs = true,
}) => {
  const [userMenu, setUserMenu] = React.useState(false);
  React.useEffect(() => {
    if (!userMenu) return;
    const h = () => setUserMenu(false);
    const t = setTimeout(() => document.addEventListener("click", h), 0);
    return () => { clearTimeout(t); document.removeEventListener("click", h); };
  }, [userMenu]);
  return (
    <div className="topbar">
      <div className="brand" onClick={onBrand} style={{cursor: onBrand ? "pointer" : "default"}}>
        <span className="brand-mark"><Icon name="heart" size={13} /></span>
        <span>{brand}</span>
      </div>
      <div className="sep" />
      <button className="tb-item" onClick={onToggleSidebar} title="Rolle wechseln">
        <Icon name={portalIcon || "grid"} size={13} /> {portal}
        <Icon name="chevronDown" size={10} />
      </button>
      <div className="crumb">
        <span className="slash">/</span>
        {crumbs.map((c, i) => (
          <React.Fragment key={i}>
            <span className={i === crumbs.length - 1 ? "leaf" : ""}>{c}</span>
            {i < crumbs.length - 1 && <span className="slash">/</span>}
          </React.Fragment>
        ))}
      </div>
      {showHeimTabs && heim !== undefined && window.HeimTabs && (
        <>
          <div className="sep" />
          <HeimTabs variant="desktop" currentHeim={heim} />
        </>
      )}
      <div className="spacer" />
      <div className="search" onClick={onSearchClick} role="button" tabIndex={0}>
        <Icon name="search" size={12} /> Suche, Sprung, Aktion…
        <kbd>⌘K</kbd>
      </div>
      <button className="tb-item icon notif-anchor" title="Benachrichtigungen" onClick={(e) => { e.stopPropagation(); window.dispatchEvent(new CustomEvent("medlink:bell")); }}><Icon name="bell" size={14} /></button>
      <div className="sep" />
      <div style={{position: "relative"}}>
        <button
          className="tb-item"
          style={{paddingLeft: 4, paddingRight: 6, height: 32, gap: 8}}
          onClick={(e) => { e.stopPropagation(); setUserMenu(v => !v); }}
          title="Konto"
        >
          <Avatar name={userName} size={26} />
          <div style={{display: "flex", flexDirection: "column", lineHeight: 1.1, alignItems: "flex-start"}}>
            <span style={{fontSize: 12, fontWeight: 500, color: "var(--fg)"}}>{userName}</span>
            <span style={{fontSize: 10.5, color: "var(--fg-subtle)"}}>{userRole}</span>
          </div>
          <Icon name="chevronDown" size={11} style={{color: "var(--fg-subtle)"}} />
        </button>
        {userMenu && (
          <div className="menu" style={{top: 38, right: 0, minWidth: 240}} onClick={(e) => e.stopPropagation()}>
            <div className="menu-head">Angemeldet</div>
            <div style={{padding: "8px 12px", display: "flex", gap: 10, alignItems: "center", borderBottom: "1px solid var(--border)"}}>
              <Avatar name={userName} size={32} />
              <div style={{minWidth: 0}}>
                <div style={{fontSize: 12, fontWeight: 500}}>{userName}</div>
                <div style={{fontSize: 11, color: "var(--fg-subtle)"}}>{userEmail || userRole}</div>
              </div>
            </div>
            <div className="menu-item"><Icon name="user" size={14} />Profil & Einstellungen</div>
            <div className="menu-item"><Icon name="shield" size={14} />Sicherheit · 2FA</div>
            <div className="menu-item"><Icon name="bell" size={14} />Benachrichtigungen</div>
            {onAdmin && <><div className="menu-sep" /><div className="menu-item" onClick={() => { setUserMenu(false); onAdmin(); }}><Icon name="shield" size={14} />Admin-Konsole</div></>}
            <div className="menu-sep" />
            <div className="menu-item" style={{color: "var(--danger)"}} onClick={() => { setUserMenu(false); onLogout?.(); }}>
              <Icon name="back" size={14} />Abmelden
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

const Sidebar = ({
  scopeMark, scopeTitle, scopeSub, onScopeClick,
  sections, active, onNav, compliance,
}) => (
  <aside className="sidebar">
    <div className="scope">
      <button className="scope-chip" onClick={onScopeClick}>
        <span className="mark">{scopeMark}</span>
        <span className="meta">
          {scopeTitle}
          <span className="sub">{scopeSub}</span>
        </span>
        <Icon name="chevronUpDown" size={12} className="caret" />
      </button>
    </div>
    <nav>
      {sections.map((sec, si) => (
        <div className="nav-section" key={si}>
          {sec.label && <div className="nav-label">{sec.label}</div>}
          {sec.items.map(it => (
            <a
              key={it.id}
              className={`nav-item ${active === it.id ? "active" : ""}`}
              onClick={(e) => { e.preventDefault(); onNav(it.id); }}
              href="#"
            >
              <Icon name={it.icon} size={14} />
              <span className="label">{it.label}</span>
              {it.badge != null && <span className="badge">{it.badge}</span>}
            </a>
          ))}
        </div>
      ))}
    </nav>
    <div className="sb-footer">
      <span className="dot-live" />
      <span className="label">{compliance || "DSGVO · EU · 2FA aktiv"}</span>
    </div>
  </aside>
);

const Tabs = ({ items, active, onChange }) => (
  <div className="tabs">
    {items.map(t => (
      <button
        key={t.id}
        className={`tab ${active === t.id ? "active" : ""}`}
        onClick={() => onChange(t.id)}
      >
        {t.icon && <Icon name={t.icon} size={13} />}
        {t.label}
        {t.count != null && <span className="count num">{t.count}</span>}
      </button>
    ))}
  </div>
);

const Toolbar = ({ children }) => <div className="toolbar">{children}</div>;

// Sensible fallback reactions for common button labels so no click is "dead".
const BTN_FALLBACKS = {
  "Filter": "Filter angewendet · 3 aktiv",
  "Export": "Export gestartet · CSV wird geladen",
  "Export (CSV)": "CSV-Export gestartet · Download bereit",
  "Drucken": "Druckdialog geöffnet",
  "PDF": "PDF wird erstellt · Öffnet in Kürze",
  "Etiketten": "Etiketten-Druck gestartet · 14 Labels",
  "Plan drucken": "Tagesplan als PDF · Download bereit",
  "Tagesplan": "Tagesplan als PDF · Download bereit",
  "Schicht-Übergabe": "Schicht-Übergabe gestartet · Entwurf bereit",
  "Visite planen": "Visite-Planer geöffnet",
  "Tourenplan": "Tourenplan neu berechnet",
  "Tour planen": "Touren-Assistent geöffnet",
  "Station öffnen": "Station-Detail geöffnet",
  "Bewohner anlegen": "Bewohner-Assistent geöffnet · 4 Schritte",
  "Benutzer einladen": "Einladungs-E-Mail wird vorbereitet",
  "Mandant anlegen": "Onboarding-Assistent gestartet",
  "Neuen Mandanten anlegen": "Onboarding-Assistent gestartet",
  "Arzt einladen": "Arzt-Einladung gesendet · KIM-ID verknüpft",
  "Apotheke anbinden": "Apotheken-Onboarding gestartet",
  "Einladen": "Einladung gesendet",
  "Einladung senden": "Einladung gesendet",
  "Monatsbericht": "Monatsbericht April 2026 · PDF bereit",
  "Anpassen": "Anpassungs-Dialog geöffnet",
  "Rückfrage": "Rückfrage an Pflege gesendet",
  "Detail": "Detail-Panel geöffnet",
  "Öffnen": "Detail geöffnet",
  "Bearbeiten": "Bearbeiten-Modus aktiv",
  "Kopieren": "In Zwischenablage kopiert",
  "Erinnern": "Erinnerung für 15:00 gesetzt",
  "Gelesen": "Als gelesen markiert",
  "Folge": "Folge-Rezept vorbereitet",
  "Plan": "Medikationsplan geöffnet",
  "F": "Freigegeben",
  "Neue Empfehlung": "Empfehlungs-Editor geöffnet",
  "Alle": "Filter: Alle Mandanten aktiv",
};

const guessReaction = (label, icon) => {
  if (BTN_FALLBACKS[label]) return BTN_FALLBACKS[label];
  if (typeof label === "string") {
    if (/^Export\b/i.test(label)) return `${label} gestartet`;
    if (/Drucken|Druck$/i.test(label)) return "Druckdialog geöffnet";
    if (/^Filter/i.test(label)) return "Filter angewendet";
    if (/neu|anlegen|einladen/i.test(label)) return `${label} · Assistent gestartet`;
  }
  if (icon === "printer") return "Druckdialog geöffnet";
  if (icon === "filter") return "Filter angewendet";
  if (icon === "plus") return label ? `${label} gestartet` : "Neues Element";
  if (icon === "eye") return "Detail geöffnet";
  if (icon === "edit") return "Bearbeiten-Modus aktiv";
  if (icon === "trash") return "Element entfernt";
  return label ? `${label} — Demo` : "Aktion ausgeführt";
};

const Btn = ({ variant, icon, kbd, sm, children, onClick, ...rest }) => {
  const label = typeof children === "string" ? children
    : Array.isArray(children) ? children.filter(c => typeof c === "string").join(" ").trim() || ""
    : "";
  const handler = onClick || ((e) => {
    e.stopPropagation();
    window.dispatchEvent(new CustomEvent("medlink:toast", { detail: guessReaction(label, icon) }));
  });
  const cls = `btn ${variant || ""}${sm ? " sm" : ""}`.trim();
  return (
    <button className={cls} onClick={handler} {...rest}>
      {icon && <Icon name={icon} size={13} />}
      {children}
      {kbd && <span className="kbd">{kbd}</span>}
    </button>
  );
};

const CheckBox = ({ checked, onChange }) => (
  <span
    className={`check-box ${checked ? "checked" : ""}`}
    onClick={(e) => { e.stopPropagation(); onChange?.(!checked); }}
  >
    {checked && <Icon name="check" size={10} />}
  </span>
);

// Menu (click-outside)
const Menu = ({ anchorRef, open, onClose, children, style }) => {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => {
      if (ref.current?.contains(e.target)) return;
      if (anchorRef?.current?.contains(e.target)) return;
      onClose?.();
    };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);
  if (!open) return null;
  return (
    <div ref={ref} className="menu" style={style}>
      {children}
    </div>
  );
};

Object.assign(window, { StatusBadge, TypBadge, Prio, Avatar, Sparkline, Kpi, Topbar, Sidebar, Tabs, Toolbar, Btn, CheckBox, Menu });
