import { describe, it, expect } from 'vitest';
import {
  KNOWN_PHISHING_PATTERNS,
  matchesPhishingPatterns,
  computePhishingContentHash,
} from './phishing-detector';

describe('KNOWN_PHISHING_PATTERNS', () => {
  it('has exactly 8 locked patterns', () => {
    expect(KNOWN_PHISHING_PATTERNS).toHaveLength(8);
  });
});

describe('matchesPhishingPatterns', () => {
  it('flags a title containing "Phishing Report"', () => {
    const result = matchesPhishingPatterns('Fwd: Phishing Report', null);
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Phishing Report');
  });

  it('flags a title containing "Spam Alert"', () => {
    const result = matchesPhishingPatterns('Spam Alert - user reported', null);
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Spam Alert');
  });

  it('flags a title containing "Phishing Alert - Email Security Report"', () => {
    const result = matchesPhishingPatterns('Phishing Alert - Email Security Report', null);
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Phishing Alert - Email Security Report');
  });

  it('flags a description containing "KnowBe4 Phish Alert Report"', () => {
    const result = matchesPhishingPatterns(null, 'This is a KnowBe4 Phish Alert Report for review');
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('KnowBe4 Phish Alert Report');
  });

  it('flags a description containing "Source: KnowBe4 Phish Alert Button"', () => {
    const result = matchesPhishingPatterns(null, 'Source: KnowBe4 Phish Alert Button');
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Source: KnowBe4 Phish Alert Button');
  });

  it('flags a description containing "userSubmissionsReportMessage"', () => {
    const result = matchesPhishingPatterns(null, 'Generated by userSubmissionsReportMessage flow');
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('userSubmissionsReportMessage');
  });

  it('flags a description containing "reported message destinations"', () => {
    const result = matchesPhishingPatterns(null, 'See reported message destinations below');
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('reported message destinations');
  });

  it('flags a description containing "Microsoft directly"', () => {
    const result = matchesPhishingPatterns(null, 'This message was reported to Microsoft directly');
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Microsoft directly');
  });

  it('does not flag a ticket with none of the patterns', () => {
    const result = matchesPhishingPatterns('Re: order confirmation', 'please review invoice');
    expect(result.flagged).toBe(false);
    expect(result.matched).toEqual([]);
  });

  it('matches case-insensitively', () => {
    const result = matchesPhishingPatterns('SPAM ALERT from user', null);
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Spam Alert');
  });

  it('returns only the patterns actually present in matched[]', () => {
    const result = matchesPhishingPatterns('Phishing Report', 'unrelated body text');
    expect(result.matched).toEqual(['Phishing Report']);
  });

  it('checks both title and description for a match', () => {
    const result = matchesPhishingPatterns('Unrelated subject', 'Spam Alert triggered');
    expect(result.flagged).toBe(true);
    expect(result.matched).toContain('Spam Alert');
  });
});

describe('computePhishingContentHash', () => {
  it('is stable for identical title+description', () => {
    expect(computePhishingContentHash('t', 'd')).toBe(computePhishingContentHash('t', 'd'));
  });

  it('changes when the title changes', () => {
    expect(computePhishingContentHash('t', 'd')).not.toBe(computePhishingContentHash('t2', 'd'));
  });

  it('changes when the description changes', () => {
    expect(computePhishingContentHash('t', 'd')).not.toBe(computePhishingContentHash('t', 'd2'));
  });

  it('is defined and stable when description is null', () => {
    const hash1 = computePhishingContentHash('t', null);
    const hash2 = computePhishingContentHash('t', null);
    expect(hash1).toBeTruthy();
    expect(hash1).toBe(hash2);
  });
});
