// Shared primitives for Dashy

const USERS = [
  { id: 'lani',  name: 'Lani',  role: 'Front of house',  hue: 28,  initials: 'LA' },
  { id: 'kirra', name: 'Kirra', role: 'Workshop lead',   hue: 145, initials: 'KI' },
  { id: 'ayron', name: 'Ayron', role: 'Tech',            hue: 215, initials: 'AY' },
  { id: 'rod',   name: 'ROD',   role: 'Owner',           hue: 280, initials: 'RO' },
];

const PRIORITY = {
  high: { label: 'High', color: 'var(--prio-high)', dot: 'var(--prio-high)' },
  med:  { label: 'Med',  color: 'var(--prio-med)',  dot: 'var(--prio-med)'  },
  low:  { label: 'Low',  color: 'var(--prio-low)',  dot: 'var(--prio-low)'  },
};

const SOURCES = {
  manual:    { label: 'Manual',    glyph: '·' },
  imessage:  { label: 'iMessage',  glyph: '✦' },
  email:     { label: 'Email',     glyph: '✉' },
  automation:{ label: 'Auto',      glyph: '⚙' },
};

function Avatar({ user, size = 28, ring = false }) {
  if (!user) return null;
  const s = { width: size, height: size, fontSize: Math.round(size * 0.42) };
  if (user.photo) {
    return (
      <span
        className={"avatar avatar--photo" + (ring ? " avatar--ring" : "")}
        style={{
          ...s,
          backgroundImage: `url(${user.photo})`,
          boxShadow: ring ? `0 0 0 2px var(--bg), 0 0 0 3px oklch(70% 0.10 ${user.hue})` : undefined,
        }}
        title={user.name}
      />
    );
  }
  return (
    <span
      className={"avatar" + (ring ? " avatar--ring" : "")}
      style={{
        ...s,
        background: `oklch(94% 0.04 ${user.hue})`,
        color: `oklch(32% 0.10 ${user.hue})`,
        boxShadow: ring ? `0 0 0 2px var(--bg), 0 0 0 3px oklch(70% 0.10 ${user.hue})` : undefined,
      }}
      title={user.name}
    >
      {user.initials}
    </span>
  );
}

function PriorityDot({ priority, withLabel = false }) {
  const p = PRIORITY[priority];
  if (!p) return null;
  return (
    <span className="prio">
      <span className="prio__dot" style={{ background: p.dot }} />
      {withLabel && <span className="prio__label">{p.label}</span>}
    </span>
  );
}

function SourceTag({ source }) {
  const s = SOURCES[source];
  if (!s || source === 'manual') return null;
  return (
    <span className="source-tag" data-source={source}>
      <span className="source-tag__glyph">{s.glyph}</span>
      {s.label}
    </span>
  );
}

function relTime(iso) {
  const now = new Date('2026-05-08T10:30:00');
  const then = new Date(iso);
  const diff = (now - then) / 1000;
  if (diff < 60) return 'just now';
  if (diff < 3600) return Math.floor(diff/60) + 'm ago';
  if (diff < 86400) return Math.floor(diff/3600) + 'h ago';
  if (diff < 86400*7) return Math.floor(diff/86400) + 'd ago';
  return then.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
}

function fmtDateTime(iso) {
  const d = new Date(iso);
  return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) +
         ' · ' + d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
}

function findUser(id) { 
  const live = window.dbUsers;
  if (live) return live.find(u => u.id === id);
  return USERS.find(u => u.id === id); 
}

function TaskCard({ task, onOpen, density = 'cozy', dragging = false, onDragStart, onDragEnd, onDragOver }) {
  const author = findUser(task.addedBy);
  const isAuto = task.status === 'unsuccessful' || task.status === 'billing';
  return (
    <article
      className={"card" + (dragging ? " card--drag" : "") + (isAuto ? " card--flagged" : "")}
      style={dragging ? { opacity: 0, pointerEvents: 'none' } : {}}
      data-density={density}
      data-priority={task.priority}
      draggable
      onDragStart={(e) => {
        e.dataTransfer.effectAllowed = 'move';
        e.dataTransfer.setData('text/dashy-task', task.id);
        onDragStart && onDragStart(task);
      }}
      onDragEnd={() => onDragEnd && onDragEnd()}
      onDragOver={onDragOver}
      onClick={() => onOpen && onOpen(task)}
      data-comment-anchor={"task-" + task.id}
    >
      <span className="card__grip" aria-hidden="true">
        <span /><span /><span /><span /><span /><span />
      </span>
      <header className="card__head">
        <h3 className="card__title">{task.title}</h3>
        <PriorityDot priority={task.priority} />
      </header>
      {task.description && (
        <p className="card__desc">{task.description}</p>
      )}
      {task.tags && task.tags.length > 0 && (
        <div className="card__tags">
          {task.tags.map(t => <span key={t} className="chip">{t}</span>)}
          {task.source && task.source !== 'manual' && <SourceTag source={task.source} />}
        </div>
      )}
      {isAuto && (
        <div className="card__alert">
          {task.status === 'unsuccessful'
            ? 'Auto-marked unsuccessful — needs review'
            : 'Switched to billing form'}
        </div>
      )}
      <footer className="card__foot">
        <span className="card__author">
          <Avatar user={author} size={20} />
          <span>{author && author.name}</span>
        </span>
        <span className="card__time">{relTime(task.addedAt)}</span>
      </footer>
    </article>
  );
}

function IconBtn({ children, onClick, label, variant = 'ghost' }) {
  return (
    <button className={"icon-btn icon-btn--" + variant} onClick={onClick} aria-label={label} title={label}>
      {children}
    </button>
  );
}

// Tiny inline icons
const Icon = {
  Plus: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M8 3v10M3 8h10" strokeLinecap="round"/></svg>,
  Bell: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M4 7a4 4 0 1 1 8 0v3l1 2H3l1-2V7Z" strokeLinejoin="round"/><path d="M6.5 13a1.5 1.5 0 0 0 3 0"/></svg>,
  Search: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><circle cx="7" cy="7" r="4.5"/><path d="m10.5 10.5 3 3" strokeLinecap="round"/></svg>,
  Logs: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M3 4h10M3 8h10M3 12h6" strokeLinecap="round"/></svg>,
  Close: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M4 4l8 8M12 4l-8 8" strokeLinecap="round"/></svg>,
  Check: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="m3.5 8.5 3 3 6-7" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  Arrow: () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M3 8h10m-4-4 4 4-4 4" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  Dot:  () => <svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="2.5" fill="currentColor"/></svg>,
  Pin:  () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M10 2 6 6H3l4 4-3 4 4-3 4 4v-3l4-4-2-2-2-4Z" strokeLinejoin="round"/></svg>,
  iMessage: () => <svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M2.5 7.5c0-2.8 2.5-5 5.5-5s5.5 2.2 5.5 5-2.5 5-5.5 5c-.6 0-1.2-.1-1.7-.2L3 13.5l.7-2.5c-.7-.9-1.2-1.9-1.2-3Z" strokeLinejoin="round"/></svg>,
};

Object.assign(window, {
  USERS, PRIORITY, SOURCES,
  Avatar, PriorityDot, SourceTag, TaskCard, IconBtn, Icon,
  relTime, fmtDateTime, findUser,
});
