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

/**
 * Property-Based Tests for Service Appointment Forms
 * Feature: service-appointment-forms, Property 8: API Data Structure
 * Validates: Requirements 18.1
 * 
 * For any valid form submission, the data sent to the API SHALL include 
 * the correct serviceType identifier and all service-specific fields.
 */

// Service type to required fields mapping based on design document
const SERVICE_TYPE_FIELDS = {
  hotel: {
    category: 'accommodation',
    requiredFields: ['checkInDate', 'checkOutDate', 'countryCity', 'hotelName', 'roomCount', 'roomType'],
    optionalFields: ['needMeal', 'mealPlan'],
  },
  vip_lounge: {
    category: 'travel',
    requiredFields: ['appointmentDate', 'airportTerminal'],
    optionalFields: ['arrivalFlightNo', 'departureFlightNo', 'adultCount', 'childCount'],
  },
  airport_transfer: {
    category: 'travel',
    requiredFields: ['appointmentDate', 'airportTerminal', 'deliveryAddress'],
    optionalFields: ['passengerCount', 'luggageCount'],
  },
  unaccompanied_minor: {
    category: 'other',
    requiredFields: ['appointmentDate', 'itinerary'],
    optionalFields: ['childAge', 'boyCount', 'girlCount'],
  },
  rail_ticket: {
    category: 'travel',
    requiredFields: ['departureDate', 'originStation', 'destinationStation'],
    optionalFields: ['seatClass', 'passengerCount'],
  },
  medical_consultation: {
    category: 'other',
    requiredFields: ['appointmentDate', 'hospitalName'],
    optionalFields: ['itinerary', 'conditionDescription'],
  },
  special_needs: {
    category: 'other',
    requiredFields: ['appointmentDate', 'itinerary'],
    optionalFields: ['specialAssistanceReason'],
  },
  pet_transportation: {
    category: 'other',
    requiredFields: ['origin', 'destination', 'departureDate', 'petType'],
    optionalFields: ['flightNo', 'petName', 'hasQuarantineCert'],
  },
  guide_translation: {
    category: 'guide_translation',
    requiredFields: ['appointmentDate'],
    optionalFields: ['serviceDays'],
  },
  visa_consultation: {
    category: 'consulting',
    requiredFields: ['specificRequirements'],
    optionalFields: [],
  },
  exhibition_service: {
    category: 'consulting',
    requiredFields: ['specificRequirements'],
    optionalFields: [],
  },
  air_logistics: {
    category: 'other',
    requiredFields: ['origin', 'destination', 'itemName'],
    optionalFields: ['itemQuantity'],
  },
  sea_freight: {
    category: 'other',
    requiredFields: ['originPort', 'destinationPort', 'cargoName'],
    optionalFields: ['cargoQuantity'],
  },
  travel_planning: {
    category: 'guide_consulting',
    requiredFields: ['travelDate', 'origin', 'travelDestination'],
    optionalFields: ['travelDays', 'passengerCount'],
  },
  insurance_consultation: {
    category: 'consulting',
    requiredFields: ['specificRequirements'],
    optionalFields: [],
  },
};

// Common fields required for all appointment types
const COMMON_FIELDS = ['realName', 'serviceType'];
const CONTACT_FIELDS = ['wechatId', 'phone', 'whatsapp'];

/**
 * Validates that an appointment data object has the correct structure
 * for its service type
 */
function validateAppointmentStructure(data) {
  // Must have serviceType
  if (!data.serviceType) {
    return { valid: false, reason: 'Missing serviceType' };
  }

  // ServiceType must be known
  const serviceConfig = SERVICE_TYPE_FIELDS[data.serviceType];
  if (!serviceConfig) {
    return { valid: false, reason: `Unknown serviceType: ${data.serviceType}` };
  }

  // Must have realName
  if (!data.realName || typeof data.realName !== 'string' || data.realName.trim() === '') {
    return { valid: false, reason: 'Missing or invalid realName' };
  }

  // Must have at least one contact method
  const hasContact = CONTACT_FIELDS.some(field => 
    data[field] && typeof data[field] === 'string' && data[field].trim() !== ''
  );
  if (!hasContact) {
    return { valid: false, reason: 'Must have at least one contact method' };
  }

  // Check all required fields for this service type are present
  for (const field of serviceConfig.requiredFields) {
    if (data[field] === undefined || data[field] === null || data[field] === '') {
      return { valid: false, reason: `Missing required field: ${field}` };
    }
  }

  return { valid: true };
}

/**
 * Generates a valid appointment data object for a given service type
 */
function generateAppointmentData(serviceType, overrides = {}) {
  const config = SERVICE_TYPE_FIELDS[serviceType];
  if (!config) {
    throw new Error(`Unknown service type: ${serviceType}`);
  }

  const baseData = {
    serviceType,
    realName: 'Test User',
    wechatId: 'test_wechat',
    phone: '13800138000',
    phoneCountryCode: '+86',
    whatsapp: '',
    notes: '',
  };

  // Add required fields with default values
  const fieldDefaults = {
    checkInDate: '2025-01-15',
    checkOutDate: '2025-01-20',
    countryCity: 'Beijing, China',
    hotelName: 'Test Hotel',
    roomCount: 1,
    roomType: 'Standard',
    appointmentDate: '2025-01-15',
    airportTerminal: 'Beijing Capital T3',
    deliveryAddress: '123 Test Street',
    itinerary: 'Beijing - Shanghai',
    departureDate: '2025-01-15',
    originStation: 'Beijing South',
    destinationStation: 'Shanghai Hongqiao',
    hospitalName: 'Test Hospital',
    origin: 'Beijing',
    destination: 'Shanghai',
    petType: 'Dog',
    specificRequirements: 'Test requirements',
    itemName: 'Test Item',
    originPort: 'Shanghai Port',
    destinationPort: 'Los Angeles Port',
    cargoName: 'Test Cargo',
    travelDate: '2025-01-15',
    travelDestination: 'Paris',
  };

  for (const field of config.requiredFields) {
    if (fieldDefaults[field] !== undefined) {
      baseData[field] = fieldDefaults[field];
    }
  }

  return { ...baseData, ...overrides };
}

/**
 * Validates passenger count for forms that require at least one passenger
 * Feature: service-appointment-forms, Property 3: Passenger Count Validation
 * Validates: Requirements 3.3, 5.3
 * 
 * For any form requiring passenger selection (VIP lounge, airport transfer, 
 * unaccompanied minor, travel planning), if total passenger count is zero, 
 * the form SHALL reject the submission.
 */
function validatePassengerCount(passengerCounts) {
  // passengerCounts is an object with count fields like { adultCount, childCount, infantCount, boyCount, girlCount }
  const countFields = ['adultCount', 'childCount', 'infantCount', 'boyCount', 'girlCount', 'passengerCount'];
  
  let totalCount = 0;
  for (const field of countFields) {
    if (typeof passengerCounts[field] === 'number' && passengerCounts[field] >= 0) {
      totalCount += passengerCounts[field];
    }
  }
  
  return totalCount > 0;
}

// Service types that require passenger count validation
const PASSENGER_REQUIRED_SERVICES = ['vip_lounge', 'airport_transfer', 'unaccompanied_minor', 'travel_planning'];

describe('Appointment Form Property Tests', () => {
  /**
   * Feature: service-appointment-forms, Property 8: API Data Structure
   * For any valid form submission, the data sent to the API SHALL include 
   * the correct serviceType identifier and all service-specific fields.
   */
  describe('Property 8: API Data Structure', () => {
    test('Valid appointment data should pass structure validation for all service types', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.option(fc.string({ minLength: 1, maxLength: 100 }), { nil: undefined }),
            phone: fc.option(fc.string({ minLength: 1, maxLength: 50 }), { nil: undefined }),
            whatsapp: fc.option(fc.string({ minLength: 1, maxLength: 50 }), { nil: undefined }),
          }).filter(contact => 
            // At least one contact method must be provided
            (contact.wechatId && contact.wechatId.trim()) || 
            (contact.phone && contact.phone.trim()) || 
            (contact.whatsapp && contact.whatsapp.trim())
          ),
          (serviceType, contactInfo) => {
            // Generate valid appointment data for this service type
            const appointmentData = generateAppointmentData(serviceType, {
              realName: contactInfo.realName,
              wechatId: contactInfo.wechatId || '',
              phone: contactInfo.phone || '',
              whatsapp: contactInfo.whatsapp || '',
            });

            // Validate the structure
            const result = validateAppointmentStructure(appointmentData);
            
            expect(result.valid).toBe(true);
            expect(appointmentData.serviceType).toBe(serviceType);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Appointment data without serviceType should fail validation', () => {
      fc.assert(
        fc.property(
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }),
          }),
          (data) => {
            const result = validateAppointmentStructure(data);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('Missing serviceType');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Appointment data with unknown serviceType should fail validation', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 1, maxLength: 50 }).filter(s => !SERVICE_TYPE_FIELDS[s]),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }),
          }),
          (unknownType, data) => {
            const appointmentData = { ...data, serviceType: unknownType };
            const result = validateAppointmentStructure(appointmentData);
            expect(result.valid).toBe(false);
            expect(result.reason).toContain('Unknown serviceType');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Appointment data without any contact method should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
          (serviceType, realName) => {
            const appointmentData = generateAppointmentData(serviceType, {
              realName,
              wechatId: '',
              phone: '',
              whatsapp: '',
            });

            const result = validateAppointmentStructure(appointmentData);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('Must have at least one contact method');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Each service type should have correct category mapping', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          (serviceType) => {
            const config = SERVICE_TYPE_FIELDS[serviceType];
            
            // Category should be one of the valid categories
            const validCategories = ['accommodation', 'travel', 'other', 'guide_translation', 'consulting', 'guide_consulting'];
            expect(validCategories).toContain(config.category);
            
            // Required fields should be an array
            expect(Array.isArray(config.requiredFields)).toBe(true);
            
            // Optional fields should be an array
            expect(Array.isArray(config.optionalFields)).toBe(true);
          }
        ),
        { numRuns: 15 } // One run per service type
      );
    });

    test('Missing required fields should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS).filter(
            type => SERVICE_TYPE_FIELDS[type].requiredFields.length > 0
          )),
          (serviceType) => {
            const config = SERVICE_TYPE_FIELDS[serviceType];
            
            // Create data with one required field missing
            const appointmentData = generateAppointmentData(serviceType);
            const fieldToRemove = config.requiredFields[0];
            delete appointmentData[fieldToRemove];

            const result = validateAppointmentStructure(appointmentData);
            expect(result.valid).toBe(false);
            expect(result.reason).toContain('Missing required field');
          }
        ),
        { numRuns: 50 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 3: Passenger Count Validation
   * For any form requiring passenger selection (VIP lounge, airport transfer, 
   * unaccompanied minor, travel planning), if total passenger count is zero, 
   * the form SHALL reject the submission.
   * **Validates: Requirements 3.3, 5.3**
   */
  describe('Property 3: Passenger Count Validation', () => {
    test('Zero passenger count should fail validation for passenger-required services', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...PASSENGER_REQUIRED_SERVICES),
          (serviceType) => {
            // Create passenger counts that are all zero
            const passengerCounts = {
              adultCount: 0,
              childCount: 0,
              infantCount: 0,
              boyCount: 0,
              girlCount: 0,
              passengerCount: 0,
            };

            const isValid = validatePassengerCount(passengerCounts);
            expect(isValid).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('At least one passenger should pass validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...PASSENGER_REQUIRED_SERVICES),
          fc.record({
            adultCount: fc.nat({ max: 10 }),
            childCount: fc.nat({ max: 10 }),
            infantCount: fc.nat({ max: 5 }),
            boyCount: fc.nat({ max: 5 }),
            girlCount: fc.nat({ max: 5 }),
          }).filter(counts => 
            // At least one count must be > 0
            counts.adultCount > 0 || counts.childCount > 0 || 
            counts.infantCount > 0 || counts.boyCount > 0 || counts.girlCount > 0
          ),
          (serviceType, passengerCounts) => {
            const isValid = validatePassengerCount(passengerCounts);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Negative passenger counts should not contribute to total', () => {
      fc.assert(
        fc.property(
          fc.record({
            adultCount: fc.integer({ min: -10, max: 0 }),
            childCount: fc.integer({ min: -10, max: 0 }),
          }),
          (passengerCounts) => {
            // Negative counts should be treated as 0, so total should be 0
            const isValid = validatePassengerCount(passengerCounts);
            expect(isValid).toBe(false);
          }
        ),
        { numRuns: 50 }
      );
    });

    test('VIP lounge form with adults and children should pass validation', () => {
      fc.assert(
        fc.property(
          fc.nat({ max: 10 }),
          fc.nat({ max: 10 }),
          (adultCount, childCount) => {
            // Skip if both are zero (that's the failure case)
            fc.pre(adultCount > 0 || childCount > 0);
            
            const passengerCounts = { adultCount, childCount };
            const isValid = validatePassengerCount(passengerCounts);
            expect(isValid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 4: Required Field Validation
   * For any form submission, if any required field is empty or contains only whitespace,
   * the form SHALL reject the submission and scroll to the first invalid field.
   * **Validates: Requirements 4.3, 6.3, 7.3, 8.3, 9.3, 10.3, 13.3, 14.3, 15.3**
   */
  describe('Property 4: Required Field Validation', () => {
    /**
     * Validates required fields for airport transfer form
     * Required fields: date, airport name, delivery address, passenger count, luggage count
     */
    function validateAirportTransferRequiredFields(formData) {
      const errors = [];
      
      // Real name is required
      if (!formData.realName || typeof formData.realName !== 'string' || formData.realName.trim() === '') {
        errors.push({ field: 'userName', message: '请输入真实姓名' });
      }
      
      // At least one contact method required
      const hasContact = 
        (formData.wechatId && formData.wechatId.trim()) ||
        (formData.phone && formData.phone.trim()) ||
        (formData.whatsapp && formData.whatsapp.trim());
      if (!hasContact) {
        errors.push({ field: 'contact', message: '请至少填写一种联系方式' });
      }
      
      // Reservation date is required
      if (!formData.reservationDate || formData.reservationDate.trim() === '') {
        errors.push({ field: 'reservationDate', message: '请选择预约日期' });
      }
      
      // Airport name is required
      if (!formData.airportName || typeof formData.airportName !== 'string' || formData.airportName.trim() === '') {
        errors.push({ field: 'airportName', message: '请输入机场名称' });
      }
      
      // Delivery address is required
      if (!formData.deliveryAddress || typeof formData.deliveryAddress !== 'string' || formData.deliveryAddress.trim() === '') {
        errors.push({ field: 'deliveryAddress', message: '请输入送达地址' });
      }
      
      // Passenger count must be > 0
      if (typeof formData.passengerCount !== 'number' || formData.passengerCount <= 0) {
        errors.push({ field: 'passengerCount', message: '请至少选择一位乘客' });
      }
      
      // Luggage count is required
      if (formData.luggageCount === undefined || formData.luggageCount === null || formData.luggageCount === '') {
        errors.push({ field: 'luggageCount', message: '请输入行李件数' });
      }
      
      return {
        valid: errors.length === 0,
        errors,
        firstError: errors.length > 0 ? errors[0] : null
      };
    }

    test('Airport transfer form with all required fields should pass validation', () => {
      fc.assert(
        fc.property(
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            phone: fc.string({ minLength: 0, maxLength: 50 }),
            whatsapp: fc.string({ minLength: 0, maxLength: 50 }),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20', '2025-06-10'),
            airportName: fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
            deliveryAddress: fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0),
            passengerCount: fc.integer({ min: 1, max: 20 }),
            luggageCount: fc.integer({ min: 0, max: 50 }),
          }),
          (formData) => {
            const result = validateAirportTransferRequiredFields(formData);
            expect(result.valid).toBe(true);
            expect(result.errors).toHaveLength(0);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Airport transfer form with empty realName should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', '   ', '\t', '\n'),
          fc.record({
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20'),
            airportName: fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
            deliveryAddress: fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0),
            passengerCount: fc.integer({ min: 1, max: 20 }),
            luggageCount: fc.integer({ min: 0, max: 50 }),
          }),
          (emptyName, formData) => {
            const data = { ...formData, realName: emptyName };
            const result = validateAirportTransferRequiredFields(data);
            expect(result.valid).toBe(false);
            expect(result.firstError.field).toBe('userName');
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Airport transfer form with no contact method should fail validation', () => {
      fc.assert(
        fc.property(
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20'),
            airportName: fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
            deliveryAddress: fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0),
            passengerCount: fc.integer({ min: 1, max: 20 }),
            luggageCount: fc.integer({ min: 0, max: 50 }),
          }),
          (formData) => {
            // Set all contact methods to empty
            const data = { ...formData, wechatId: '', phone: '', whatsapp: '' };
            const result = validateAirportTransferRequiredFields(data);
            expect(result.valid).toBe(false);
            expect(result.errors.some(e => e.field === 'contact')).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Airport transfer form with empty airport name should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', '   ', '\t', '\n'),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20'),
            deliveryAddress: fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0),
            passengerCount: fc.integer({ min: 1, max: 20 }),
            luggageCount: fc.integer({ min: 0, max: 50 }),
          }),
          (emptyAirport, formData) => {
            const data = { ...formData, airportName: emptyAirport };
            const result = validateAirportTransferRequiredFields(data);
            expect(result.valid).toBe(false);
            expect(result.errors.some(e => e.field === 'airportName')).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Airport transfer form with empty delivery address should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', '   ', '\t', '\n'),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20'),
            airportName: fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
            passengerCount: fc.integer({ min: 1, max: 20 }),
            luggageCount: fc.integer({ min: 0, max: 50 }),
          }),
          (emptyAddress, formData) => {
            const data = { ...formData, deliveryAddress: emptyAddress };
            const result = validateAirportTransferRequiredFields(data);
            expect(result.valid).toBe(false);
            expect(result.errors.some(e => e.field === 'deliveryAddress')).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Airport transfer form with zero passenger count should fail validation', () => {
      fc.assert(
        fc.property(
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20'),
            airportName: fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
            deliveryAddress: fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0),
            luggageCount: fc.integer({ min: 0, max: 50 }),
          }),
          (formData) => {
            const data = { ...formData, passengerCount: 0 };
            const result = validateAirportTransferRequiredFields(data);
            expect(result.valid).toBe(false);
            expect(result.errors.some(e => e.field === 'passengerCount')).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Airport transfer form with missing luggage count should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(undefined, null, ''),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            reservationDate: fc.constantFrom('2025-01-15', '2025-02-20'),
            airportName: fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
            deliveryAddress: fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0),
            passengerCount: fc.integer({ min: 1, max: 20 }),
          }),
          (emptyLuggage, formData) => {
            const data = { ...formData, luggageCount: emptyLuggage };
            const result = validateAirportTransferRequiredFields(data);
            expect(result.valid).toBe(false);
            expect(result.errors.some(e => e.field === 'luggageCount')).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Whitespace-only strings should be treated as empty for required fields', () => {
      fc.assert(
        fc.property(
          fc.stringOf(fc.constantFrom(' ', '\t', '\n', '\r'), { minLength: 1, maxLength: 10 }),
          (whitespaceString) => {
            const formData = {
              realName: whitespaceString,
              wechatId: 'valid_wechat',
              reservationDate: '2025-01-15',
              airportName: 'Valid Airport',
              deliveryAddress: 'Valid Address',
              passengerCount: 1,
              luggageCount: 1,
            };
            const result = validateAirportTransferRequiredFields(formData);
            expect(result.valid).toBe(false);
            expect(result.firstError.field).toBe('userName');
          }
        ),
        { numRuns: 100 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 2: Date Range Validation
   * For any hotel reservation form where check-out date is earlier than check-in date,
   * the form SHALL reject the submission and display a validation error.
   * **Validates: Requirements 2.5**
   */
  describe('Property 2: Date Range Validation', () => {
    /**
     * Validates date range for hotel reservation form
     * Check-out date must be >= check-in date
     */
    function validateDateRange(checkInDate, checkOutDate) {
      if (!checkInDate || !checkOutDate) {
        return { valid: false, reason: 'Both dates are required' };
      }
      
      const checkIn = new Date(checkInDate);
      const checkOut = new Date(checkOutDate);
      
      if (isNaN(checkIn.getTime()) || isNaN(checkOut.getTime())) {
        return { valid: false, reason: 'Invalid date format' };
      }
      
      if (checkOut < checkIn) {
        return { valid: false, reason: '退房日期不能早于入住日期' };
      }
      
      return { valid: true };
    }

    /**
     * Generates a valid date string in YYYY-MM-DD format
     */
    function generateDateString(year, month, day) {
      const y = String(year).padStart(4, '0');
      const m = String(month).padStart(2, '0');
      const d = String(day).padStart(2, '0');
      return `${y}-${m}-${d}`;
    }

    test('Check-out date earlier than check-in date should fail validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 2024, max: 2027 }),
          fc.integer({ min: 1, max: 12 }),
          fc.integer({ min: 1, max: 28 }),
          fc.integer({ min: 1, max: 10 }),
          (year, month, checkInDay, daysBefore) => {
            // Ensure check-out is before check-in
            const checkOutDay = Math.max(1, checkInDay - daysBefore);
            fc.pre(checkOutDay < checkInDay);
            
            const checkInDate = generateDateString(year, month, checkInDay);
            const checkOutDate = generateDateString(year, month, checkOutDay);
            
            const result = validateDateRange(checkInDate, checkOutDate);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('退房日期不能早于入住日期');
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Check-out date same as check-in date should pass validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 2024, max: 2027 }),
          fc.integer({ min: 1, max: 12 }),
          fc.integer({ min: 1, max: 28 }),
          (year, month, day) => {
            const date = generateDateString(year, month, day);
            
            const result = validateDateRange(date, date);
            expect(result.valid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Check-out date after check-in date should pass validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 2024, max: 2027 }),
          fc.integer({ min: 1, max: 12 }),
          fc.integer({ min: 1, max: 20 }),
          fc.integer({ min: 1, max: 8 }),
          (year, month, checkInDay, daysAfter) => {
            const checkOutDay = checkInDay + daysAfter;
            fc.pre(checkOutDay <= 28);
            
            const checkInDate = generateDateString(year, month, checkInDay);
            const checkOutDate = generateDateString(year, month, checkOutDay);
            
            const result = validateDateRange(checkInDate, checkOutDate);
            expect(result.valid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Missing check-in date should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', null, undefined),
          fc.constantFrom('2025-01-15', '2025-02-20', '2025-06-10'),
          (emptyCheckIn, checkOutDate) => {
            const result = validateDateRange(emptyCheckIn, checkOutDate);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('Both dates are required');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Missing check-out date should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('2025-01-15', '2025-02-20', '2025-06-10'),
          fc.constantFrom('', null, undefined),
          (checkInDate, emptyCheckOut) => {
            const result = validateDateRange(checkInDate, emptyCheckOut);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('Both dates are required');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Check-out in different month after check-in should pass validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 2024, max: 2027 }),
          fc.integer({ min: 1, max: 11 }),
          fc.integer({ min: 1, max: 28 }),
          fc.integer({ min: 1, max: 28 }),
          (year, checkInMonth, checkInDay, checkOutDay) => {
            const checkOutMonth = checkInMonth + 1;
            
            const checkInDate = generateDateString(year, checkInMonth, checkInDay);
            const checkOutDate = generateDateString(year, checkOutMonth, checkOutDay);
            
            const result = validateDateRange(checkInDate, checkOutDate);
            expect(result.valid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 10: Conditional Field Display
   * For any hotel reservation form, when meal requirement is set to "Yes", 
   * meal plan options SHALL be visible; when set to "No", meal plan options SHALL be hidden.
   * **Validates: Requirements 2.3, 2.4**
   */
  describe('Property 10: Conditional Field Display', () => {
    /**
     * Simulates the conditional field display logic for hotel reservation form
     * Returns the visibility state of the meal plan field
     */
    function getMealPlanVisibility(needMeal) {
      return needMeal === true;
    }

    /**
     * Validates hotel reservation form with conditional meal plan field
     */
    function validateHotelFormWithMealPlan(formData) {
      const errors = [];
      
      // If needMeal is true, mealPlan is required
      if (formData.needMeal === true) {
        if (!formData.mealPlan || formData.mealPlan.trim() === '') {
          errors.push({ field: 'mealPlan', message: '请选择用餐方案' });
        }
      }
      
      return {
        valid: errors.length === 0,
        errors,
        mealPlanVisible: getMealPlanVisibility(formData.needMeal)
      };
    }

    test('When needMeal is true, meal plan field should be visible', () => {
      fc.assert(
        fc.property(
          fc.boolean().filter(b => b === true),
          (needMeal) => {
            const visibility = getMealPlanVisibility(needMeal);
            expect(visibility).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('When needMeal is false, meal plan field should be hidden', () => {
      fc.assert(
        fc.property(
          fc.boolean().filter(b => b === false),
          (needMeal) => {
            const visibility = getMealPlanVisibility(needMeal);
            expect(visibility).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('When needMeal is true and mealPlan is empty, validation should fail', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', '   ', null, undefined),
          (emptyMealPlan) => {
            const formData = {
              needMeal: true,
              mealPlan: emptyMealPlan || ''
            };
            const result = validateHotelFormWithMealPlan(formData);
            expect(result.valid).toBe(false);
            expect(result.mealPlanVisible).toBe(true);
            expect(result.errors.some(e => e.field === 'mealPlan')).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('When needMeal is true and mealPlan is provided, validation should pass', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('breakfast', 'three_meals', 'all_inclusive'),
          (mealPlan) => {
            const formData = {
              needMeal: true,
              mealPlan: mealPlan
            };
            const result = validateHotelFormWithMealPlan(formData);
            expect(result.valid).toBe(true);
            expect(result.mealPlanVisible).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('When needMeal is false, mealPlan is not required and validation should pass', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', null, undefined, 'breakfast', 'three_meals'),
          (mealPlan) => {
            const formData = {
              needMeal: false,
              mealPlan: mealPlan || ''
            };
            const result = validateHotelFormWithMealPlan(formData);
            expect(result.valid).toBe(true);
            expect(result.mealPlanVisible).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Meal plan visibility should toggle correctly with needMeal changes', () => {
      fc.assert(
        fc.property(
          fc.array(fc.boolean(), { minLength: 1, maxLength: 10 }),
          (needMealSequence) => {
            // Simulate toggling needMeal multiple times
            for (const needMeal of needMealSequence) {
              const visibility = getMealPlanVisibility(needMeal);
              expect(visibility).toBe(needMeal);
            }
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Valid meal plan options should be accepted when needMeal is true', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('breakfast', 'three_meals', 'all_inclusive'),
          (mealPlan) => {
            const validMealPlans = ['breakfast', 'three_meals', 'all_inclusive'];
            expect(validMealPlans).toContain(mealPlan);
            
            const formData = {
              needMeal: true,
              mealPlan: mealPlan
            };
            const result = validateHotelFormWithMealPlan(formData);
            expect(result.valid).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 5: Text Input Acceptance
   * For any text input field (remarks, address, description, requirements), 
   * the field SHALL accept and preserve any valid string input including multi-line text.
   * **Validates: Requirements 1.4, 4.2, 7.2, 8.2, 11.2, 12.2, 16.2**
   */
  describe('Property 5: Text Input Acceptance', () => {
    /**
     * Validates and preserves text input for textarea fields
     * Returns the processed text that would be stored
     */
    function processTextInput(input) {
      if (input === null || input === undefined) {
        return { valid: true, value: '', preserved: true };
      }
      
      if (typeof input !== 'string') {
        return { valid: false, value: null, preserved: false, reason: 'Input must be a string' };
      }
      
      // Text input should preserve the original content including whitespace and newlines
      // Only trim for validation purposes, but preserve original for storage
      return { 
        valid: true, 
        value: input, 
        preserved: true,
        trimmedValue: input.trim()
      };
    }

    /**
     * Validates condition description field for medical consultation form
     * Requirement 7.2: Accept multi-line text input
     */
    function validateConditionDescription(description) {
      const result = processTextInput(description);
      
      if (!result.valid) {
        return result;
      }
      
      // For required fields, trimmed value must not be empty
      if (result.trimmedValue === '') {
        return { 
          valid: false, 
          value: result.value, 
          preserved: true,
          reason: '请输入病情描述'
        };
      }
      
      return result;
    }

    /**
     * Validates that multi-line text is properly accepted and preserved
     */
    function validateMultiLineText(text) {
      const result = processTextInput(text);
      
      if (!result.valid) {
        return result;
      }
      
      // Check if newlines are preserved
      const hasNewlines = text && text.includes('\n');
      const newlinesPreserved = hasNewlines ? result.value.includes('\n') : true;
      
      return {
        ...result,
        hasNewlines,
        newlinesPreserved
      };
    }

    test('Single-line text input should be accepted and preserved', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 1, maxLength: 500 }).filter(s => s.trim().length > 0 && !s.includes('\n')),
          (text) => {
            const result = processTextInput(text);
            expect(result.valid).toBe(true);
            expect(result.value).toBe(text);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Multi-line text input should be accepted and preserve newlines', () => {
      fc.assert(
        fc.property(
          fc.array(
            fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            { minLength: 2, maxLength: 5 }
          ),
          (lines) => {
            const multiLineText = lines.join('\n');
            const result = validateMultiLineText(multiLineText);
            
            expect(result.valid).toBe(true);
            expect(result.value).toBe(multiLineText);
            expect(result.preserved).toBe(true);
            expect(result.hasNewlines).toBe(true);
            expect(result.newlinesPreserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Text with special characters should be accepted and preserved', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0),
          (text) => {
            const result = processTextInput(text);
            expect(result.valid).toBe(true);
            expect(result.value).toBe(text);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Text with Unicode characters (Chinese, emoji) should be accepted and preserved', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(
            '这是中文描述',
            '病情描述：头痛、发烧',
            '需要咨询关于签证的问题',
            '我需要预约医疗服务\n详细描述如下',
            '特殊需求：轮椅服务',
            '货物名称：电子产品\n数量：100件',
            '旅行计划：北京→上海→广州'
          ),
          (text) => {
            const result = processTextInput(text);
            expect(result.valid).toBe(true);
            expect(result.value).toBe(text);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Condition description with valid multi-line text should pass validation', () => {
      fc.assert(
        fc.property(
          fc.array(
            fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            { minLength: 1, maxLength: 5 }
          ),
          (lines) => {
            const description = lines.join('\n');
            const result = validateConditionDescription(description);
            
            expect(result.valid).toBe(true);
            expect(result.value).toBe(description);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Empty condition description should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', '   ', '\t', '\n', '\r\n', '  \n  '),
          (emptyDescription) => {
            const result = validateConditionDescription(emptyDescription);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('请输入病情描述');
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Text input should preserve leading and trailing whitespace in value', () => {
      fc.assert(
        fc.property(
          // Content must not start or end with whitespace (so we can test adding whitespace separately)
          fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0 && s === s.trim()),
          fc.stringOf(fc.constantFrom(' ', '\t'), { minLength: 0, maxLength: 3 }),
          fc.stringOf(fc.constantFrom(' ', '\t'), { minLength: 0, maxLength: 3 }),
          (content, leadingSpace, trailingSpace) => {
            const textWithSpaces = leadingSpace + content + trailingSpace;
            const result = processTextInput(textWithSpaces);
            
            expect(result.valid).toBe(true);
            expect(result.value).toBe(textWithSpaces);
            expect(result.trimmedValue).toBe(content);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Null and undefined inputs should be handled gracefully', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(null, undefined),
          (nullishValue) => {
            const result = processTextInput(nullishValue);
            expect(result.valid).toBe(true);
            expect(result.value).toBe('');
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Long text input should be accepted up to reasonable limits', () => {
      fc.assert(
        fc.property(
          fc.string({ minLength: 500, maxLength: 1000 }).filter(s => s.trim().length > 0),
          (longText) => {
            const result = processTextInput(longText);
            expect(result.valid).toBe(true);
            expect(result.value).toBe(longText);
            expect(result.value.length).toBe(longText.length);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Text with mixed content (text, numbers, symbols) should be preserved', () => {
      fc.assert(
        fc.property(
          fc.record({
            text: fc.string({ minLength: 1, maxLength: 50 }).filter(s => s.trim().length > 0),
            number: fc.integer({ min: 1, max: 9999 }),
            symbol: fc.constantFrom('!', '@', '#', '$', '%', '&', '*', '-', '+', '=')
          }),
          ({ text, number, symbol }) => {
            const mixedContent = `${text} ${symbol} ${number}`;
            const result = processTextInput(mixedContent);
            
            expect(result.valid).toBe(true);
            expect(result.value).toBe(mixedContent);
            expect(result.preserved).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 6: Numeric Input Validation
   * For any numeric input field (days, quantity, count), the field SHALL only 
   * accept valid positive integer values.
   * **Validates: Requirements 10.2, 13.2, 14.2, 15.2**
   */
  describe('Property 6: Numeric Input Validation', () => {
    /**
     * Validates numeric input for fields like serviceDays, itemQuantity, cargoQuantity, travelDays
     * Returns validation result with parsed value
     */
    function validateNumericInput(input) {
      if (input === null || input === undefined || input === '') {
        return { valid: false, value: null, reason: 'Input is required' };
      }

      if (typeof input === 'string') {
        const trimmed = input.trim();
        if (trimmed === '') {
          return { valid: false, value: null, reason: 'Input is required' };
        }
        if (!/^-?\d+$/.test(trimmed)) {
          return { valid: false, value: null, reason: 'Input must be a valid integer' };
        }
        const parsed = parseInt(trimmed, 10);
        if (parsed <= 0) {
          return { valid: false, value: parsed, reason: 'Input must be a positive integer' };
        }
        return { valid: true, value: parsed };
      }

      if (typeof input === 'number') {
        if (!Number.isInteger(input)) {
          return { valid: false, value: null, reason: 'Input must be an integer' };
        }
        if (input <= 0) {
          return { valid: false, value: input, reason: 'Input must be a positive integer' };
        }
        return { valid: true, value: input };
      }

      return { valid: false, value: null, reason: 'Invalid input type' };
    }

    function validateServiceDays(serviceDays) {
      const result = validateNumericInput(serviceDays);
      if (!result.valid) {
        return {
          ...result,
          message: result.reason === 'Input is required' 
            ? '请输入服务天数' 
            : '请输入有效的服务天数'
        };
      }
      return result;
    }

    test('Valid positive integers should pass validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 1, max: 365 }),
          (days) => {
            const result = validateNumericInput(days);
            expect(result.valid).toBe(true);
            expect(result.value).toBe(days);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Valid positive integer strings should pass validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 1, max: 365 }),
          (days) => {
            const result = validateNumericInput(String(days));
            expect(result.valid).toBe(true);
            expect(result.value).toBe(days);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Zero should fail validation', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(0, '0', ' 0 '),
          (zeroValue) => {
            const result = validateNumericInput(zeroValue);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('Input must be a positive integer');
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Negative integers should fail validation', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: -1000, max: -1 }),
          (negativeValue) => {
            const result = validateNumericInput(negativeValue);
            expect(result.valid).toBe(false);
            expect(result.reason).toBe('Input must be a positive integer');
          }
        ),
        { numRuns: 100 }
      );
    });

    test('ServiceDays validation should accept valid positive integers', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: 1, max: 30 }),
          (days) => {
            const result = validateServiceDays(days);
            expect(result.valid).toBe(true);
            expect(result.value).toBe(days);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('ServiceDays validation should reject zero and negative values', () => {
      fc.assert(
        fc.property(
          fc.integer({ min: -100, max: 0 }),
          (invalidDays) => {
            const result = validateServiceDays(invalidDays);
            expect(result.valid).toBe(false);
            expect(result.message).toBe('请输入有效的服务天数');
          }
        ),
        { numRuns: 100 }
      );
    });

    test('ServiceDays validation should reject empty input', () => {
      fc.assert(
        fc.property(
          fc.constantFrom('', null, undefined),
          (emptyValue) => {
            const result = validateServiceDays(emptyValue);
            expect(result.valid).toBe(false);
            expect(result.message).toBe('请输入服务天数');
          }
        ),
        { numRuns: 100 }
      );
    });
  });

  /**
   * Feature: service-appointment-forms, Property 9: Duplicate Submission Prevention
   * For any form, while a submission is in progress, subsequent submit button clicks 
   * SHALL be ignored until the current submission completes.
   * **Validates: Requirements 18.4**
   */
  describe('Property 9: Duplicate Submission Prevention', () => {
    /**
     * Simulates form submission state management
     * This models the behavior of the Vue form components
     */
    class FormSubmissionManager {
      constructor() {
        this.submitting = false;
        this.submissionCount = 0;
        this.submissionResults = [];
      }

      /**
       * Attempts to submit the form
       * Returns true if submission was accepted, false if blocked
       */
      async attemptSubmit(formData) {
        // If already submitting, reject the submission
        if (this.submitting) {
          return { accepted: false, reason: 'submission_in_progress' };
        }

        // Set submitting flag
        this.submitting = true;
        this.submissionCount++;

        try {
          // Simulate async submission (API call)
          await this.simulateApiCall(formData);
          this.submissionResults.push({ success: true, data: formData });
          return { accepted: true, success: true };
        } catch (error) {
          this.submissionResults.push({ success: false, error: error.message });
          return { accepted: true, success: false, error: error.message };
        } finally {
          // Always reset submitting flag
          this.submitting = false;
        }
      }

      /**
       * Simulates an API call with configurable delay
       */
      async simulateApiCall(formData, delay = 5) {
        return new Promise((resolve) => {
          setTimeout(() => resolve({ success: true }), delay);
        });
      }

      /**
       * Synchronous check if submission would be blocked
       */
      wouldBlockSubmission() {
        return this.submitting;
      }

      /**
       * Reset the manager state
       */
      reset() {
        this.submitting = false;
        this.submissionCount = 0;
        this.submissionResults = [];
      }
    }

    /**
     * Validates that the submitting flag correctly prevents duplicate submissions
     */
    function validateSubmissionPrevention(submittingState, attemptSubmit) {
      // If submitting is true, the attempt should be blocked
      if (submittingState) {
        return { shouldBlock: true };
      }
      return { shouldBlock: false };
    }

    test('Submission should be blocked when submitting flag is true', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
          }),
          (serviceType, formData) => {
            // When submitting is true, submission should be blocked
            const result = validateSubmissionPrevention(true, () => {});
            expect(result.shouldBlock).toBe(true);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Submission should be allowed when submitting flag is false', () => {
      fc.assert(
        fc.property(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          fc.record({
            realName: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
            wechatId: fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
          }),
          (serviceType, formData) => {
            // When submitting is false, submission should be allowed
            const result = validateSubmissionPrevention(false, () => {});
            expect(result.shouldBlock).toBe(false);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Concurrent submission attempts should only allow one through', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          fc.integer({ min: 2, max: 5 }),
          async (serviceType, numAttempts) => {
            const manager = new FormSubmissionManager();
            const formData = generateAppointmentData(serviceType);

            // Start first submission (should be accepted)
            const firstSubmitPromise = manager.attemptSubmit(formData);
            
            // Immediately try additional submissions (should be blocked)
            const additionalAttempts = [];
            for (let i = 1; i < numAttempts; i++) {
              additionalAttempts.push(manager.attemptSubmit(formData));
            }

            // Wait for all attempts to complete
            const [firstResult, ...otherResults] = await Promise.all([
              firstSubmitPromise,
              ...additionalAttempts
            ]);

            // First submission should be accepted
            expect(firstResult.accepted).toBe(true);

            // All other submissions should be blocked
            for (const result of otherResults) {
              expect(result.accepted).toBe(false);
              expect(result.reason).toBe('submission_in_progress');
            }

            // Only one submission should have been processed
            expect(manager.submissionCount).toBe(1);
          }
        ),
        { numRuns: 30 }
      );
    }, 15000);

    test('Submitting flag should be reset after submission completes', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          async (serviceType) => {
            const manager = new FormSubmissionManager();
            const formData = generateAppointmentData(serviceType);

            // Initially not submitting
            expect(manager.wouldBlockSubmission()).toBe(false);

            // Submit and wait for completion
            await manager.attemptSubmit(formData);

            // After completion, should not be submitting
            expect(manager.wouldBlockSubmission()).toBe(false);

            // Should be able to submit again
            const secondResult = await manager.attemptSubmit(formData);
            expect(secondResult.accepted).toBe(true);
            expect(manager.submissionCount).toBe(2);
          }
        ),
        { numRuns: 30 }
      );
    }, 15000);

    test('Submitting flag should be reset even if submission fails', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          async (serviceType) => {
            const manager = new FormSubmissionManager();
            const formData = generateAppointmentData(serviceType);

            // Override simulateApiCall to throw an error
            manager.simulateApiCall = async () => {
              throw new Error('Network error');
            };

            // Submit (will fail)
            const result = await manager.attemptSubmit(formData);
            expect(result.accepted).toBe(true);
            expect(result.success).toBe(false);

            // After failure, should not be submitting
            expect(manager.wouldBlockSubmission()).toBe(false);

            // Should be able to submit again
            manager.simulateApiCall = async () => ({ success: true });
            const retryResult = await manager.attemptSubmit(formData);
            expect(retryResult.accepted).toBe(true);
          }
        ),
        { numRuns: 30 }
      );
    }, 15000);

    test('Sequential submissions should all be processed', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          fc.integer({ min: 2, max: 3 }),
          async (serviceType, numSubmissions) => {
            const manager = new FormSubmissionManager();
            const formData = generateAppointmentData(serviceType);

            // Submit sequentially (waiting for each to complete)
            for (let i = 0; i < numSubmissions; i++) {
              const result = await manager.attemptSubmit(formData);
              expect(result.accepted).toBe(true);
            }

            // All submissions should have been processed
            expect(manager.submissionCount).toBe(numSubmissions);
            expect(manager.submissionResults).toHaveLength(numSubmissions);
          }
        ),
        { numRuns: 30 }
      );
    }, 15000);

    test('Form submission state should correctly model Vue component behavior', () => {
      fc.assert(
        fc.property(
          fc.boolean(),
          fc.constantFrom(...Object.keys(SERVICE_TYPE_FIELDS)),
          (initialSubmittingState, serviceType) => {
            // Model the Vue component's submitAppointment method behavior
            let submitting = initialSubmittingState;
            let submissionAttempted = false;

            // Simulate the guard check: if (this.submitting) return
            const attemptSubmit = () => {
              if (submitting) {
                return { blocked: true };
              }
              submitting = true;
              submissionAttempted = true;
              return { blocked: false };
            };

            const result = attemptSubmit();

            if (initialSubmittingState) {
              // If already submitting, should be blocked
              expect(result.blocked).toBe(true);
              expect(submissionAttempted).toBe(false);
            } else {
              // If not submitting, should proceed
              expect(result.blocked).toBe(false);
              expect(submissionAttempted).toBe(true);
              expect(submitting).toBe(true);
            }
          }
        ),
        { numRuns: 100 }
      );
    });
  });
});
