import { describe, expect, it } from 'vitest';
import viMessages from '../../messages/vi.json';
import enMessages from '../../messages/en.json';

describe('locale messages', () => {
  describe('structural parity between vi.json and en.json', () => {
    function getKeys(obj: Record<string, unknown>, prefix = ''): string[] {
      const keys: string[] = [];
      for (const key of Object.keys(obj)) {
        const fullKey = prefix ? `${prefix}.${key}` : key;
        if (
          typeof obj[key] === 'object' &&
          obj[key] !== null &&
          !Array.isArray(obj[key])
        ) {
          keys.push(
            ...getKeys(obj[key] as Record<string, unknown>, fullKey),
          );
        } else {
          keys.push(fullKey);
        }
      }
      return keys.sort();
    }

    it('vi.json and en.json have the same top-level namespaces', () => {
      const viNamespaces = Object.keys(viMessages).sort();
      const enNamespaces = Object.keys(enMessages).sort();
      expect(viNamespaces).toEqual(enNamespaces);
    });

    it('vi.json and en.json have the exact same key structure', () => {
      const viKeys = getKeys(viMessages as unknown as Record<string, unknown>);
      const enKeys = getKeys(enMessages as unknown as Record<string, unknown>);
      expect(viKeys).toEqual(enKeys);
    });

    it('no keys are missing from en.json', () => {
      const viKeys = new Set(
        getKeys(viMessages as unknown as Record<string, unknown>),
      );
      const enKeys = new Set(
        getKeys(enMessages as unknown as Record<string, unknown>),
      );
      const missingInEn = [...viKeys].filter((k) => !enKeys.has(k));
      expect(missingInEn).toEqual([]);
    });

    it('no keys are missing from vi.json', () => {
      const viKeys = new Set(
        getKeys(viMessages as unknown as Record<string, unknown>),
      );
      const enKeys = new Set(
        getKeys(enMessages as unknown as Record<string, unknown>),
      );
      const missingInVi = [...enKeys].filter((k) => !viKeys.has(k));
      expect(missingInVi).toEqual([]);
    });
  });

  describe('Vietnamese (vi.json) content', () => {
    it('has a metadata namespace with title', () => {
      expect(viMessages.metadata).toBeDefined();
      expect(viMessages.metadata.title).toBe(
        'GoodGo — Nền tảng Bất động sản Việt Nam',
      );
    });

    it('has common namespace with Vietnamese translations', () => {
      expect(viMessages.common.loading).toBe('Đang tải...');
      expect(viMessages.common.login).toBe('Đăng nhập');
      expect(viMessages.common.register).toBe('Đăng ký');
      expect(viMessages.common.logout).toBe('Đăng xuất');
    });

    it('has nav namespace with Vietnamese navigation labels', () => {
      expect(viMessages.nav.home).toBe('Trang chủ');
      expect(viMessages.nav.search).toBe('Tìm kiếm');
      expect(viMessages.nav.pricing).toBe('Bảng giá');
    });

    it('has propertyTypes namespace with all 9 property types in Vietnamese', () => {
      const types = viMessages.propertyTypes;
      expect(Object.keys(types)).toHaveLength(9);
      expect(types.APARTMENT).toBe('Căn hộ');
      expect(types.HOUSE).toBe('Nhà riêng');
      expect(types.VILLA).toBe('Biệt thự');
      expect(types.LAND).toBe('Đất nền');
      expect(types.OFFICE).toBe('Văn phòng');
      expect(types.SHOPHOUSE).toBe('Shophouse');
      expect(types.ROOM_RENTAL).toBe('Phòng trọ');
      expect(types.CONDOTEL).toBe('Condotel');
      expect(types.SERVICED_APARTMENT).toBe('Căn hộ dịch vụ');
    });

    it('has transactionTypes in Vietnamese', () => {
      expect(viMessages.transactionTypes.SALE).toBe('Bán');
      expect(viMessages.transactionTypes.RENT).toBe('Cho thuê');
    });

    it('has language labels including self-referencing Vietnamese label', () => {
      expect(viMessages.language.label).toBe('Ngôn ngữ');
      expect(viMessages.language.vi).toBe('Tiếng Việt');
      expect(viMessages.language.en).toBe('English');
    });

    it('has auth namespace with login form labels', () => {
      expect(viMessages.auth.loginTitle).toBe('Đăng nhập');
      expect(viMessages.auth.phone).toBe('Số điện thoại');
      expect(viMessages.auth.password).toBe('Mật khẩu');
    });

    it('has pricing namespace with plan tier labels', () => {
      expect(viMessages.pricing.tiers.FREE).toBe('Miễn phí');
      expect(viMessages.pricing.tiers.AGENT_PRO).toBe('Môi giới Pro');
      expect(viMessages.pricing.tiers.INVESTOR).toBe('Nhà đầu tư');
      expect(viMessages.pricing.tiers.ENTERPRISE).toBe('Doanh nghiệp');
    });

    it('has search namespace with filter labels', () => {
      expect(viMessages.search.filters).toBe('Bộ lọc');
      expect(viMessages.search.district).toBe('Quận/huyện');
      expect(viMessages.search.ward).toBe('Phường/xã');
    });
  });

  describe('English (en.json) content', () => {
    it('has a metadata namespace with English title', () => {
      expect(enMessages.metadata.title).toBe(
        'GoodGo — Vietnam Real Estate Platform',
      );
    });

    it('has common namespace with English translations', () => {
      expect(enMessages.common.loading).toBe('Loading...');
      expect(enMessages.common.login).toBe('Login');
      expect(enMessages.common.register).toBe('Register');
      expect(enMessages.common.logout).toBe('Logout');
    });

    it('has propertyTypes in English', () => {
      expect(enMessages.propertyTypes.APARTMENT).toBe('Apartment');
      expect(enMessages.propertyTypes.HOUSE).toBe('House');
      expect(enMessages.propertyTypes.VILLA).toBe('Villa');
    });

    it('has transactionTypes in English', () => {
      expect(enMessages.transactionTypes.SALE).toBe('Sale');
      expect(enMessages.transactionTypes.RENT).toBe('Rent');
    });
  });

  describe('interpolation placeholders', () => {
    it('vi.json common.errorCode contains {code} placeholder', () => {
      expect(viMessages.common.errorCode).toContain('{code}');
    });

    it('en.json common.errorCode contains {code} placeholder', () => {
      expect(enMessages.common.errorCode).toContain('{code}');
    });

    it('vi.json common.retriedCount contains {count} placeholder', () => {
      expect(viMessages.common.retriedCount).toContain('{count}');
    });

    it('en.json common.retriedCount contains {count} placeholder', () => {
      expect(enMessages.common.retriedCount).toContain('{count}');
    });

    it('vi.json search.bedroomsCount contains {count} placeholder', () => {
      expect(viMessages.search.bedroomsCount).toContain('{count}');
    });

    it('en.json search.bedroomsCount contains {count} placeholder', () => {
      expect(enMessages.search.bedroomsCount).toContain('{count}');
    });

    it('vi.json and en.json pricing.currentPlanBadge both contain {plan}', () => {
      expect(viMessages.pricing.currentPlanBadge).toContain('{plan}');
      expect(enMessages.pricing.currentPlanBadge).toContain('{plan}');
    });
  });

  describe('no empty values', () => {
    function findEmptyValues(
      obj: Record<string, unknown>,
      prefix = '',
    ): string[] {
      const empty: string[] = [];
      for (const key of Object.keys(obj)) {
        const fullKey = prefix ? `${prefix}.${key}` : key;
        const value = obj[key];
        if (
          typeof value === 'object' &&
          value !== null &&
          !Array.isArray(value)
        ) {
          empty.push(
            ...findEmptyValues(value as Record<string, unknown>, fullKey),
          );
        } else if (typeof value === 'string' && value.trim() === '') {
          empty.push(fullKey);
        }
      }
      return empty;
    }

    it('vi.json has no empty string values', () => {
      const emptyKeys = findEmptyValues(
        viMessages as unknown as Record<string, unknown>,
      );
      expect(emptyKeys).toEqual([]);
    });

    it('en.json has no empty string values', () => {
      const emptyKeys = findEmptyValues(
        enMessages as unknown as Record<string, unknown>,
      );
      expect(emptyKeys).toEqual([]);
    });
  });
});
