/**
 * Phishing Campaign Timeline Merge (Phase 22, Wave 0, REVIEW-02)
 *
 * Pure transform: merges the three already-camelCased sources consumed by
 * `TimelineCard` (reports, classifications, audit_events — see
 * app/api/phishing/campaigns/[id]/route.ts's response shape and
 * lib/services/phishing-audit.ts's canonical event_type values) into a
 * single ascending-by-timestamp array. Server-merge approach chosen per
 * 22-RESEARCH.md Alternatives Considered. No DB/fetch imports — pure
 * function, takes already-fetched row arrays.
 */

export type TimelineEntry =
  | { kind: 'report'; at: string; reportId: string; ticketNumber: string | null; companyName: string | null }
  | { kind: 'classification'; at: string; verdict: string; confidence: string | null }
  | { kind: 'audit'; at: string; eventType: string; actor: string | null; payload: unknown };

interface ReportTimelineSource {
  createdAt: string;
  reportId: string;
  ticketNumber: string | null;
  companyName: string | null;
}

interface ClassificationTimelineSource {
  createdAt: string;
  verdict: string;
  confidence: string | null;
}

interface AuditTimelineSource {
  createdAt: string;
  eventType: string;
  actor: string | null;
  payload: unknown;
}

/** Fixed tie-break priority when two entries share an identical `at` timestamp. */
const KIND_PRIORITY: Record<TimelineEntry['kind'], number> = {
  report: 0,
  classification: 1,
  audit: 2,
};

/**
 * Maps each of the three sources into its `TimelineEntry` variant,
 * concatenates, and sorts ascending by `at` (oldest first — matches the
 * existing `ORDER BY created_at ASC` convention). Ties on identical
 * timestamps fall back to a fixed kind priority (report < classification <
 * audit) for a stable, deterministic order.
 */
export function mergeTimeline(
  reports: ReportTimelineSource[],
  classifications: ClassificationTimelineSource[],
  auditEvents: AuditTimelineSource[]
): TimelineEntry[] {
  const entries: TimelineEntry[] = [
    ...reports.map<TimelineEntry>((report) => ({
      kind: 'report',
      at: report.createdAt,
      reportId: report.reportId,
      ticketNumber: report.ticketNumber,
      companyName: report.companyName,
    })),
    ...classifications.map<TimelineEntry>((classification) => ({
      kind: 'classification',
      at: classification.createdAt,
      verdict: classification.verdict,
      confidence: classification.confidence,
    })),
    ...auditEvents.map<TimelineEntry>((event) => ({
      kind: 'audit',
      at: event.createdAt,
      eventType: event.eventType,
      actor: event.actor,
      payload: event.payload,
    })),
  ];

  return entries.sort((a, b) => {
    const diff = new Date(a.at).getTime() - new Date(b.at).getTime();
    if (diff !== 0) return diff;
    return KIND_PRIORITY[a.kind] - KIND_PRIORITY[b.kind];
  });
}
