import { describe, it, expect } from 'vitest';
import { getPostSlugs, getAvailableLocales, getPost, getAllPosts, LOCALES } from '@/lib/blog';

describe('lib/blog', () => {
  describe('LOCALES', () => {
    it('should include all supported locales', () => {
      expect(LOCALES).toContain('en');
      expect(LOCALES).toContain('pl');
      expect(LOCALES).toContain('fr');
      expect(LOCALES).toContain('es');
      expect(LOCALES).toHaveLength(4);
    });
  });

  describe('getPostSlugs', () => {
    it('should return slugs for English locale', () => {
      const slugs = getPostSlugs('en');
      expect(slugs).toContain('what-is-rss');
      expect(slugs.length).toBeGreaterThanOrEqual(1);
    });

    it('should return slugs for Polish locale', () => {
      const slugs = getPostSlugs('pl');
      expect(slugs).toContain('czym-jest-rss');
      expect(slugs.length).toBeGreaterThanOrEqual(1);
    });

    it('should return an empty array for a nonexistent locale', () => {
      const slugs = getPostSlugs('xx');
      expect(slugs).toEqual([]);
    });

    it('should only return .md and .mdx files as slugs', () => {
      for (const locale of LOCALES) {
        const slugs = getPostSlugs(locale);
        slugs.forEach((slug) => {
          expect(slug).not.toMatch(/\.(md|mdx)$/);
        });
      }
    });
  });

  describe('getAvailableLocales', () => {
    it('should find locales where a shared slug exists', () => {
      // "czym-jest-rss" only exists in pl
      const locales = getAvailableLocales('czym-jest-rss');
      expect(locales).toContain('pl');
    });

    it('should return empty array for a nonexistent slug', () => {
      const locales = getAvailableLocales('nonexistent-post-slug');
      expect(locales).toEqual([]);
    });
  });

  describe('getPost', () => {
    it('should return a fully parsed post for a valid slug', async () => {
      const post = await getPost('en', 'what-is-rss');
      expect(post).not.toBeNull();
      expect(post!.title).toBeTruthy();
      expect(post!.description).toBeTruthy();
      expect(post!.date).toBeTruthy();
      expect(post!.slug).toBe('what-is-rss');
      expect(post!.locale).toBe('en');
      expect(post!.contentHtml).toContain('<');
      expect(post!.availableLocales).toBeInstanceOf(Array);
    });

    it('should return null for a nonexistent slug', async () => {
      const post = await getPost('en', 'does-not-exist');
      expect(post).toBeNull();
    });

    it('should return null for a nonexistent locale', async () => {
      const post = await getPost('xx', 'what-is-rss');
      expect(post).toBeNull();
    });

    it('should render markdown content as HTML', async () => {
      const post = await getPost('en', 'what-is-rss');
      expect(post).not.toBeNull();
      // Should contain HTML tags from rendered markdown
      expect(post!.contentHtml).toMatch(/<(p|h[1-6]|ul|ol|a|em|strong)/);
    });
  });

  describe('getAllPosts', () => {
    it('should return posts sorted by date (newest first)', () => {
      const posts = getAllPosts('pl');
      expect(posts.length).toBeGreaterThanOrEqual(1);

      for (let i = 1; i < posts.length; i++) {
        const prevDate = new Date(posts[i - 1].date).getTime();
        const currDate = new Date(posts[i].date).getTime();
        expect(prevDate).toBeGreaterThanOrEqual(currDate);
      }
    });

    it('should return posts with required metadata fields', () => {
      for (const locale of LOCALES) {
        const posts = getAllPosts(locale);
        posts.forEach((post) => {
          expect(post.title).toBeTruthy();
          expect(typeof post.description).toBe('string');
          expect(post.date).toBeTruthy();
          expect(post.slug).toBeTruthy();
          expect(post.locale).toBe(locale);
          expect(post.availableLocales).toBeInstanceOf(Array);
        });
      }
    });

    it('should return an empty array for a nonexistent locale', () => {
      const posts = getAllPosts('xx');
      expect(posts).toEqual([]);
    });
  });
});
