import { describe, it, expect } from 'vitest';
import en from '@/messages/en.json';
import pl from '@/messages/pl.json';
import fr from '@/messages/fr.json';
import es from '@/messages/es.json';

const locales: Record<string, Record<string, unknown>> = { en, pl, fr, es };

/**
 * Recursively extract all keys from a nested object.
 * Arrays are treated as leaf values (not recursed into).
 */
function getKeys(obj: Record<string, unknown>, prefix = ''): string[] {
  return Object.entries(obj).flatMap(([key, value]) => {
    const fullKey = prefix ? `${prefix}.${key}` : key;
    if (value && typeof value === 'object' && !Array.isArray(value)) {
      return getKeys(value as Record<string, unknown>, fullKey);
    }
    return [fullKey];
  });
}

describe('i18n messages', () => {
  const enKeys = getKeys(en).sort();

  it('should have the same top-level sections across all locales', () => {
    const enSections = Object.keys(en).sort();
    for (const [locale, messages] of Object.entries(locales)) {
      if (locale === 'en') continue;
      const sections = Object.keys(messages).sort();
      expect(sections, `${locale} top-level sections should match en`).toEqual(enSections);
    }
  });

  it('should have identical key structure in every locale', () => {
    for (const [locale, messages] of Object.entries(locales)) {
      if (locale === 'en') continue;
      const keys = getKeys(messages).sort();
      expect(keys, `${locale} keys should match en`).toEqual(enKeys);
    }
  });

  it('should not have empty string values', () => {
    for (const [locale, messages] of Object.entries(locales)) {
      const keys = getKeys(messages);
      keys.forEach((key) => {
        const value = key.split('.').reduce<unknown>((obj, k) => {
          if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
            return (obj as Record<string, unknown>)[k];
          }
          return obj;
        }, messages);

        if (typeof value === 'string') {
          expect(value.trim(), `${locale}:${key} should not be empty`).not.toBe('');
        }
      });
    }
  });

  it('should have required top-level sections', () => {
    const requiredSections = ['nav', 'hero', 'what_is', 'features', 'faq', 'footer', 'cookies', 'blog', 'changelog', 'privacy', 'terms', 'meta'];
    for (const [locale, messages] of Object.entries(locales)) {
      for (const section of requiredSections) {
        expect(messages, `${locale} should have section "${section}"`).toHaveProperty(section);
      }
    }
  });

  it('should have the same number of feature items in every locale', () => {
    const enCount = (en.features.items as unknown[]).length;
    expect(enCount).toBe(8);

    for (const [locale, messages] of Object.entries(locales)) {
      const items = (messages as typeof en).features.items;
      expect(items.length, `${locale} features.items count`).toBe(enCount);
    }
  });

  it('should have the same number of FAQ items in every locale', () => {
    const enCount = (en.faq.items as unknown[]).length;
    for (const [locale, messages] of Object.entries(locales)) {
      const items = (messages as typeof en).faq.items;
      expect(items.length, `${locale} faq.items count`).toBe(enCount);
    }
  });

  it('should have valid feature icon names', () => {
    const validIcons = ['Rss', 'ShieldOff', 'Search', 'Bookmark', 'Moon', 'Smartphone', 'Zap', 'Lock'];
    for (const [locale, messages] of Object.entries(locales)) {
      const items = (messages as typeof en).features.items;
      items.forEach((item, i) => {
        expect(validIcons, `${locale} features.items[${i}].icon "${item.icon}" should be valid`).toContain(item.icon);
      });
    }
  });

  it('should have the same number of privacy sections in every locale', () => {
    const enCount = (en.privacy.sections as unknown[]).length;
    for (const [locale, messages] of Object.entries(locales)) {
      const sections = (messages as typeof en).privacy.sections;
      expect(sections.length, `${locale} privacy.sections count`).toBe(enCount);
    }
  });

  it('should have the same number of terms sections in every locale', () => {
    const enCount = (en.terms.sections as unknown[]).length;
    for (const [locale, messages] of Object.entries(locales)) {
      const sections = (messages as typeof en).terms.sections;
      expect(sections.length, `${locale} terms.sections count`).toBe(enCount);
    }
  });
});
