import { describe, it, expect } from 'vitest';
import { formatTriageNote, type TriageNoteEvidence } from './triage-note-format';
import type { BlastRadiusResult } from './mimecast-blast-radius';

function baseEvidence(overrides: Partial<TriageNoteEvidence> = {}): TriageNoteEvidence {
  return {
    campaignId: 'campaign-1',
    reportCount: 3,
    companyName: 'Acme Corp',
    subject: 'Your invoice is ready',
    verdict: 'THREAT',
    confidence: 0.85,
    summary: 'Credential-harvesting link found in message body.',
    reasons: ['Sender domain not in allowlist', 'URL matches known phishing indicator'],
    recommendedActions: ['block_sender', 'purge_message'],
    requiresApproval: true,
    blastRadius: { status: 'unavailable', reason: 'not_configured' },
    remediationActions: [],
    urls: [],
    ...overrides,
  };
}

describe('formatTriageNote', () => {
  it('includes the verdict label and confidence value', () => {
    const output = formatTriageNote(baseEvidence());
    expect(output).toContain('THREAT');
    expect(output).toContain('0.85');
  });

  it('includes a Summary line and a Reasons section listing each reason', () => {
    const output = formatTriageNote(baseEvidence());
    expect(output).toContain('Credential-harvesting link found in message body.');
    expect(output).toContain('Sender domain not in allowlist');
    expect(output).toContain('URL matches known phishing indicator');
  });

  it('shows delivered/held/rejected/clicked counts when blast radius is ok', () => {
    const ok: BlastRadiusResult = {
      status: 'ok',
      matched: 5,
      delivered: 3,
      held: 1,
      rejected: 1,
      clicked: 2,
      perRecipient: [{ recipient: 'user@acme.example', status: 'delivered' }],
      source: 'fan-out',
    };
    const output = formatTriageNote(baseEvidence({ blastRadius: ok }));
    expect(output).toContain('3');
    expect(output).toContain('1');
    expect(output).toContain('2');
  });

  it('shows an explicit unavailable reason when blast radius is unavailable', () => {
    const output = formatTriageNote(
      baseEvidence({ blastRadius: { status: 'unavailable', reason: 'not_configured' } })
    );
    expect(output).toContain('unavailable');
    expect(output).toContain('not_configured');
  });

  it('states no action taken when remediationActions is empty', () => {
    const output = formatTriageNote(baseEvidence({ remediationActions: [] }));
    expect(output.toLowerCase()).toMatch(/proposed|no action/);
  });

  it('lists each remediation action with status and approver when present', () => {
    const output = formatTriageNote(
      baseEvidence({
        remediationActions: [
          { actionType: 'block_sender', status: 'approved', approvedBy: 'operator@example.com', approvedAt: '2026-07-01T00:00:00Z' },
          { actionType: 'purge_message', status: 'completed', approvedBy: 'operator@example.com', approvedAt: '2026-07-01T00:00:00Z' },
        ],
      })
    );
    expect(output).toContain('block_sender');
    expect(output).toContain('approved');
    expect(output).toContain('purge_message');
    expect(output).toContain('completed');
    expect(output).toContain('operator@example.com');
  });

  it('renders indicator URLs in sanitized form, dropping query strings', () => {
    const output = formatTriageNote(baseEvidence({ urls: ['http://evil.example/p?token=leak'] }));
    expect(output).not.toContain('token=leak');
    expect(output).toContain('http://evil.example/p');
  });

  it('never leaks a secret embedded in free-text fields (sanitizeNoteText applied to whole output)', () => {
    const output = formatTriageNote(
      baseEvidence({ summary: 'Found link http://evil.example/x?access_token=SECRETVALUE in body' })
    );
    expect(output).not.toContain('access_token=SECRETVALUE');
  });

  it('handles null verdict/confidence gracefully without throwing', () => {
    expect(() =>
      formatTriageNote(baseEvidence({ verdict: null, confidence: null }))
    ).not.toThrow();
    const output = formatTriageNote(baseEvidence({ verdict: null, confidence: null }));
    expect(output.toLowerCase()).toContain('not yet classified');
  });
});
