// Industry news — trade-press stories + rightsholder monitoring.
// Two surfaces share this file: a Dashboard card (latest few, unread-first)
// and the full feed inside News Intake's "Industry news" tab.

const IMPACT_META = {
  direct:   { label: 'Direct impact',   kind: 'attention' },
  indirect: { label: 'Indirect',        kind: 'pending' },
  info:     { label: 'FYI',             kind: 'muted' },
};
const impactMeta = (v) => IMPACT_META[v] || IMPACT_META.info;

// ── Feed order: unread first, then newest first ─────────────────────────────
// Both surfaces sort through this, so the Dashboard card can never show a
// different top item than the feed it links to.
//
// Unread leads on purpose. Sorting on date alone buried every newly collected
// item: a story with no publication date falls back to the date it was
// collected, so undated pages (federation sponsorship landing pages, directory
// listings) permanently outranked real news published weeks earlier. A sweep
// could add a dozen items and none of them appeared in the first 25 rows.
// Read state answers "have we looked at this yet", which is the question this
// feed exists for, and it does not decay the way a fallback date does.
const newsDateOf = (it) => it.publishedDate || (it.createdAt || '').slice(0, 10) || '';

function byUnreadThenDate(a, b) {
  const unreadA = a.isRead ? 1 : 0;
  const unreadB = b.isRead ? 1 : 0;
  if (unreadA !== unreadB) return unreadA - unreadB;   // unread (0) before read (1)
  return newsDateOf(b).localeCompare(newsDateOf(a));   // then newest first
}

// Shared loader — items sorted unread-first, newest first.
function useIndustryNews() {
  const [items, setItems] = React.useState(null);   // null = loading
  const [error, setError] = React.useState(null);

  const load = React.useCallback(() => {
    window.IPSEM_API.getIndustryNews()
      .then((rows) => { setItems(Array.isArray(rows) ? rows : []); setError(null); })
      .catch((e) => { setError(e.message || 'Could not load industry news'); setItems([]); });
  }, []);
  React.useEffect(() => { load(); }, [load]);

  const markRead = (id, isRead) => {
    setItems((cur) => (cur || []).map((it) => it.id === id ? { ...it, isRead } : it));
    window.IPSEM_API.updateIndustryNews(id, { isRead }).catch(() => {
      // Put this one item back rather than reloading the feed — a reload would
      // also discard every other item marked read in the same pass.
      setItems((cur) => (cur || []).map((it) => it.id === id ? { ...it, isRead: !isRead } : it));
    });
  };

  return { items, error, load, markRead };
}

function IndustryItem({ it, onMarkRead, compact }) {
  const im = impactMeta(it.impact);
  return (
    <div
      className="row gap-3"
      style={{
        padding: compact ? '10px 12px' : '14px 16px',
        background: it.isRead ? 'transparent' : 'var(--card-alt)',
        borderRadius: 8,
        alignItems: 'flex-start',
        borderLeft: it.isRead ? '3px solid transparent' : `3px solid ${it.impact === 'direct' ? 'var(--attention)' : 'var(--accent)'}`,
      }}
    >
      <div className="grow" style={{ minWidth: 0 }}>
        <div className="row gap-2" style={{ alignItems: 'center', flexWrap: 'wrap' }}>
          {it.url ? (
            <a href={it.url} target="_blank" rel="noopener noreferrer" style={{ fontWeight: 600, fontSize: compact ? 13 : 13.5, color: 'var(--ink)', textDecoration: 'none' }}
               onClick={() => !it.isRead && onMarkRead(it.id, true)}>
              {it.title}
            </a>
          ) : (
            <span style={{ fontWeight: 600, fontSize: compact ? 13 : 13.5 }}>{it.title}</span>
          )}
          {it.propertyName ? <Pill kind="accent">{it.propertyName}</Pill> : null}
          <Pill kind={im.kind}>{im.label}</Pill>
        </div>
        {!compact && it.summary ? (
          <div className="text-sm text-2" style={{ marginTop: 4, lineHeight: 1.55 }}>{it.summary}</div>
        ) : compact && it.summary ? (
          <div className="text-xs text-2 truncate" style={{ marginTop: 3 }}>{it.summary}</div>
        ) : null}
        <div className="row gap-2 text-xs text-3" style={{ marginTop: 4, flexWrap: 'wrap' }}>
          {it.source ? <span>{it.source}</span> : null}
          {(it.publishedDate || it.createdAt) ? (<><span>·</span><span>{formatDate(it.publishedDate || it.createdAt)}</span></>) : null}
          {(it.brandsMentioned || []).length ? (
            <>
              <span>·</span>
              <span>Brands: {(it.brandsMentioned || []).slice(0, 4).join(', ')}</span>
            </>
          ) : null}
          {it.url ? (
            <a href={it.url} target="_blank" rel="noopener noreferrer" className="row gap-1" style={{ color: 'var(--accent)' }}
               onClick={() => !it.isRead && onMarkRead(it.id, true)}>
              <window.I.external size={11} /> Read
            </a>
          ) : null}
        </div>
      </div>
      <button
        className="btn btn-icon btn-ghost"
        title={it.isRead ? 'Mark unread' : 'Mark read'}
        onClick={() => onMarkRead(it.id, !it.isRead)}
        style={{ flexShrink: 0 }}
      >
        <window.I.check size={13} stroke={it.isRead ? 'var(--ink-4)' : 'var(--positive)'} />
      </button>
    </div>
  );
}

// ─── Full feed (News Intake tab) ────────────────────────────────────────────
function IndustryFeed({ onToast }) {
  const { items, error, load, markRead } = useIndustryNews();
  const [scanning, setScanning] = React.useState(false);
  const [filter, setFilter] = React.useState('all'); // all | rightsholder | trade | unread

  const runSweep = async () => {
    if (scanning) return;
    setScanning(true);
    try {
      await window.IPSEM_API.runIndustryScan();
      onToast && onToast('Industry sweep started — new items appear here in a minute or two');
      setTimeout(load, 90000);
    } catch (e) {
      onToast && onToast(e.message || 'Could not start the sweep');
    } finally {
      setScanning(false);
    }
  };

  const list = (items || []).filter((it) =>
    filter === 'all' ? true :
    filter === 'unread' ? !it.isRead :
    it.category === filter
  );
  const sorted = [...list].sort(byUnreadThenDate);

  return (
    <Card pad={false}>
      <div className="row" style={{ padding: '14px 18px', borderBottom: '1px solid var(--hairline)', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8 }}>
        <div>
          <div className="h3">Industry news</div>
          <div className="text-3 text-xs" style={{ marginTop: 2 }}>
            Trade press + monitoring of your rightsholders. Updated with every scan.
          </div>
        </div>
        <div className="row gap-2">
          <div className="toggle-group">
            <button className={filter === 'all' ? 'is-active' : ''} onClick={() => setFilter('all')}>All</button>
            <button className={filter === 'unread' ? 'is-active' : ''} onClick={() => setFilter('unread')}>Unread</button>
            <button className={filter === 'rightsholder' ? 'is-active' : ''} onClick={() => setFilter('rightsholder')}>Our rightsholders</button>
            <button className={filter === 'trade' ? 'is-active' : ''} onClick={() => setFilter('trade')}>Trade</button>
          </div>
          <button className="btn btn-sm" onClick={runSweep} disabled={scanning}>
            <window.I.refresh size={12} className={scanning ? 'spin' : ''} />
            {scanning ? 'Sweeping…' : 'Run sweep now'}
          </button>
        </div>
      </div>

      {items === null ? (
        <div className="empty">Loading industry news…</div>
      ) : error ? (
        <div className="empty">{error}</div>
      ) : sorted.length === 0 ? (
        <div className="empty">
          <div className="col gap-3" style={{ alignItems: 'center' }}>
            <div>{filter === 'all' ? 'No industry news collected yet.' : 'Nothing matches this filter.'}</div>
            {filter === 'all' ? (
              <button className="btn btn-primary btn-sm" onClick={runSweep} disabled={scanning}>
                <window.I.bolt size={13} /> Run the first sweep
              </button>
            ) : null}
          </div>
        </div>
      ) : (
        <div className="col" style={{ padding: 12, gap: 8 }}>
          {sorted.map((it) => <IndustryItem key={it.id} it={it} onMarkRead={markRead} />)}
        </div>
      )}
    </Card>
  );
}

// ─── Dashboard card (latest few, unread-first) ──────────────────────────────
function IndustryNewsCard({ onNavigate }) {
  const { items, markRead } = useIndustryNews();
  if (items === null) return null;           // loading — keep the dashboard calm
  if (!items.length) return null;            // nothing collected yet — hide card
  const unread = items.filter((it) => !it.isRead).length;
  const shown = [...items].sort(byUnreadThenDate).slice(0, 5);

  return (
    <Card pad={false} style={{ marginBottom: 18 }}>
      <div className="row" style={{ padding: '14px 18px', borderBottom: '1px solid var(--hairline)', justifyContent: 'space-between' }}>
        <div className="col" style={{ gap: 2 }}>
          <div className="h3 row gap-2">
            Industry news
            {unread ? <Pill kind="accent">{unread} new</Pill> : null}
          </div>
          <div className="text-3 text-xs">Your rightsholders and the sponsorship trade press.</div>
        </div>
        <button className="btn btn-sm btn-ghost" onClick={() => {
          try { sessionStorage.setItem('ipsem-intake-tab', 'industry'); } catch (_) {}
          onNavigate('intake');
        }}>
          See all <window.I.chevronRight size={14} />
        </button>
      </div>
      <div className="col" style={{ padding: 10, gap: 6 }}>
        {shown.map((it) => <IndustryItem key={it.id} it={it} onMarkRead={markRead} compact />)}
      </div>
    </Card>
  );
}

Object.assign(window, { IndustryFeed, IndustryNewsCard });
