// ClientLogo: a client's logo, or a monogram tile when it has none.
// Logos are only served to signed-in people who may see that client, so they are fetched with the
// auth token and kept as object URLs (one fetch per client and logo version).
// Exports: ClientLogo

const _logoUrls = new Map();   // "id:version" -> Promise<string | null>

function loadClientLogo(clientId, version) {
  const key = clientId + ':' + version;
  if (!_logoUrls.has(key)) {
    _logoUrls.set(key, fetch('/api/clients/' + clientId + '/logo', {
      headers: { Authorization: 'Bearer ' + (localStorage.getItem('hub_token') || '') },
    })
      .then(r => r.ok ? r.blob() : null)
      .then(b => b ? URL.createObjectURL(b) : null)
      .catch(() => null));
  }
  return _logoUrls.get(key);
}

// monogram colours, taken from the brand palette so tiles feel related but not identical
const MONOGRAMS = [
  ['#E8EFF8', '#1A5090'], ['#FDEEE6', '#B8470F'], ['#E6F4EF', '#17745A'],
  ['#EEEAF8', '#5B45A8'], ['#FBF1DC', '#8A5A00'], ['#E7F1F8', '#0F5E8A'],
];
function monogramFor(name) {
  let h = 0;
  for (const ch of String(name || '?')) h = (h * 31 + ch.charCodeAt(0)) >>> 0;
  return MONOGRAMS[h % MONOGRAMS.length];
}
function monogramLetters(name) {
  const parts = String(name || '?').trim().split(/\s+/).filter(Boolean);
  return ((parts[0]?.[0] || '?') + (parts.length > 1 ? parts[parts.length - 1][0] : '')).toUpperCase();
}

function ClientLogo({ clientId, name, hasLogo, version = 0, size = 36, radius, style }) {
  const [url, setUrl] = React.useState(null);
  React.useEffect(() => {
    let live = true;
    setUrl(null);
    if (hasLogo && clientId) loadClientLogo(clientId, version).then(u => { if (live) setUrl(u); });
    return () => { live = false; };
  }, [clientId, hasLogo, version]);

  const r = radius ?? Math.round(size * 0.26);
  const box = { width: size, height: size, borderRadius: r, flexShrink: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden', ...style };

  if (url) {
    return (
      <span style={{ ...box, background: '#fff', border: '1px solid #E2E8F0', boxSizing: 'border-box' }}>
        <img src={url} alt={name ? name + ' logo' : ''} style={{ width: '100%', height: '100%', objectFit: 'contain', padding: Math.round(size * 0.14), boxSizing: 'border-box' }} />
      </span>
    );
  }
  const [bg, fg] = monogramFor(name);
  return (
    <span aria-hidden="true" style={{ ...box, background: bg, color: fg, fontWeight: 800, fontSize: Math.round(size * 0.38), letterSpacing: '-0.02em' }}>
      {monogramLetters(name)}
    </span>
  );
}

// ── Ticket type icons and colours (the server accepts exactly these keys) ──
const TYPE_PALETTE = {
  blue:   ['#E8EFF8', '#1A5090'], violet: ['#EEEAF8', '#5B45A8'], green:  ['#E6F4EF', '#17745A'], amber:  ['#FBF1DC', '#8A5A00'],
  rose:   ['#FBE9EC', '#B4233C'], slate:  ['#EDF0F4', '#475569'], teal:   ['#E3F3F5', '#0F6B7A'], orange: ['#FDEEE6', '#B8470F'],
};
const TYPE_DEFAULT_COLORS = ['blue', 'violet', 'green', 'amber', 'rose', 'slate'];   // used by position until an admin picks one
const TYPE_ICONS = {
  bug:      'M8 2l1.88 1.88 M14.12 3.88L16 2 M9 7.13v-1a3.003 3.003 0 1 1 6 0v1 M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6 M12 20v-9 M6.53 9C4.6 8.8 3 7.1 3 5 M6 13H2 M3 21c0-2.1 1.7-3.9 3.8-4 M20.97 5c0 2.1-1.6 3.8-3.5 4 M22 13h-4 M17.2 17c2.1.1 3.8 1.9 3.8 4',
  help:     'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3 M12 17h.01',
  key:      'M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4',
  wrench:   'M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z',
  bolt:     'M13 2L3 14h9l-1 8 10-12h-9l1-8z',
  shield:   'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z',
  message:  'M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z',
  lifebuoy: 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z M12 16a4 4 0 1 0 0-8 4 4 0 0 0 0 8z M4.93 4.93l4.24 4.24 M14.83 9.17l4.24-4.24 M14.83 14.83l4.24 4.24 M9.17 14.83l-4.24 4.24',
  rocket:   'M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z M12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0 M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5',
  globe:    'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z M2 12h20 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',
  file:     'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8',
  database: 'M12 8c4.97 0 9-1.34 9-3s-4.03-3-9-3-9 1.34-9 3 4.03 3 9 3z M21 12c0 1.66-4 3-9 3s-9-1.34-9-3 M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5',
  star:     'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z',
  lock:     'M19 11H5a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2z M7 11V7a5 5 0 0 1 10 0v4',
  tag:      'M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z M7 7h.01',
};
const TYPE_ICON_LABELS = { bug: 'Bug', help: 'Question', key: 'Access', wrench: 'Maintenance', bolt: 'Urgent', shield: 'Security', message: 'Feedback', lifebuoy: 'Support', rocket: 'Release', globe: 'Website', file: 'Document', database: 'Data', star: 'Feature', lock: 'Permissions', tag: 'General' };

function TypeIcon({ name, size = 18, strokeWidth = 1.9 }) {
  const d = TYPE_ICONS[name];
  if (!d) return null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" style={{ flexShrink: 0 }}>
      {d.split(' M').map((seg, i) => <path key={i} d={(i ? 'M' : '') + seg} />)}
    </svg>
  );
}

// the tile a ticket type wears: its icon (or first letter) in its colours
function TypeBadge({ icon, bg, fg, name, size = 42, radius }) {
  return (
    <span aria-hidden="true" style={{ width: size, height: size, borderRadius: radius ?? Math.round(size * 0.26), background: bg, color: fg, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontWeight: 800, fontSize: Math.round(size * 0.42), flexShrink: 0 }}>
      {icon && TYPE_ICONS[icon] ? <TypeIcon name={icon} size={Math.round(size * 0.5)} /> : String(name || '?').charAt(0).toUpperCase()}
    </span>
  );
}

// ── People's photos: the photo when there is one, else coloured initials ──
const _photoUrls = new Map();
function loadUserPhoto(userId, version) {
  const key = userId + ':' + version;
  if (!_photoUrls.has(key)) {
    _photoUrls.set(key, fetch('/api/users/' + userId + '/photo', {
      headers: { Authorization: 'Bearer ' + (localStorage.getItem('hub_token') || '') },
    })
      .then(r => r.ok ? r.blob() : null)
      .then(b => b ? URL.createObjectURL(b) : null)
      .catch(() => null));
  }
  return _photoUrls.get(key);
}

function UserAvatar({ userId, name, hasPhoto, version = 0, size = 32, style }) {
  const [url, setUrl] = React.useState(null);
  React.useEffect(() => {
    let live = true;
    setUrl(null);
    if (hasPhoto && userId) loadUserPhoto(userId, version).then(u => { if (live) setUrl(u); });
    return () => { live = false; };
  }, [userId, hasPhoto, version]);
  const box = { width: size, height: size, borderRadius: '50%', flexShrink: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden', ...style };
  if (url) return <img src={url} alt={name ? name + ' photo' : ''} style={{ ...box, objectFit: 'cover' }} />;
  const [bg, fg] = monogramFor(name);
  return <span aria-hidden="true" style={{ ...box, background: bg, color: fg, fontWeight: 800, fontSize: Math.round(size * 0.4) }}>{monogramLetters(name)}</span>;
}

Object.assign(window, { ClientLogo, monogramFor, monogramLetters, TYPE_PALETTE, TYPE_DEFAULT_COLORS, TYPE_ICONS, TYPE_ICON_LABELS, TypeIcon, TypeBadge, UserAvatar });
