/**
 * Cascade alert formatter.
 *
 * Triggered by CascadeEngine when an injury / lineup / weather delta
 * recomputes a slate of grades. Composes the broadcast text + image
 * downstream channels send.
 */

const { buildCard, publicCardUrl } = require('./_shareCardClient');

const EMOJI_BY_TRIGGER = Object.freeze({
  injury:  '🚨',
  lineup:  '🔁',
  weather: '☔',
  ref:     '🟨',
  umpire:  '🟨',
  manual:  '🟢',
});

function urgencyFor(affectedCount) {
  if (affectedCount >= 5) return 'high';
  if (affectedCount >= 2) return 'medium';
  return 'low';
}

function shortTrigger(detail) {
  // Best-effort headline: prefer player + status if present, otherwise
  // type-specific defaults. Keep under 60 chars for the subject line.
  if (!detail || typeof detail !== 'object') return 'event';
  if (detail.player && detail.status) return `${detail.player} ${detail.status}`;
  if (detail.player) return detail.player;
  if (detail.summary) return String(detail.summary).slice(0, 60);
  return detail.type || 'event';
}

async function format(alert) {
  const triggerType = alert.trigger_type || 'manual';
  const emoji = EMOJI_BY_TRIGGER[triggerType] || '🟢';
  const affected = Array.isArray(alert.affected_props) ? alert.affected_props : [];
  const count = affected.length;
  const headline = shortTrigger(alert.trigger_detail);

  const text = `${emoji} ${headline.toUpperCase()} — ${count} prop${count === 1 ? '' : 's'} affected`;

  // Render the cascade as a "recap" card so the layout is consistent.
  // Negative deltas (grade went down) render as miss-tinted rows, positives
  // as hit-tinted. This is purely visual; the data layer keeps the deltas.
  const entries = affected.slice(0, 6).map((p) => ({
    player: p.player || '',
    stat: p.stat || '',
    direction: p.direction || 'over',
    line: p.line,
    grade: p.new_grade || p.grade || '—',
    result: (p.new_grade && p.old_grade && rank(p.new_grade) > rank(p.old_grade)) ? 'miss' : 'hit',
  }));

  const payload = {
    date: `${emoji} ${headline}`.slice(0, 40),
    accuracy: null,
    entries,
  };

  let card = null;
  try {
    card = await buildCard({ type: 'recap', format: 'square', payload });
  } catch (err) {
    console.error('[cascadeFormatter] card build failed:', err.message);
  }

  return {
    text,
    urgency: urgencyFor(count),
    affected_count: count,
    imageBuffer: card?.buffer || null,
    imageUrl: publicCardUrl({ type: 'recap', format: 'square', payload }),
  };
}

function rank(grade) {
  const map = { 'A+': 0, 'A': 1, 'A-': 2, 'B+': 3, 'B': 4, 'B-': 5, 'C+': 6, 'C': 7, 'C-': 8, 'D': 9, 'F': 10 };
  return map[grade] ?? 5;
}

module.exports = { format, urgencyFor };
