import { describe, expect, test } from 'bun:test';
import { checkUrlTargeting, testRegex } from './url-match';

describe('testRegex', () => {
  test('returns true for matching regex', () => {
    expect(testRegex('hello', 'hello world')).toBe(true);
    expect(testRegex('^https://', 'https://example.com')).toBe(true);
    expect(testRegex('/products/\\d+', '/products/123')).toBe(true);
  });

  test('returns false for non-matching regex', () => {
    expect(testRegex('^https://', 'http://example.com')).toBe(false);
    expect(testRegex('/products/\\d+$', '/products/abc')).toBe(false);
  });

  test('returns false for invalid regex', () => {
    expect(testRegex('[invalid', 'test')).toBe(false);
    expect(testRegex('(unclosed', 'test')).toBe(false);
  });
});

describe('checkUrlTargeting', () => {
  describe('empty targeting', () => {
    test('returns true for empty targeting array', () => {
      expect(checkUrlTargeting([], 'https://example.com')).toBe(true);
    });
  });

  describe('equals condition', () => {
    test('matches exact URL', () => {
      const targeting = [{ url: 'https://example.com/page', condition: 'equals' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true);
    });

    test('does not match different URL', () => {
      const targeting = [{ url: 'https://example.com/page', condition: 'equals' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/other')).toBe(false);
    });

    test('ignores trailing slashes', () => {
      const targeting = [{ url: 'https://example.com/page/', condition: 'equals' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true);
    });
  });

  describe('not equals condition', () => {
    test('matches when URL is different', () => {
      const targeting = [{ url: 'https://example.com/page', condition: 'not equals' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/other')).toBe(true);
    });

    test('does not match when URL is same', () => {
      const targeting = [{ url: 'https://example.com/page', condition: 'not equals' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false);
    });
  });

  describe('contains condition', () => {
    test('matches when URL contains substring', () => {
      const targeting = [{ url: 'example', condition: 'contains' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true);
    });

    test('matches partial path', () => {
      const targeting = [{ url: '/products/', condition: 'contains' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/products/123')).toBe(true);
    });

    test('does not match when substring not present', () => {
      const targeting = [{ url: 'foobar', condition: 'contains' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false);
    });
  });

  describe('does not contain condition', () => {
    test('matches when URL does not contain substring', () => {
      const targeting = [{ url: 'admin', condition: 'does not contain' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true);
    });

    test('does not match when URL contains substring', () => {
      const targeting = [{ url: 'example', condition: 'does not contain' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false);
    });
  });

  describe('starts with condition', () => {
    test('matches URL starting with prefix', () => {
      const targeting = [{ url: 'https://example.com', condition: 'starts with' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true);
    });

    test('does not match URL with different start', () => {
      const targeting = [{ url: 'https://other.com', condition: 'starts with' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false);
    });
  });

  describe('ends with condition', () => {
    test('matches URL ending with suffix', () => {
      const targeting = [{ url: '/checkout', condition: 'ends with' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/checkout')).toBe(true);
    });

    test('does not match URL with different ending', () => {
      const targeting = [{ url: '/checkout', condition: 'ends with' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/cart')).toBe(false);
    });
  });

  describe('matches regex condition', () => {
    test('matches valid regex pattern', () => {
      const targeting = [{ url: '/products/\\d+', condition: 'matches regex' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/products/123')).toBe(true);
    });

    test('does not match non-matching pattern', () => {
      const targeting = [{ url: '/products/\\d+$', condition: 'matches regex' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/products/abc')).toBe(false);
    });

    test('handles invalid regex gracefully', () => {
      const targeting = [{ url: '[invalid', condition: 'matches regex' as const }];
      expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false);
    });
  });

  describe('multiple targeting rules', () => {
    test('returns true if any rule matches (OR logic)', () => {
      const targeting = [
        { url: '/admin', condition: 'contains' as const },
        { url: '/dashboard', condition: 'contains' as const },
      ];
      expect(checkUrlTargeting(targeting, 'https://example.com/dashboard')).toBe(true);
    });

    test('returns false if no rules match', () => {
      const targeting = [
        { url: '/admin', condition: 'contains' as const },
        { url: '/dashboard', condition: 'contains' as const },
      ];
      expect(checkUrlTargeting(targeting, 'https://example.com/home')).toBe(false);
    });

    test('first matching rule short-circuits', () => {
      const targeting = [
        { url: 'example', condition: 'contains' as const },
        { url: '[invalid', condition: 'matches regex' as const }, // invalid, but won't be checked
      ];
      expect(checkUrlTargeting(targeting, 'https://example.com')).toBe(true);
    });
  });
});
