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

/**
 * Property-Based Tests for Data Models
 * Feature: overseas-appointment-backend, Property 55: Multi-language data storage
 * Validates: Requirements 12.3
 * 
 * These tests verify that multi-language data can be stored and retrieved correctly
 * for all content types (categories, services, notifications) in all supported languages.
 */

// Mock data structure to simulate database storage
class MockDatabase {
  constructor() {
    this.categories = new Map();
    this.services = new Map();
    this.notifications = new Map();
  }

  clear() {
    this.categories.clear();
    this.services.clear();
    this.notifications.clear();
  }

  createCategory(data) {
    const id = Math.random().toString(36).substring(7);
    const category = { id, ...data };
    this.categories.set(id, category);
    return category;
  }

  findCategory(id) {
    return this.categories.get(id);
  }

  createService(data) {
    const id = Math.random().toString(36).substring(7);
    const service = { id, ...data };
    this.services.set(id, service);
    return service;
  }

  findService(id) {
    return this.services.get(id);
  }

  createNotification(data) {
    const id = Math.random().toString(36).substring(7);
    const notification = { id, ...data };
    this.notifications.set(id, notification);
    return notification;
  }

  findNotification(id) {
    return this.notifications.get(id);
  }
}

const db = new MockDatabase();

describe('Data Models Property Tests', () => {
  afterEach(() => {
    // Clean up after each test
    db.clear();
  });

  /**
   * Feature: overseas-appointment-backend, Property 55: Multi-language data storage
   * For any content type (services, notifications, categories), the system should 
   * store and retrieve translations for all supported languages (zh, en, pt)
   */
  describe('Property 55: Multi-language data storage', () => {
    test('Category should store and retrieve all language translations', () => {
      fc.assert(
        fc.property(
          fc.record({
            key: fc.string({ minLength: 1, maxLength: 50 }).filter(s => /^[a-z0-9-]+$/.test(s)),
            nameZh: fc.string({ minLength: 1, maxLength: 100 }),
            nameEn: fc.string({ minLength: 1, maxLength: 100 }),
            namePt: fc.string({ minLength: 1, maxLength: 100 }),
            sortOrder: fc.integer({ min: 0, max: 1000 }),
          }),
          (categoryData) => {
            // Create category with multi-language data
            const category = db.createCategory({
              key: categoryData.key,
              nameZh: categoryData.nameZh,
              nameEn: categoryData.nameEn,
              namePt: categoryData.namePt,
              sortOrder: categoryData.sortOrder,
            });

            // Retrieve the category
            const retrieved = db.findCategory(category.id);

            // Verify all language fields are stored and retrieved correctly
            expect(retrieved.nameZh).toBe(categoryData.nameZh);
            expect(retrieved.nameEn).toBe(categoryData.nameEn);
            expect(retrieved.namePt).toBe(categoryData.namePt);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Service should store and retrieve all language translations', () => {
      fc.assert(
        fc.property(
          fc.record({
            titleZh: fc.string({ minLength: 1, maxLength: 200 }),
            titleEn: fc.string({ minLength: 1, maxLength: 200 }),
            titlePt: fc.string({ minLength: 1, maxLength: 200 }),
            descriptionZh: fc.string({ minLength: 0, maxLength: 500 }),
            descriptionEn: fc.string({ minLength: 0, maxLength: 500 }),
            descriptionPt: fc.string({ minLength: 0, maxLength: 500 }),
          }),
          (serviceData) => {
            // Create service with multi-language data
            const service = db.createService({
              titleZh: serviceData.titleZh,
              titleEn: serviceData.titleEn,
              titlePt: serviceData.titlePt,
              descriptionZh: serviceData.descriptionZh,
              descriptionEn: serviceData.descriptionEn,
              descriptionPt: serviceData.descriptionPt,
            });

            // Retrieve the service
            const retrieved = db.findService(service.id);

            // Verify all language fields are stored and retrieved correctly
            expect(retrieved.titleZh).toBe(serviceData.titleZh);
            expect(retrieved.titleEn).toBe(serviceData.titleEn);
            expect(retrieved.titlePt).toBe(serviceData.titlePt);
            expect(retrieved.descriptionZh).toBe(serviceData.descriptionZh);
            expect(retrieved.descriptionEn).toBe(serviceData.descriptionEn);
            expect(retrieved.descriptionPt).toBe(serviceData.descriptionPt);
          }
        ),
        { numRuns: 100 }
      );
    });

    test('Notification should store and retrieve all language translations', () => {
      fc.assert(
        fc.property(
          fc.record({
            titleZh: fc.string({ minLength: 1, maxLength: 200 }),
            titleEn: fc.string({ minLength: 1, maxLength: 200 }),
            titlePt: fc.string({ minLength: 1, maxLength: 200 }),
            contentZh: fc.string({ minLength: 1, maxLength: 500 }),
            contentEn: fc.string({ minLength: 1, maxLength: 500 }),
            contentPt: fc.string({ minLength: 1, maxLength: 500 }),
            type: fc.constantFrom('system', 'activity', 'service'),
          }),
          (notificationData) => {
            // Create notification with multi-language data
            const notification = db.createNotification({
              type: notificationData.type,
              titleZh: notificationData.titleZh,
              titleEn: notificationData.titleEn,
              titlePt: notificationData.titlePt,
              contentZh: notificationData.contentZh,
              contentEn: notificationData.contentEn,
              contentPt: notificationData.contentPt,
            });

            // Retrieve the notification
            const retrieved = db.findNotification(notification.id);

            // Verify all language fields are stored and retrieved correctly
            expect(retrieved.titleZh).toBe(notificationData.titleZh);
            expect(retrieved.titleEn).toBe(notificationData.titleEn);
            expect(retrieved.titlePt).toBe(notificationData.titlePt);
            expect(retrieved.contentZh).toBe(notificationData.contentZh);
            expect(retrieved.contentEn).toBe(notificationData.contentEn);
            expect(retrieved.contentPt).toBe(notificationData.contentPt);
          }
        ),
        { numRuns: 100 }
      );
    });
  });
});
