/**
 * Triage-note formatter (Phase 21, NOTE-01).
 *
 * Pure, deterministic function that turns a structured campaign-evidence
 * object (`TriageNoteEvidence`) into human-readable prose suitable for
 * posting as an internal Autotask `TicketNotes` entry. No DB, network, or
 * Autotask dependency — Plan 02's service gathers evidence and calls
 * `formatTriageNote()`, then writes the resulting text.
 *
 * Every URL and the entire assembled string are routed through
 * `triage-note-sanitize.ts` before being returned, so a secret/token/full
 * malicious query string embedded in ANY source field (summary, reasons,
 * URLs) is stripped regardless of which field it came from (D-04 "full
 * picture" + NOTE-01 sanitization requirement).
 */

import { sanitizeUrl, sanitizeNoteText } from './triage-note-sanitize';
import type { BlastRadiusResult } from './mimecast-blast-radius';

export interface TriageNoteEvidence {
  campaignId: string;
  reportCount: number;
  companyName?: string | null;
  subject?: string | null;
  verdict: 'SPAM' | 'UNWANTED' | 'THREAT' | 'USER_AWARENESS' | null;
  confidence: number | null;
  summary: string | null;
  reasons: string[];
  recommendedActions: string[];
  requiresApproval: boolean;
  blastRadius: BlastRadiusResult;
  remediationActions: Array<{
    actionType: string;
    status: string;
    approvedBy: string | null;
    approvedAt: string | null;
  }>;
  urls: string[];
}

function formatBlastRadiusSection(blastRadius: BlastRadiusResult): string {
  if (blastRadius.status === 'unavailable') {
    const detail = blastRadius.error ? ` — ${blastRadius.error}` : '';
    return `Blast Radius: unavailable (reason: ${blastRadius.reason})${detail}`;
  }

  return [
    'Blast Radius:',
    `  Matched: ${blastRadius.matched}`,
    `  Delivered: ${blastRadius.delivered}`,
    `  Held: ${blastRadius.held}`,
    `  Rejected: ${blastRadius.rejected}`,
    `  Clicked: ${blastRadius.clicked}`,
  ].join('\n');
}

function formatRemediationSection(
  remediationActions: TriageNoteEvidence['remediationActions']
): string {
  if (remediationActions.length === 0) {
    return 'Current Remediation State: No action has been taken yet — recommended actions are proposed-only.';
  }

  const lines = remediationActions.map((action) => {
    const approver =
      action.approvedBy || action.approvedAt
        ? ` (approver: ${action.approvedBy ?? 'unknown'}, approved at: ${action.approvedAt ?? 'unknown'})`
        : '';
    return `  - ${action.actionType} — ${action.status}${approver}`;
  });

  return ['Current Remediation State:', ...lines].join('\n');
}

/**
 * Assemble the full triage note as human-readable prose, sanitized so no
 * secret/token/full malicious URL query string survives regardless of which
 * evidence field it originated from.
 */
export function formatTriageNote(evidence: TriageNoteEvidence): string {
  const verdictLabel = evidence.verdict ?? 'not yet classified';
  const confidenceLabel =
    evidence.confidence === null || evidence.confidence === undefined
      ? 'not yet classified'
      : String(evidence.confidence);

  const headerLine = `Phishing Triage Summary — Campaign ${evidence.campaignId} (${evidence.reportCount} report${evidence.reportCount === 1 ? '' : 's'})`;

  const classificationSection = [
    'Classification:',
    `  Verdict: ${verdictLabel}`,
    `  Confidence: ${confidenceLabel}`,
    `  Summary: ${evidence.summary ?? 'not yet classified'}`,
  ].join('\n');

  const reasonsSection =
    evidence.reasons.length > 0
      ? ['Reasons:', ...evidence.reasons.map((r) => `  - ${r}`)].join('\n')
      : 'Reasons: none recorded';

  const blastRadiusSection = formatBlastRadiusSection(evidence.blastRadius);

  const recommendedActionsSection = [
    'Recommended Actions:',
    evidence.recommendedActions.length > 0
      ? evidence.recommendedActions.map((a) => `  - ${a}`).join('\n')
      : '  - none',
    evidence.requiresApproval ? '  (requires operator approval)' : '  (no approval required)',
  ].join('\n');

  const remediationSection = formatRemediationSection(evidence.remediationActions);

  const urlsSection =
    evidence.urls.length > 0
      ? ['Indicator URLs:', ...evidence.urls.map((u) => `  - ${sanitizeUrl(u)}`)].join('\n')
      : null;

  const sections = [
    headerLine,
    evidence.companyName ? `Company: ${evidence.companyName}` : null,
    evidence.subject ? `Subject: ${evidence.subject}` : null,
    classificationSection,
    reasonsSection,
    blastRadiusSection,
    recommendedActionsSection,
    remediationSection,
    urlsSection,
  ].filter((s): s is string => s !== null);

  const assembled = sections.join('\n\n');

  return sanitizeNoteText(assembled);
}
