// portal-shared.jsx — desktop UI atoms for the Snap Operation portal.
// Inherits the iPad app's ink-first palette but tuned for desktop density.

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ------------------------------------------------------------------
// Icons — Remix Icon webfont (https://remixicon.com).
// We accept legacy short names so we don't have to rewrite every callsite,
// and pass-through any explicit "ri-..." class.
// ------------------------------------------------------------------
const P_ICON_MAP = {
  home:      'ri-home-5-line',
  clipboard: 'ri-clipboard-line',
  megaphone: 'ri-megaphone-line',
  broom:     'ri-brush-line',
  box:       'ri-archive-2-line',
  truck:     'ri-truck-line',
  users:     'ri-team-line',
  history:   'ri-history-line',
  book:      'ri-book-open-line',
  settings:  'ri-settings-3-line',
  plus:      'ri-add-line',
  minus:     'ri-subtract-line',
  x:         'ri-close-line',
  check:     'ri-check-line',
  chevronL:  'ri-arrow-left-s-line',
  chevronR:  'ri-arrow-right-s-line',
  chevronD:  'ri-arrow-down-s-line',
  chevronU:  'ri-arrow-up-s-line',
  search:    'ri-search-line',
  filter:    'ri-filter-3-line',
  edit:      'ri-pencil-line',
  trash:     'ri-delete-bin-line',
  copy:      'ri-file-copy-line',
  save:      'ri-save-line',
  moreH:     'ri-more-fill',
  grip:      'ri-drag-move-2-line',
  calendar:  'ri-calendar-line',
  clock:     'ri-time-line',
  bell:      'ri-notification-3-line',
  arrowR:    'ri-arrow-right-line',
  eye:       'ri-eye-line',
  lock:      'ri-lock-2-line',
  star:      'ri-star-line',
  sparkle:   'ri-sparkling-2-line',
  download:  'ri-download-line',
  print:     'ri-printer-line',
  flame:     'ri-fire-line',
  leaf:      'ri-leaf-line',
  droplet:   'ri-drop-line',
  grid:      'ri-layout-grid-line',
  list:      'ri-list-check',
  archive:   'ri-archive-line',
  info:      'ri-information-line',
  msg:       'ri-message-3-line',
  tablet:    'ri-tablet-line',
  refresh:   'ri-refresh-line',
};

const PIcon = ({ name, size = 16, color = 'currentColor', style }) => {
  const cls = name && name.startsWith('ri-') ? name : (P_ICON_MAP[name] || 'ri-question-line');
  return (
    <i
      className={cls}
      style={{
        fontSize: size,
        lineHeight: 1,
        color,
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        width: size,
        height: size,
        verticalAlign: 'middle',
        ...style,
      }}
    />
  );
};

// ------------------------------------------------------------------
// Avatar (compact desktop variant)
// ------------------------------------------------------------------
const PAvatar = ({ staff, size = 24, ring = false, style }) => {
  if (!staff) return null;
  return (
    <div style={{
      width: size, height: size, borderRadius: 999,
      background: staff.color, color: '#fff',
      fontWeight: 500, fontSize: size * 0.42,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      flexShrink: 0,
      letterSpacing: '0.01em',
      boxShadow: ring ? '0 0 0 2px #fff' : 'none',
      ...style,
    }}>{staff.initials}</div>
  );
};

const PAvatarStack = ({ ids = [], size = 22, max = 4 }) => {
  const staff = ids.map(id => window.SAMPLE_STAFF.find(s => s.id === id)).filter(Boolean);
  const shown = staff.slice(0, max);
  const extra = staff.length - max;
  return (
    <div style={{ display: 'inline-flex' }}>
      {shown.map((s, i) => (
        <div key={s.id} style={{ marginLeft: i === 0 ? 0 : -size * 0.32 }}>
          <PAvatar staff={s} size={size} style={{ boxShadow: '0 0 0 1.5px #fff' }} />
        </div>
      ))}
      {extra > 0 && (
        <div style={{
          width: size, height: size, borderRadius: 999,
          background: '#E5E5EA', color: '#6E6E73',
          fontWeight: 500, fontSize: size * 0.4,
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          marginLeft: -size * 0.32,
          boxShadow: '0 0 0 1.5px #fff',
        }}>+{extra}</div>
      )}
    </div>
  );
};

// ------------------------------------------------------------------
// Button
// ------------------------------------------------------------------
const PBtn = ({ variant = 'secondary', size = 'md', icon, trailing, children, onClick, disabled, style, fullWidth, title }) => {
  const sizes = {
    xs: { height: 26, padding: '0 9px',  fs: 12,   gap: 5, radius: 6,  iconSz: 13 },
    sm: { height: 30, padding: '0 11px', fs: 12.5, gap: 6, radius: 7,  iconSz: 14 },
    md: { height: 34, padding: '0 14px', fs: 13,   gap: 7, radius: 8,  iconSz: 15 },
    lg: { height: 40, padding: '0 18px', fs: 14,   gap: 8, radius: 9,  iconSz: 16 },
  }[size];
  const variants = {
    primary:   { bg: 'var(--fg-1)',      fg: '#FFFFFF',      border: 'transparent' },
    secondary: { bg: 'var(--bg-surface)', fg: 'var(--fg-1)', border: 'var(--border-1)' },
    ghost:     { bg: 'transparent',       fg: 'var(--fg-1)', border: 'transparent' },
    tint:      { bg: 'var(--bg-sunken)',  fg: 'var(--fg-1)', border: 'transparent' },
    danger:    { bg: 'var(--bg-surface)', fg: 'var(--danger)', border: 'var(--border-1)' },
  }[variant];
  return (
    <button onClick={onClick} disabled={disabled} title={title} style={{
      height: sizes.height, padding: icon && !children ? 0 : sizes.padding,
      width: icon && !children ? sizes.height : (fullWidth ? '100%' : undefined),
      background: variants.bg, color: variants.fg,
      borderRadius: sizes.radius, border: `1px solid ${variants.border}`,
      fontSize: sizes.fs, fontWeight: 500, letterSpacing: '-0.005em',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: sizes.gap,
      whiteSpace: 'nowrap',
      opacity: disabled ? 0.45 : 1,
      transition: 'background 120ms, transform 80ms',
      ...style,
    }}
    onMouseDown={e => !disabled && (e.currentTarget.style.transform = 'translateY(0.5px)')}
    onMouseUp={e => (e.currentTarget.style.transform = '')}
    onMouseLeave={e => (e.currentTarget.style.transform = '')}>
      {icon && <PIcon name={icon} size={sizes.iconSz} />}
      {children}
      {trailing && <PIcon name={trailing} size={sizes.iconSz} />}
    </button>
  );
};

// ------------------------------------------------------------------
// Number stepper
// ------------------------------------------------------------------
const PStepper = ({ value, onChange, min = 0, max = 999, step = 1 }) => {
  const dec = () => onChange(Math.max(min, value - step));
  const inc = () => onChange(Math.min(max, value + step));
  return (
    <div className="portal-stepper">
      <button onClick={dec} disabled={value <= min}><PIcon name="minus" size={13} /></button>
      <input
        value={value}
        onChange={e => {
          const v = e.target.value;
          if (v === '') { onChange(0); return; }
          const n = parseFloat(v);
          if (!isNaN(n)) onChange(Math.max(min, Math.min(max, n)));
        }}
      />
      <button onClick={inc} disabled={value >= max}><PIcon name="plus" size={13} /></button>
    </div>
  );
};

// ------------------------------------------------------------------
// Segment (tabs / pill nav)
// ------------------------------------------------------------------
const PSegment = ({ options, value, onChange }) => (
  <div className="portal-segment">
    {options.map(o => (
      <button key={o.value} className={value === o.value ? 'is-active' : ''} onClick={() => onChange(o.value)}>
        {o.label}
      </button>
    ))}
  </div>
);

// ------------------------------------------------------------------
// Pills
// ------------------------------------------------------------------
const PCategoryChip = ({ category }) => {
  const tone = {
    Sauce:                  { bg: '#F5F5F7', fg: '#6E6E73' },
    Vegetable:              { bg: '#F5F5F7', fg: '#6E6E73' },
    Meat:                   { bg: '#F5F5F7', fg: '#6E6E73' },
    Other:                  { bg: '#F5F5F7', fg: '#6E6E73' },
    'Cleaning & Fixing':    { bg: '#F5F5F7', fg: '#6E6E73' },
    Dry:                    { bg: '#F5F5F7', fg: '#6E6E73' },
    Dairy:                  { bg: '#F5F5F7', fg: '#6E6E73' },
  }[category] || { bg: '#F5F5F7', fg: '#6E6E73' };
  const icon = {
    Sauce: 'droplet', Vegetable: 'leaf', Meat: 'flame',
    Other: 'sparkle', 'Cleaning & Fixing': 'broom',
    Dry: 'box', Dairy: 'box',
  }[category];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      padding: '2px 8px 2px 6px', borderRadius: 999,
      background: tone.bg, color: tone.fg,
      fontSize: 11, fontWeight: 500, letterSpacing: 0,
    }}>
      {icon && <PIcon name={icon} size={11} />}
      {category}
    </span>
  );
};

const PPriorityPill = ({ priority }) => {
  const isPrim = priority === 'primary';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center',
      padding: '1.5px 7px',
      borderRadius: 999,
      background: isPrim ? 'var(--fg-1)' : 'transparent',
      color: isPrim ? '#FFFFFF' : 'var(--fg-2)',
      border: isPrim ? 'none' : '1px solid var(--border-1)',
      fontSize: 10,
      letterSpacing: '0.05em', textTransform: 'uppercase', fontWeight: 500,
    }}>{isPrim ? 'Primary' : 'Secondary'}</span>
  );
};

// ------------------------------------------------------------------
// Toast
// ------------------------------------------------------------------
const PToast = ({ message, open, onClose }) => {
  useEffect(() => {
    if (!open) return;
    const t = setTimeout(() => onClose && onClose(), 2400);
    return () => clearTimeout(t);
  }, [open]);
  if (!open) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 24, left: '50%',
      transform: 'translateX(-50%)',
      zIndex: 2000,
      padding: '9px 16px',
      background: '#181818', color: '#fff',
      borderRadius: 999, fontSize: 13, fontWeight: 500,
      display: 'flex', alignItems: 'center', gap: 8,
      boxShadow: '0 20px 50px rgba(0,0,0,0.18)',
      animation: 'slide-up 220ms cubic-bezier(0.25,0.46,0.45,0.94)',
    }}>
      <PIcon name="check" size={14} strokeWidth={2.5} />
      {message}
    </div>
  );
};

// ------------------------------------------------------------------
// Modal
// ------------------------------------------------------------------
const PModal = ({ open, onClose, children, width = 480, title }) => {
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0,
      background: 'rgba(0,0,0,0.30)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      zIndex: 1000, padding: 24,
      animation: 'fade-in 160ms',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width, maxWidth: '100%', maxHeight: '88vh',
        background: '#FFFFFF', borderRadius: 14,
        boxShadow: '0 20px 60px rgba(0,0,0,0.22)',
        overflow: 'hidden',
        display: 'flex', flexDirection: 'column',
        animation: 'pop-in 200ms cubic-bezier(0.25,0.46,0.45,0.94)',
      }}>
        {title && (
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '14px 18px', borderBottom: '1px solid var(--border-2)',
          }}>
            <div style={{ fontSize: 14, fontWeight: 600, letterSpacing: '-0.01em' }}>{title}</div>
            <button onClick={onClose} style={{
              width: 28, height: 28, borderRadius: 999,
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              color: 'var(--fg-2)',
            }}><PIcon name="x" size={15} /></button>
          </div>
        )}
        <div style={{ overflow: 'auto', flex: 1 }}>{children}</div>
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// Date helpers
// ------------------------------------------------------------------
const fmtDate = (d) => {
  const opts = { weekday: 'short', month: 'short', day: 'numeric' };
  return d.toLocaleDateString('en-US', opts);
};
const fmtDateLong = (d) => {
  const opts = { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' };
  return d.toLocaleDateString('en-US', opts);
};
const isoDate = (d) => d.toISOString().slice(0, 10);
const dayDiff = (a, b) => {
  const ms = 1000 * 60 * 60 * 24;
  const da = new Date(a.getFullYear(), a.getMonth(), a.getDate());
  const db = new Date(b.getFullYear(), b.getMonth(), b.getDate());
  return Math.round((da - db) / ms);
};

// ------------------------------------------------------------------
// Date picker (compact, popover)
// ------------------------------------------------------------------
const PDatePicker = ({ value, onChange }) => {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    const handler = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const today = new Date();
  const diff = dayDiff(value, today);
  let label;
  if (diff === 0) label = 'Today';
  else if (diff === -1) label = 'Yesterday';
  else if (diff === 1) label = 'Tomorrow';
  else label = fmtDate(value);

  const shift = (n) => {
    const d = new Date(value);
    d.setDate(d.getDate() + n);
    onChange(d);
  };

  // Mini calendar grid
  const [cursor, setCursor] = useState(new Date(value.getFullYear(), value.getMonth(), 1));
  useEffect(() => { setCursor(new Date(value.getFullYear(), value.getMonth(), 1)); }, [open]);

  const monthLabel = cursor.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
  const startWeekday = cursor.getDay();
  const daysInMonth = new Date(cursor.getFullYear(), cursor.getMonth() + 1, 0).getDate();

  return (
    <div ref={ref} style={{ position: 'relative', display: 'inline-flex', alignItems: 'center', gap: 4 }}>
      <button onClick={() => shift(-1)} className="portal-stepper-btn" style={{
        width: 30, height: 30, borderRadius: 8,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        color: 'var(--fg-2)',
      }}><PIcon name="chevronL" size={15} /></button>

      <button onClick={() => setOpen(o => !o)} style={{
        height: 34, padding: '0 12px',
        borderRadius: 8, border: '1px solid var(--border-1)',
        background: 'var(--bg-surface)', color: 'var(--fg-1)',
        fontSize: 13, fontWeight: 500,
        display: 'inline-flex', alignItems: 'center', gap: 8,
        minWidth: 160, justifyContent: 'space-between',
      }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <PIcon name="calendar" size={14} color="var(--fg-2)" />
          <span>{label}</span>
        </span>
        <span style={{ fontSize: 11, color: 'var(--fg-3)', fontVariantNumeric: 'tabular-nums' }}>
          {isoDate(value)}
        </span>
      </button>

      <button onClick={() => shift(1)} style={{
        width: 30, height: 30, borderRadius: 8,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        color: 'var(--fg-2)',
      }}><PIcon name="chevronR" size={15} /></button>

      {!isToday(value) && (
        <button onClick={() => onChange(new Date())} style={{
          height: 30, padding: '0 10px', marginLeft: 4,
          fontSize: 12, color: 'var(--fg-2)',
          borderRadius: 7,
          border: '1px solid var(--border-1)',
          background: 'var(--bg-surface)',
        }}>Jump to today</button>
      )}

      {open && (
        <div style={{
          position: 'absolute', top: '110%', left: 36,
          width: 260, padding: 12,
          background: '#fff', borderRadius: 12,
          boxShadow: '0 12px 40px rgba(0,0,0,0.15)',
          border: '1px solid var(--border-2)',
          zIndex: 100,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
            <button onClick={() => setCursor(c => new Date(c.getFullYear(), c.getMonth() - 1, 1))} style={{
              width: 24, height: 24, color: 'var(--fg-2)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            }}><PIcon name="chevronL" size={14} /></button>
            <div style={{ fontSize: 13, fontWeight: 600 }}>{monthLabel}</div>
            <button onClick={() => setCursor(c => new Date(c.getFullYear(), c.getMonth() + 1, 1))} style={{
              width: 24, height: 24, color: 'var(--fg-2)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            }}><PIcon name="chevronR" size={14} /></button>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2 }}>
            {['S','M','T','W','T','F','S'].map((d, i) => (
              <div key={i} style={{ fontSize: 10.5, color: 'var(--fg-3)', textAlign: 'center', padding: '2px 0', fontWeight: 500 }}>{d}</div>
            ))}
            {Array.from({ length: startWeekday }).map((_, i) => <div key={'b'+i}/>)}
            {Array.from({ length: daysInMonth }).map((_, i) => {
              const d = i + 1;
              const date = new Date(cursor.getFullYear(), cursor.getMonth(), d);
              const sel = isSameDay(date, value);
              const tod = isSameDay(date, new Date());
              return (
                <button key={d} onClick={() => { onChange(date); setOpen(false); }} style={{
                  height: 28, borderRadius: 6,
                  background: sel ? 'var(--fg-1)' : (tod ? 'var(--bg-sunken)' : 'transparent'),
                  color: sel ? '#fff' : 'var(--fg-1)',
                  fontSize: 12, fontWeight: tod && !sel ? 600 : 400,
                  fontVariantNumeric: 'tabular-nums',
                }}>{d}</button>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
};

const isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
const isToday = (d) => isSameDay(d, new Date());
const isPast = (d) => dayDiff(d, new Date()) < 0;
const isFuture = (d) => dayDiff(d, new Date()) > 0;

// ------------------------------------------------------------------
// Persistence helper
// ------------------------------------------------------------------
const usePersistent = (key, initial) => {
  const [val, setVal] = useState(() => {
    try {
      const raw = localStorage.getItem(key);
      if (raw === null) return initial;
      return JSON.parse(raw);
    } catch (e) { return initial; }
  });
  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(val)); } catch (e) {}
  }, [key, val]);
  return [val, setVal];
};

Object.assign(window, {
  PIcon, PAvatar, PAvatarStack, PBtn, PStepper, PSegment,
  PCategoryChip, PPriorityPill, PToast, PModal, PDatePicker,
  fmtDate, fmtDateLong, isoDate, dayDiff, isSameDay, isToday, isPast, isFuture,
  usePersistent,
});
