const fc = require('fast-check');

/**
 * Property-Based Tests for Contact Method Validation
 * Feature: service-appointment-forms, Property 1: Contact Method Validation
 * Validates: Requirements 1.2
 * 
 * For any form submission attempt with empty WeChat, empty phone, and empty WhatsApp fields,
 * the form SHALL reject the submission and display a validation error.
 */

/**
 * Validates that at least one contact method is provided
 * This is a copy of the validation function from utils/form-validation.js
 * for testing purposes (to avoid UniApp dependencies in Node.js tests)
 * 
 * @param {string} wechat - WeChat ID
 * @param {string} phone - Phone number
 * @param {string} whatsapp - WhatsApp number
 * @returns {boolean} True if at least one contact method is provided
 */
function validateContactMethods(wechat, phone, whatsapp) {
  const hasWechat = wechat && typeof wechat === 'string' && wechat.trim().length > 0;
  const hasPhone = phone && typeof phone === 'string' && phone.trim().length > 0;
  const hasWhatsapp = whatsapp && typeof whatsapp === 'string' && whatsapp.trim().length > 0;
  
  return !!(hasWechat || hasPhone || hasWhatsapp);
}

describe('Contact Method Validation Property Tests', () => {
  /**
   * Feature: service-appointment-forms, Property 1: Contact Method Validation
   * For any form submission attempt with empty WeChat, empty phone, and empty WhatsApp fields,
   * the form SHALL reject the submission and display a validation error.
   * **Validates: Requirements 1.2**
   */
  describe('Property 1: Contact Method Validation', () => {
    
    test('All empty contact methods should fail validation', () => {
      fc.assert(
        fc.property(
          // Generate various forms of "empty" values
          fc.constantFrom('', null, undefined),
          fc.constantFrom('', null, undefined),
          fc.constantFrom('', null, undefined),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Whitespace-only contact methods should fail validation', () => {
      fc.assert(
        fc.property(
          fc.stringOf(fc.constantFrom(' ', '\t', '\n', '\r'), { minLength: 0, maxLength: 10 }),
          fc.stringOf(fc.constantFrom(' ', '\t', '\n', '\r'), { minLength: 0, maxLength: 10 }),
          fc.stringOf(fc.constantFrom(' ', '\t', '\n', '\r'), { minLength: 0, maxLength: 10 }),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('At least one valid WeChat should pass validation', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
          fc.constantFrom('', null, undefined, '   '),
          fc.constantFrom('', null, undefined, '   '),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('At least one valid phone should pass validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', null, undefined, '   '),
          fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0),
          fc.constantFrom('', null, undefined, '   '),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('At least one valid WhatsApp should pass validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', null, undefined, '   '),
          fc.constantFrom('', null, undefined, '   '),
          fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Multiple valid contact methods should pass validation', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
          fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0),
          fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Any combination with at least one valid contact should pass', () => {
      fc.assert(
        fc.property(
          fc.option(fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0), { nil: '' }),
          fc.option(fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0), { nil: '' }),
          fc.option(fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0), { nil: '' }),
          (wechat, phone, whatsapp) => {
            // At least one must be valid for this test
            const hasValidWechat = wechat && wechat.trim().length > 0;
            const hasValidPhone = phone && phone.trim().length > 0;
            const hasValidWhatsapp = whatsapp && whatsapp.trim().length > 0;
            
            fc.pre(hasValidWechat || hasValidPhone || hasValidWhatsapp);
            
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Non-string types should be handled gracefully', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(123, {}, [], true, false, 0),
          fc.constantFrom(123, {}, [], true, false, 0),
          fc.constantFrom(123, {}, [], true, false, 0),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            // Non-string types should be treated as invalid/empty
            expect(isValid).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Mixed valid string and invalid types should pass if string is valid', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
          fc.constantFrom(123, {}, [], true, false, 0, null, undefined),
          fc.constantFrom(123, {}, [], true, false, 0, null, undefined),
          (wechat, phone, whatsapp) => {
            const isValid = validateContactMethods(wechat, phone, whatsapp);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Realistic contact method formats should pass validation', () => {
      fc.assert(
        fc.property(
          // WeChat IDs: alphanumeric, 6-20 chars
          fc.stringOf(fc.constantFrom(...'abcdefghijklmnopqrstuvwxyz0123456789_'), { minLength: 6, maxLength: 20 }),
          // Phone numbers: digits with optional country code
          fc.tuple(
            fc.constantFrom('+86', '+1', '+44', '+55', '+52', ''),
            fc.stringOf(fc.constantFrom(...'0123456789'), { minLength: 10, maxLength: 11 })
          ).map(([code, num]) => code + num),
          // WhatsApp: similar to phone
          fc.stringOf(fc.constantFrom(...'0123456789'), { minLength: 10, maxLength: 15 }),
          (wechat, phone, whatsapp) => {
            // Test with just wechat
            expect(validateContactMethods(wechat, '', '')).toBe(true);
            // Test with just phone
            expect(validateContactMethods('', phone, '')).toBe(true);
            // Test with just whatsapp
            expect(validateContactMethods('', '', whatsapp)).toBe(true);
            // Test with all
            expect(validateContactMethods(wechat, phone, whatsapp)).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });
  });
});
