// Shared atoms + helpers used across views and drawers
const { useState, useMemo, useEffect, useRef, useLayoutEffect } = React;

function Dot({ color }) {
  return <span style={{ display: "inline-block", width: 6, height: 6, borderRadius: 99, background: color, flexShrink: 0 }} />;
}

function Pill({ children, tone = "default" }) {
  const tones = {
    default: { bg: "var(--c-surface-2)", fg: "var(--c-fg-soft)", bd: "var(--c-border)" },
    accent:  { bg: "color-mix(in oklab, var(--c-accent) 14%, transparent)", fg: "var(--c-accent)", bd: "color-mix(in oklab, var(--c-accent) 28%, transparent)" },
    success: { bg: "color-mix(in oklab, var(--c-green) 14%, transparent)", fg: "var(--c-green)", bd: "color-mix(in oklab, var(--c-green) 28%, transparent)" },
    warn:    { bg: "color-mix(in oklab, var(--c-amber) 14%, transparent)", fg: "var(--c-amber)", bd: "color-mix(in oklab, var(--c-amber) 28%, transparent)" },
    danger:  { bg: "color-mix(in oklab, var(--c-red) 14%, transparent)", fg: "var(--c-red)", bd: "color-mix(in oklab, var(--c-red) 28%, transparent)" },
  };
  const t = tones[tone];
  return <span style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "2px 8px", borderRadius: 6, background: t.bg, color: t.fg, border: `1px solid ${t.bd}`, fontSize: 11, fontWeight: 500, lineHeight: 1.4, whiteSpace: "nowrap" }}>{children}</span>;
}

function IconBtn({ children, onClick, title, danger }) {
  return <button onClick={onClick} title={title} className="icon-btn" data-danger={danger ? "1" : undefined}>{children}</button>;
}

function Button({ children, onClick, variant = "primary", type = "button", disabled, full }) {
  return <button type={type} onClick={onClick} disabled={disabled} className={`btn btn-${variant}`} style={full ? { width: "100%" } : {}}>{children}</button>;
}

function Field({ label, children, full, hint }) {
  return (
    <label className="field" data-full={full ? "1" : undefined}>
      <span className="field-label">{label}</span>
      {children}
      {hint && <span className="field-hint">{hint}</span>}
    </label>
  );
}

function EmptyState({ icon, title, hint }) {
  return (
    <div className="empty">
      <div className="empty-icon">{icon}</div>
      <div className="empty-title">{title}</div>
      {hint && <div className="empty-hint">{hint}</div>}
    </div>
  );
}

function Panel({ title, right, children, className }) {
  return (
    <section className={`panel${className ? " " + className : ""}`}>
      <header className="panel-head">
        <h2>{title}</h2>
        {right}
      </header>
      <div className="panel-body">{children}</div>
    </section>
  );
}

// Inline minimal icon set (24x24 grid, stroke-based)
const Icon = ({ name, size = 16 }) => {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    dashboard: <><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></>,
    today:     <><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/><circle cx="12" cy="15" r="1.2" fill="currentColor"/></>,
    week:      <><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4M8 14h2M12 14h2M16 14h2M8 18h2M12 18h2"/></>,
    month:     <><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/></>,
    plus:      <><path d="M12 5v14M5 12h14"/></>,
    people:    <><circle cx="9" cy="8" r="3.2"/><path d="M3 20c.6-3.4 3.2-5.5 6-5.5s5.4 2.1 6 5.5"/><circle cx="17" cy="9" r="2.4"/><path d="M21 18c-.4-2.2-2-3.6-4-3.6"/></>,
    kanban:    <><rect x="3" y="4" width="5" height="16" rx="1"/><rect x="10" y="4" width="5" height="10" rx="1"/><rect x="17" y="4" width="4" height="13" rx="1"/></>,
    bell:      <><path d="M6 9a6 6 0 1 1 12 0c0 4 1.5 5.5 2 6H4c.5-.5 2-2 2-6Z"/><path d="M10 19a2 2 0 0 0 4 0"/></>,
    note:      <><path d="M5 4h11l3 3v13H5z"/><path d="M16 4v3h3M8 12h8M8 16h5"/></>,
    search:    <><circle cx="11" cy="11" r="6"/><path d="m20 20-4.5-4.5"/></>,
    moon:      <><path d="M20 13.5A8 8 0 1 1 10.5 4a6.5 6.5 0 0 0 9.5 9.5Z"/></>,
    sun:       <><circle cx="12" cy="12" r="3.5"/><path d="M12 2v2M12 20v2M4 12H2M22 12h-2M5 5l1.4 1.4M17.6 17.6 19 19M5 19l1.4-1.4M17.6 6.4 19 5"/></>,
    download:  <><path d="M12 4v11m0 0 4-4m-4 4-4-4M4 20h16"/></>,
    upload:    <><path d="M12 20V9m0 0 4 4m-4-4-4 4M4 4h16"/></>,
    reset:     <><path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5"/></>,
    check:     <><path d="m5 12 5 5L20 7"/></>,
    x:         <><path d="M6 6l12 12M18 6 6 18"/></>,
    clock:     <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>,
    video:     <><rect x="3" y="6" width="13" height="12" rx="2"/><path d="m16 10 5-3v10l-5-3z"/></>,
    pin:       <><path d="M12 21v-7"/><path d="M9 4h6l-1 6 3 3H7l3-3-1-6Z"/></>,
    edit:      <><path d="M4 20h4l10-10-4-4L4 16Z"/><path d="m14 6 4 4"/></>,
    trash:     <><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/></>,
    arrow:     <><path d="M5 12h14m-5-5 5 5-5 5"/></>,
    chevL:     <><path d="m14 6-6 6 6 6"/></>,
    chevR:     <><path d="m10 6 6 6-6 6"/></>,
    money:     <><path d="M12 3v18"/><path d="M17 7H10a2.5 2.5 0 0 0 0 5h4a2.5 2.5 0 0 1 0 5H7"/></>,
    whatsapp:  <><path d="M3 21l1.6-5A8 8 0 1 1 8 19.4L3 21Z"/><path d="M9 9c.4 2.5 2.5 4.6 5 5l1.5-1.5 2.5 1v2c-3.8.6-7.6-3.2-7-7l2-1 1 2.5L9 9.7Z" strokeLinejoin="round"/></>,
    grip:      <><circle cx="9" cy="6" r="1" fill="currentColor"/><circle cx="9" cy="12" r="1" fill="currentColor"/><circle cx="9" cy="18" r="1" fill="currentColor"/><circle cx="15" cy="6" r="1" fill="currentColor"/><circle cx="15" cy="12" r="1" fill="currentColor"/><circle cx="15" cy="18" r="1" fill="currentColor"/></>,
    repeat:    <><path d="M17 2v4h-4"/><path d="M17 6a8 8 0 0 0-14 4"/><path d="M7 22v-4h4"/><path d="M7 18a8 8 0 0 0 14-4"/></>,
    history:   <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/><path d="M3 8 6 5"/></>,
    palette:   <><path d="M12 3a9 9 0 1 0 0 18c2 0 1-3 2-3h2a4 4 0 0 0 0-8h-1a8 8 0 0 1-3-7Z"/><circle cx="7.5" cy="10.5" r="1" fill="currentColor"/><circle cx="11.5" cy="6.5" r="1" fill="currentColor"/><circle cx="16.5" cy="9.5" r="1" fill="currentColor"/></>,
    copy:      <><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M4 16V6a2 2 0 0 1 2-2h10"/></>,
    funnel:    <><path d="M3 4h18l-7 9v6l-4 2v-8L3 4Z"/></>,
    chart:     <><path d="M3 20h18"/><path d="M6 20V10M11 20V4M16 20v-7M21 20v-3"/></>,
    settings:  <><circle cx="12" cy="12" r="3"/><path d="M19 12a7 7 0 0 0-.1-1.2l2-1.5-2-3.5-2.4.8a7 7 0 0 0-2-1.2L14 3h-4l-.5 2.4a7 7 0 0 0-2 1.2l-2.4-.8-2 3.5 2 1.5A7 7 0 0 0 5 12c0 .4 0 .8.1 1.2l-2 1.5 2 3.5 2.4-.8a7 7 0 0 0 2 1.2L10 21h4l.5-2.4a7 7 0 0 0 2-1.2l2.4.8 2-3.5-2-1.5c.1-.4.1-.8.1-1.2Z"/></>,
  };
  return <svg {...p}>{paths[name] || null}</svg>;
};

// --- Helpers ----------------------------------------------------------------
function formatBRL(n) {
  return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL", minimumFractionDigits: 0 }).format(n || 0);
}

function matches(a, people, q) {
  q = q.toLowerCase();
  const person = people.find(p => p.id === a.personId);
  return [a.title, a.notes, a.location, a.type, person?.name].filter(Boolean).some(s => s.toLowerCase().includes(q));
}

function statusTone(s) {
  return s === "confirmado" ? "success" : s === "cancelado" ? "danger" : s === "reagendar" ? "warn" : "default";
}

// Debounced effect helper for auto-save
function useDebouncedEffect(fn, deps, delay = 600) {
  useEffect(() => {
    const t = setTimeout(fn, delay);
    return () => clearTimeout(t);
  }, deps);
}

// Shared ApptRow used in many views
function ApptRow({ a, people, compact, onOpen }) {
  const person = people.find(p => p.id === a.personId);
  const status = STATUS_META[a.status] || STATUS_META.agendado;
  const type = TYPE_META[a.type];
  const isMeet = (a.location || "").includes("meet.google.com");
  const hasNotes = !!(a.notes && a.notes.trim());
  return (
    <div className="appt-row clickable" onClick={() => onOpen && onOpen(a)} role={onOpen ? "button" : undefined} tabIndex={onOpen ? 0 : undefined}>
      <div className="appt-time">
        <div className="appt-date">{new Date(a.date + "T00:00:00").toLocaleDateString("pt-BR", { weekday: "short", day: "2-digit", month: "short" })}</div>
        <div className="appt-hour">{a.time}<span className="dim"> · {a.duration}min</span></div>
      </div>
      <span className="appt-type-bar" style={{ background: type?.hue || "var(--c-fg-soft)" }} />
      <div className="appt-body">
        <div className="appt-title">{a.title}</div>
        <div className="appt-meta">
          {person ? <span>{person.name}</span> : <span className="dim">— sem pessoa —</span>}
          <span className="dim">·</span>
          <span className="dim">{a.type}</span>
          {a.location && (<><span className="dim">·</span><span className="dim ellipsis">{isMeet ? "Google Meet" : a.location}</span></>)}
        </div>
      </div>
      <div className="appt-side">
        {hasNotes && <span className="note-mark" title="Possui anotações"><Icon name="note" size={12} /></span>}
        <Pill tone={statusTone(a.status)}>
          <Dot color={status.dot} />{status.label}
        </Pill>
      </div>
    </div>
  );
}

Object.assign(window, {
  Dot, Pill, IconBtn, Button, Field, EmptyState, Panel, Icon, ApptRow,
  formatBRL, matches, statusTone, useDebouncedEffect,
});
