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

/**
 * Property-Based Tests for Admin Service Management
 * Feature: overseas-appointment-backend
 * 
 * These tests verify admin service CRUD operations maintain consistency
 * using property-based testing.
 */

// Mock database for testing
class MockAdminServiceDatabase {
  constructor() {
    this.services = new Map();
    this.categories = new Map();
    this.appointments = new Map();
    this.initializeCategories();
  }

  initializeCategories() {
    const categories = [
      {
        id: 'cat-1',
        key: 'airport',
        nameZh: '机场服务',
        nameEn: 'Airport Service',
        namePt: 'Serviço de Aeroporto',
        icon: 'airport.png',
        sortOrder: 1,
      },
      {
        id: 'cat-2',
        key: 'hotel',
        nameZh: '酒店预订',
        nameEn: 'Hotel Booking',
        namePt: 'Reserva de Hotel',
        icon: 'hotel.png',
        sortOrder: 2,
      },
      {
        id: 'cat-3',
        key: 'train',
        nameZh: '火车票',
        nameEn: 'Train Ticket',
        namePt: 'Bilhete de Trem',
        icon: 'train.png',
        sortOrder: 3,
      },
    ];

    categories.forEach(cat => this.categories.set(cat.id, cat));
  }

  clear() {
    this.services.clear();
    this.appointments.clear();
    this.categories.clear();
    this.initializeCategories();
  }

  createService(serviceData) {
    // Validate required fields first
    const requiredFields = ['categoryId', 'titleZh', 'titleEn', 'titlePt'];
    for (const field of requiredFields) {
      if (!serviceData[field]) {
        const error = new Error(`Missing required field: ${field}`);
        error.statusCode = 400;
        error.code = 'MISSING_REQUIRED_FIELD';
        throw error;
      }
    }

    // Validate category exists
    if (!this.categories.has(serviceData.categoryId)) {
      const error = new Error('Category not found');
      error.statusCode = 404;
      error.code = 'CATEGORY_NOT_FOUND';
      throw error;
    }

    const id = `service-${Math.random().toString(36).substring(7)}`;
    const service = {
      id,
      status: serviceData.status || 'active',
      sortOrder: serviceData.sortOrder || 0,
      createdAt: new Date(),
      updatedAt: new Date(),
      ...serviceData,
    };
    this.services.set(id, service);
    return service;
  }

  findServiceById(id) {
    const service = this.services.get(id);
    if (!service) return null;

    const category = this.categories.get(service.categoryId);
    return {
      ...service,
      category: category || null,
    };
  }

  updateService(id, updateData) {
    const service = this.services.get(id);
    if (!service) {
      const error = new Error('Service not found');
      error.statusCode = 404;
      error.code = 'SERVICE_NOT_FOUND';
      throw error;
    }

    // Validate category if being updated
    if (updateData.categoryId && !this.categories.has(updateData.categoryId)) {
      const error = new Error('Category not found');
      error.statusCode = 404;
      error.code = 'CATEGORY_NOT_FOUND';
      throw error;
    }

    const updatedService = {
      ...service,
      ...updateData,
      updatedAt: new Date(),
    };
    this.services.set(id, updatedService);
    return updatedService;
  }

  deleteService(id) {
    const service = this.services.get(id);
    if (!service) {
      const error = new Error('Service not found');
      error.statusCode = 404;
      error.code = 'SERVICE_NOT_FOUND';
      throw error;
    }

    // Check if service has appointments
    const appointmentCount = Array.from(this.appointments.values())
      .filter(apt => apt.serviceId === id).length;

    if (appointmentCount > 0) {
      const error = new Error('Cannot delete service with existing appointments');
      error.statusCode = 400;
      error.code = 'SERVICE_HAS_APPOINTMENTS';
      throw error;
    }

    this.services.delete(id);
    return true;
  }

  createAppointment(serviceId) {
    const id = `apt-${Math.random().toString(36).substring(7)}`;
    const appointment = {
      id,
      serviceId,
      createdAt: new Date(),
    };
    this.appointments.set(id, appointment);
    return appointment;
  }

  getAllServices() {
    return Array.from(this.services.values());
  }

  getAllCategories() {
    return Array.from(this.categories.values());
  }
}

// Mock admin service
const mockAdminService = {
  db: new MockAdminServiceDatabase(),

  createService: async (serviceData) => {
    return mockAdminService.db.createService(serviceData);
  },

  getServiceById: async (serviceId) => {
    const service = mockAdminService.db.findServiceById(serviceId);
    if (!service) {
      const error = new Error('Service not found');
      error.statusCode = 404;
      error.code = 'SERVICE_NOT_FOUND';
      throw error;
    }
    return service;
  },

  updateService: async (serviceId, updateData) => {
    return mockAdminService.db.updateService(serviceId, updateData);
  },

  deleteService: async (serviceId) => {
    return mockAdminService.db.deleteService(serviceId);
  },
};

describe('Admin Service Management Property Tests', () => {
  beforeEach(() => {
    mockAdminService.db.clear();
  });

  /**
   * Feature: overseas-appointment-backend, Property 6: Category CRUD operations maintain consistency
   * Validates: Requirements 2.1
   * 
   * For any service category, creating, reading, updating, and deleting operations 
   * should maintain database consistency without orphaned records.
   */
  describe('Property 6: Category CRUD operations maintain consistency', () => {
    test('Creating a service with valid category succeeds', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
            image: fc.webUrl(),
            price: fc.double({ min: 0, max: 10000, noNaN: true }),
          }),
          async (serviceData) => {
            // Create service
            const service = await mockAdminService.createService(serviceData);

            // Verify service was created
            expect(service).toBeDefined();
            expect(service.id).toBeDefined();
            expect(service.categoryId).toBe(serviceData.categoryId);
            expect(service.titleZh).toBe(serviceData.titleZh);
            expect(service.titleEn).toBe(serviceData.titleEn);
            expect(service.titlePt).toBe(serviceData.titlePt);

            // Verify service can be retrieved
            const retrieved = await mockAdminService.getServiceById(service.id);
            expect(retrieved).toBeDefined();
            expect(retrieved.id).toBe(service.id);
            expect(retrieved.category).toBeDefined();
            expect(retrieved.category.id).toBe(serviceData.categoryId);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Creating a service with invalid category fails', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constant('invalid-category-id'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Attempt to create service with invalid category
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow('Category not found');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Updating service maintains category consistency', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
          async (serviceData, newCategoryId) => {
            // Create service
            const service = await mockAdminService.createService(serviceData);

            // Update category
            const updated = await mockAdminService.updateService(service.id, {
              categoryId: newCategoryId,
            });

            // Verify category was updated
            expect(updated.categoryId).toBe(newCategoryId);

            // Verify service can still be retrieved with new category
            const retrieved = await mockAdminService.getServiceById(service.id);
            expect(retrieved.categoryId).toBe(newCategoryId);
            expect(retrieved.category).toBeDefined();
            expect(retrieved.category.id).toBe(newCategoryId);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Updating service with invalid category fails', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Create service
            const service = await mockAdminService.createService(serviceData);

            // Attempt to update with invalid category
            await expect(
              mockAdminService.updateService(service.id, {
                categoryId: 'invalid-category-id',
              })
            ).rejects.toThrow('Category not found');

            // Verify original category is unchanged
            const retrieved = await mockAdminService.getServiceById(service.id);
            expect(retrieved.categoryId).toBe(serviceData.categoryId);
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Deleting service without appointments succeeds', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Create service
            const service = await mockAdminService.createService(serviceData);

            // Delete service
            const result = await mockAdminService.deleteService(service.id);
            expect(result).toBe(true);

            // Verify service no longer exists
            await expect(mockAdminService.getServiceById(service.id)).rejects.toThrow('Service not found');

            // Verify no orphaned records
            const allServices = mockAdminService.db.getAllServices();
            expect(allServices.find(s => s.id === service.id)).toBeUndefined();
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Deleting service with appointments fails', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Create service
            const service = await mockAdminService.createService(serviceData);

            // Create appointment for this service
            mockAdminService.db.createAppointment(service.id);

            // Attempt to delete service
            await expect(mockAdminService.deleteService(service.id)).rejects.toThrow(
              'Cannot delete service with existing appointments'
            );

            // Verify service still exists
            const retrieved = await mockAdminService.getServiceById(service.id);
            expect(retrieved).toBeDefined();
            expect(retrieved.id).toBe(service.id);
          }
        ),
        { numRuns: 50 }
      );
    });

    test('CRUD operations maintain database consistency', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.array(
            fc.record({
              categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
              titleZh: fc.string({ minLength: 5, maxLength: 50 }),
              titleEn: fc.string({ minLength: 5, maxLength: 50 }),
              titlePt: fc.string({ minLength: 5, maxLength: 50 }),
              descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
              descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
              descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
            }),
            { minLength: 3, maxLength: 10 }
          ),
          async (servicesData) => {
            // Clear database for this iteration
            mockAdminService.db.clear();
            
            // Create multiple services
            const createdServices = [];
            for (const data of servicesData) {
              const service = await mockAdminService.createService(data);
              createdServices.push(service);
            }

            // Verify all services exist
            expect(mockAdminService.db.getAllServices().length).toBe(servicesData.length);

            // Update some services
            for (let i = 0; i < Math.min(3, createdServices.length); i++) {
              await mockAdminService.updateService(createdServices[i].id, {
                titleZh: '更新后的标题',
              });
            }

            // Verify updates
            for (let i = 0; i < Math.min(3, createdServices.length); i++) {
              const retrieved = await mockAdminService.getServiceById(createdServices[i].id);
              expect(retrieved.titleZh).toBe('更新后的标题');
            }

            // Delete some services (without appointments)
            const toDelete = createdServices.slice(0, Math.min(2, createdServices.length));
            for (const service of toDelete) {
              await mockAdminService.deleteService(service.id);
            }

            // Verify deletions
            const remainingCount = servicesData.length - toDelete.length;
            expect(mockAdminService.db.getAllServices().length).toBe(remainingCount);

            // Verify deleted services don't exist
            for (const service of toDelete) {
              await expect(mockAdminService.getServiceById(service.id)).rejects.toThrow('Service not found');
            }

            // Verify remaining services still exist
            const remaining = createdServices.slice(toDelete.length);
            for (const service of remaining) {
              const retrieved = await mockAdminService.getServiceById(service.id);
              expect(retrieved).toBeDefined();
            }
          }
        ),
        { numRuns: 50 }
      );
    });

    test('All services maintain valid category references', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.array(
            fc.record({
              categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
              titleZh: fc.string({ minLength: 5, maxLength: 50 }),
              titleEn: fc.string({ minLength: 5, maxLength: 50 }),
              titlePt: fc.string({ minLength: 5, maxLength: 50 }),
              descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
              descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
              descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
            }),
            { minLength: 5, maxLength: 15 }
          ),
          async (servicesData) => {
            // Clear database for this iteration
            mockAdminService.db.clear();
            
            // Create multiple services
            for (const data of servicesData) {
              await mockAdminService.createService(data);
            }

            // Get all services
            const allServices = mockAdminService.db.getAllServices();
            const allCategories = mockAdminService.db.getAllCategories();
            const categoryIds = new Set(allCategories.map(c => c.id));

            // Verify every service has a valid category reference
            for (const service of allServices) {
              expect(categoryIds.has(service.categoryId)).toBe(true);

              // Verify category can be retrieved
              const retrieved = await mockAdminService.getServiceById(service.id);
              expect(retrieved.category).toBeDefined();
              expect(retrieved.category.id).toBe(service.categoryId);
            }
          }
        ),
        { numRuns: 50 }
      );
    });
  });

  /**
   * Feature: overseas-appointment-backend, Property 7: Service creation requires all mandatory fields
   * Validates: Requirements 2.2
   * 
   * For any service creation attempt missing required fields (category, title, description, image), 
   * the system should reject the request with appropriate validation errors.
   */
  describe('Property 7: Service creation requires all mandatory fields', () => {
    test('Service creation fails when categoryId is missing', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Attempt to create service without categoryId
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow('Missing required field');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Service creation fails when titleZh is missing', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Attempt to create service without titleZh
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow('Missing required field');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Service creation fails when titleEn is missing', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Attempt to create service without titleEn
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow('Missing required field');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Service creation fails when titlePt is missing', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
          }),
          async (serviceData) => {
            // Attempt to create service without titlePt
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow('Missing required field');
          }
        ),
        { numRuns: 50 }
      );
    });

    test('Service creation fails when any required field is empty string', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.constantFrom('categoryId', 'titleZh', 'titleEn', 'titlePt'),
          async (fieldToEmpty) => {
            const serviceData = {
              categoryId: 'cat-1',
              titleZh: '中文标题',
              titleEn: 'English Title',
              titlePt: 'Título Português',
              descriptionZh: '中文描述',
              descriptionEn: 'English Description',
              descriptionPt: 'Descrição Portuguesa',
            };

            // Set one required field to empty string
            serviceData[fieldToEmpty] = '';

            // Attempt to create service
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow();
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Service creation succeeds when all required fields are present', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
          }),
          async (serviceData) => {
            // Create service with all required fields
            const service = await mockAdminService.createService(serviceData);

            // Verify service was created successfully
            expect(service).toBeDefined();
            expect(service.id).toBeDefined();
            expect(service.categoryId).toBe(serviceData.categoryId);
            expect(service.titleZh).toBe(serviceData.titleZh);
            expect(service.titleEn).toBe(serviceData.titleEn);
            expect(service.titlePt).toBe(serviceData.titlePt);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Service creation succeeds with optional fields omitted', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
          }),
          async (serviceData) => {
            // Create service without optional fields (description, image, price)
            const service = await mockAdminService.createService(serviceData);

            // Verify service was created successfully
            expect(service).toBeDefined();
            expect(service.id).toBeDefined();
            expect(service.categoryId).toBe(serviceData.categoryId);
            expect(service.titleZh).toBe(serviceData.titleZh);
            expect(service.titleEn).toBe(serviceData.titleEn);
            expect(service.titlePt).toBe(serviceData.titlePt);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Service creation with all fields (required and optional) succeeds', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.record({
            categoryId: fc.constantFrom('cat-1', 'cat-2', 'cat-3'),
            titleZh: fc.string({ minLength: 5, maxLength: 50 }),
            titleEn: fc.string({ minLength: 5, maxLength: 50 }),
            titlePt: fc.string({ minLength: 5, maxLength: 50 }),
            descriptionZh: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionEn: fc.string({ minLength: 10, maxLength: 200 }),
            descriptionPt: fc.string({ minLength: 10, maxLength: 200 }),
            image: fc.webUrl(),
            price: fc.double({ min: 0, max: 10000, noNaN: true }),
            status: fc.constantFrom('active', 'inactive'),
            sortOrder: fc.integer({ min: 0, max: 100 }),
          }),
          async (serviceData) => {
            // Create service with all fields
            const service = await mockAdminService.createService(serviceData);

            // Verify all fields are set correctly
            expect(service).toBeDefined();
            expect(service.id).toBeDefined();
            expect(service.categoryId).toBe(serviceData.categoryId);
            expect(service.titleZh).toBe(serviceData.titleZh);
            expect(service.titleEn).toBe(serviceData.titleEn);
            expect(service.titlePt).toBe(serviceData.titlePt);
            expect(service.descriptionZh).toBe(serviceData.descriptionZh);
            expect(service.descriptionEn).toBe(serviceData.descriptionEn);
            expect(service.descriptionPt).toBe(serviceData.descriptionPt);
            expect(service.image).toBe(serviceData.image);
            expect(service.price).toBe(serviceData.price);
            expect(service.status).toBe(serviceData.status);
            expect(service.sortOrder).toBe(serviceData.sortOrder);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Multiple required field validations fail appropriately', async () => {
      await fc.assert(
        fc.asyncProperty(
          fc.array(fc.constantFrom('categoryId', 'titleZh', 'titleEn', 'titlePt'), {
            minLength: 1,
            maxLength: 4,
          }),
          async (fieldsToOmit) => {
            const serviceData = {
              categoryId: 'cat-1',
              titleZh: '中文标题',
              titleEn: 'English Title',
              titlePt: 'Título Português',
              descriptionZh: '中文描述',
              descriptionEn: 'English Description',
              descriptionPt: 'Descrição Portuguesa',
            };

            // Remove specified fields
            fieldsToOmit.forEach(field => {
              delete serviceData[field];
            });

            // Attempt to create service
            await expect(mockAdminService.createService(serviceData)).rejects.toThrow();
          }
        ),
        { numRuns: 50 }
      );
    });
  });
});
