// Shared small components: Tile, Pill, Icon, etc.
const { useState, useEffect, useMemo, useRef, useCallback } = React;

const Icon = ({ name, size = 14, stroke = "currentColor" }) => {
  const paths = {
    search: <><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></>,
    home:   <><path d="M3 10.5 12 3l9 7.5"/><path d="M5 9v11h14V9"/></>,
    inbox:  <><path d="M3 13h6l2 3h2l2-3h6"/><path d="M3 13V6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7"/><path d="M3 13v6a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-6"/></>,
    flag:   <><path d="M4 22V4"/><path d="M4 4h13l-2 4 2 4H4"/></>,
    export: <><path d="M12 3v12"/><path d="m7 8 5-5 5 5"/><path d="M5 21h14"/></>,
    settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3h.1a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z"/></>,
    check:  <polyline points="4 12 10 18 20 6"/>,
    x:      <><path d="m6 6 12 12"/><path d="m18 6-12 12"/></>,
    chevR:  <polyline points="9 6 15 12 9 18"/>,
    chevL:  <polyline points="15 6 9 12 15 18"/>,
    chevD:  <polyline points="6 9 12 15 18 9"/>,
    ext:    <><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"/></>,
    filter: <><path d="M3 5h18"/><path d="M6 12h12"/><path d="M10 19h4"/></>,
    ban:    <><circle cx="12" cy="12" r="9"/><path d="m5 5 14 14"/></>,
    dot:    <circle cx="12" cy="12" r="4"/>,
    clock:  <><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 16 14"/></>,
    user:   <><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></>,
    lock:   <><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 1 1 8 0v3"/></>,
    bolt:   <path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/>,
    clock:  <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>,
    edit:   <><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 1 1 3 3L7 19l-4 1 1-4Z"/></>,
    help:   <><circle cx="12" cy="12" r="9"/><path d="M9.1 9a3 3 0 0 1 5.8 1c0 2-3 2.5-3 4"/><circle cx="12" cy="17" r="0.6" fill="currentColor" stroke="none"/></>,
    plus:   <><path d="M12 5v14"/><path d="M5 12h14"/></>,
    trash:  <><path d="M4 7h16"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13"/><path d="M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"/></>,
    copy:   <><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/></>,
    logout: <><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><path d="m21 12-9 0"/></>,
    alert:  <><path d="m21 16-4-4m0 0l-4-4m4 4l-4-4m4 4l4-4"/><circle cx="12" cy="12" r="10"/><path d="M12 7v5"/><path d="M12 16h.01"/></>,
    loader: <><path d="M12 3v3m6.366-.366l-2.12 2.12M21 12h-3m.366 6.366l-2.12-2.12M12 21v-3m-6.366.366l2.12-2.12M3 12h3m-.366-6.366l2.12 2.12"/></>,
    refresh: <><path d="M21.5 2v6h-6M2.5 22v-6h6"/><path d="M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/></>,
    login:  <><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><path d="m15 12-15 0"/></>,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
         stroke={stroke} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      {paths[name]}
    </svg>
  );
};

const TILE_LABELS = {
  instagram: 'IG', youtube: 'YT', tiktok: 'TK', x: 'X', facebook: 'FB', twitch: 'TH', web: 'WW',
};

const Tile = ({ platform, status, size = '', selected = false, onClick, title }) => (
  <div
    className={`tile ${status} ${size} ${selected ? 'selected' : ''}`}
    onClick={onClick}
    title={title || `${platform}: ${status}`}
    role={onClick ? 'button' : 'presentation'}
  >
    <div className="tile-lbl">{TILE_LABELS[platform]}</div>
    <div className="tile-bar" />
    {status === 'qc' && (
      <div style={{
        position: 'absolute', top: 2, right: 2,
        width: 8, height: 8, borderRadius: 2,
        background: '#16A34A',
      }}/>
    )}
    {status === 'verified' && (
      <div style={{
        position: 'absolute', top: 2, right: 2,
        width: 4, height: 4, borderRadius: 2,
        background: '#16A34A',
      }}/>
    )}
  </div>
);

const Pill = ({ kind = 'neutral', dot = false, children }) => (
  <span className={`pill ${kind}`}>
    {dot && <span className="dot" style={{background: 'currentColor'}}/>}
    {children}
  </span>
);

// Status helpers
const STATUS_META = {
  missing:       { label: 'Missing',          color: '#A8A29E',  pill: 'neutral' },
  unverified:    { label: 'Needs review',     color: '#D97706',  pill: 'warn' },
  verified:      { label: 'Verified',         color: '#84CC16',  pill: 'info' },
  qc:            { label: 'QC passed',        color: '#16A34A',  pill: 'ok' },
  'non-existing':{ label: 'Confirmed absent', color: '#57534E',  pill: 'neutral' },
  trusted:       { label: 'Trusted',          color: '#059669',  pill: 'ok' },
};

// Compute counts per person (now handles arrays of handles per platform)
function computeCounts(person, platforms) {
  const c = { missing: 0, unverified: 0, verified: 0, qc: 0, 'non-existing': 0 };
  let totalHandles = 0;
  for (const p of platforms) {
    const handles = person.handles[p.id];
    if (Array.isArray(handles)) {
      totalHandles += handles.length;
      for (const h of handles) {
        c[h.status] = (c[h.status] || 0) + 1;
      }
    } else {
      // Backwards compatibility for single handle structure
      totalHandles += 1;
      c[handles.status] = (c[handles.status] || 0) + 1;
    }
  }
  const done = c.qc + c['non-existing'];
  const complete = done === totalHandles;
  return { ...c, done, total: totalHandles, complete };
}

function overallStatus(counts) {
  if (counts.complete) return { kind: 'ok', label: 'Complete' };
  if (counts.unverified > 0 || counts.missing > 0) return { kind: 'warn', label: `${counts.unverified + counts.missing} to review` };
  if (counts.verified > 0) return { kind: 'info', label: `${counts.verified} for QC` };
  return { kind: 'neutral', label: '—' };
}

// Profile (country + category) counts — same status vocabulary as platforms,
// but only for the person-attribute rows. Used in the detail view's progress.
// Trusted attributes (where tool and ES match) are excluded from verification workflow.
function computeProfileCounts(person) {
  const c = { unverified: 0, verified: 0, qc: 0, trusted: 0 };
  if (!person.profile) return { ...c, done: 0, total: 0 };
  let totalCount = 0;
  for (const k of ['country', 'category']) {
    const st = person.profile[k]?.status || 'unverified';
    c[st] = (c[st] || 0) + 1;
    if (st !== 'trusted') totalCount++; // Don't count trusted items in progress
  }
  return { ...c, done: c.qc, total: totalCount };
}

// Active "soft locks": who else has opened a person in the last 5 minutes.
// Returns { [personId]: { id, name, initials, role, activity, since, status, openedAt } }.
function getActiveLocks(team, currentUser) {
  const map = {};
  const fiveMinutesMs = 5 * 60 * 1000;
  const now = Date.now();

  const parseApiTimestamp = (value) => {
    if (!value || typeof value !== 'string') return NaN;
    let s = value.trim();
    // API can return microseconds (e.g., .254000). JS Date prefers milliseconds.
    s = s.replace(/\.(\d{3})\d+/, '.$1');

    const hasTimezone = /[zZ]$|[+-]\d{2}:\d{2}$/.test(s);
    if (hasTimezone) return Date.parse(s);

    // Some endpoints return naive timestamps that are effectively UTC,
    // others behave like local time. Evaluate both and choose the closer one.
    const utcTs = Date.parse(`${s}Z`);
    const localTs = Date.parse(s);
    const utcDiff = Number.isFinite(utcTs) ? Math.abs(now - utcTs) : Number.POSITIVE_INFINITY;
    const localDiff = Number.isFinite(localTs) ? Math.abs(now - localTs) : Number.POSITIVE_INFINITY;

    if (!Number.isFinite(utcTs) && !Number.isFinite(localTs)) return NaN;
    return utcDiff <= localDiff ? utcTs : localTs;
  };

  const currentUserIds = new Set([
    currentUser?.id,
    currentUser?._id,
    currentUser?.user_id,
    currentUser?.email,
  ].filter(Boolean));

  const toInitials = (name) => {
    if (!name) return '?';
    return name
      .split(' ')
      .map(n => n.charAt(0))
      .join('')
      .toUpperCase()
      .slice(0, 2);
  };

  const formatSince = (openedAt) => {
    const diffMs = Math.max(0, now - openedAt);
    const minutes = Math.floor(diffMs / 60000);
    if (minutes <= 0) return 'just now';
    if (minutes === 1) return '1 minute ago';
    return `${minutes} minutes ago`;
  };

  for (const t of team || []) {
    const actorId = t?.id || t?.user_id || t?.email;
    if (actorId && currentUserIds.has(actorId)) continue;

    const personIdRaw = t?.personId || t?.current_person_id || t?.last_viewed_person?.id;
    const personId = personIdRaw != null ? String(personIdRaw) : '';
    const openedAtRaw = t?.last_viewed_person?.at || t?.current_person_at || t?.last_active;
    const openedAt = parseApiTimestamp(openedAtRaw || '');
    if (!personId || !Number.isFinite(openedAt)) continue;

    if (now - openedAt > fiveMinutesMs) continue;

    const normalized = {
      ...t,
      personId,
      initials: t?.initials || toInitials(t?.name),
      activity: t?.activity || 'review',
      since: t?.since || formatSince(openedAt),
      status: t?.status || 'online',
      openedAt,
    };

    const existing = map[personId];
    if (!existing || normalized.openedAt > existing.openedAt) {
      map[personId] = normalized;
    }
  }
  return map;
}

// Small presence chip — avatar + activity dot — for list rows.
const LockChip = ({ lock, size = 18 }) => {
  if (!lock) return null;
  const verb = lock.activity === 'qc' ? 'QC' : 'reviewing';
  return (
    <span
      className={`lock-chip ${lock.status}`}
      title={`${lock.name} (${lock.role}) · ${verb} · ${lock.since}`}
      onClick={(e) => e.stopPropagation()}
    >
      <span className="avatar xs" style={{width: size, height: size, fontSize: Math.round(size*0.45)}}>
        {lock.initials}
      </span>
      <span className={`presence ${lock.status}`}/>
    </span>
  );
};

// Helper function to get the lowest status from multiple handles
// Shows the status that needs the most attention (lowest priority in workflow)
// Status priority: missing < unverified < non-existing < verified < qc
function getMostAdvancedStatus(handles) {
  if (!Array.isArray(handles) || handles.length === 0) {
    return { status: 'missing', sports: '', panel: '', merged: '' };
  }
  
  const priorities = {
    'missing': 1,        // Highest priority to show (needs most attention)
    'unverified': 2,
    'non-existing': 3,
    'verified': 4,
    'qc': 5             // Lowest priority to show (completed)
  };
  
  return handles.reduce((worst, current) => {
    const currentPriority = priorities[current.status] || 1;
    const worstPriority = priorities[worst.status] || 1;
    return currentPriority < worstPriority ? current : worst;
  });
}

Object.assign(window, { Icon, Tile, Pill, TILE_LABELS, STATUS_META, computeCounts, overallStatus, computeProfileCounts, getActiveLocks, LockChip, getMostAdvancedStatus });
