import { describe, expect, it, vi, beforeEach } from 'vitest';

// Mock the routing module
vi.mock('../routing', () => ({
  routing: {
    locales: ['vi', 'en'] as const,
    defaultLocale: 'vi',
    localePrefix: 'as-needed',
  },
}));

// Track getRequestConfig calls
let capturedConfigFn: ((params: { requestLocale: Promise<string | undefined> }) => Promise<{
  locale: string;
  messages: Record<string, unknown>;
}>) | null = null;

vi.mock('next-intl/server', () => ({
  getRequestConfig: (fn: typeof capturedConfigFn) => {
    capturedConfigFn = fn;
    return fn;
  },
}));

// Provide message mocks
vi.mock('../../messages/vi.json', () => ({
  default: {
    common: { goodgo: 'GoodGo', loading: 'Đang tải...' },
    metadata: { title: 'GoodGo — Nền tảng Bất động sản Việt Nam' },
  },
}));

vi.mock('../../messages/en.json', () => ({
  default: {
    common: { goodgo: 'GoodGo', loading: 'Loading...' },
    metadata: { title: 'GoodGo — Vietnam Real Estate Platform' },
  },
}));

// Import triggers getRequestConfig, which captures the config function
await import('../request');

describe('i18n/request', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('captures a config function via getRequestConfig', () => {
    expect(capturedConfigFn).toBeTypeOf('function');
  });

  describe('locale resolution', () => {
    it('uses the requested locale when it is valid (vi)', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('vi'),
      });
      expect(result.locale).toBe('vi');
    });

    it('uses the requested locale when it is valid (en)', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('en'),
      });
      expect(result.locale).toBe('en');
    });

    it('falls back to default locale (vi) when requestLocale is undefined', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve(undefined),
      });
      expect(result.locale).toBe('vi');
    });

    it('falls back to default locale (vi) when requestLocale is empty string', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve(''),
      });
      expect(result.locale).toBe('vi');
    });

    it('falls back to default locale (vi) for an invalid locale', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('fr'),
      });
      expect(result.locale).toBe('vi');
    });

    it('falls back to default locale (vi) for another invalid locale', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('ja'),
      });
      expect(result.locale).toBe('vi');
    });
  });

  describe('message loading', () => {
    it('loads Vietnamese messages for vi locale', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('vi'),
      });
      expect(result.messages).toBeDefined();
      expect((result.messages as Record<string, Record<string, string>>).common.loading).toBe('Đang tải...');
    });

    it('loads English messages for en locale', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('en'),
      });
      expect(result.messages).toBeDefined();
      expect((result.messages as Record<string, Record<string, string>>).common.loading).toBe('Loading...');
    });

    it('loads Vietnamese messages when falling back from invalid locale', async () => {
      const result = await capturedConfigFn!({
        requestLocale: Promise.resolve('fr'),
      });
      expect(result.locale).toBe('vi');
      expect((result.messages as Record<string, Record<string, string>>).common.loading).toBe('Đang tải...');
    });
  });
});
