/**
 * Blog utility functions
 * This file contains common functions used across blog components
 */

import { type BlogPost, type Lang } from '@/types';
import { defaultLang } from '@/i18n/ui';

/**
 * Get blog posts based on language
 * @param lang - Current language
 * @param postsGlob - Object containing imported posts from glob
 * @returns Processed blog posts array
 */
export async function getBlogPosts(lang: Lang, postsGlob: Record<string, any>): Promise<BlogPost[]> {
  // Get posts based on language
  let allPosts = [];
  
  if (lang === 'zh') {
    allPosts = postsGlob.zh;
  } else {
    allPosts = postsGlob.en;
  }
  
  // Process blog post data
  const posts: BlogPost[] = allPosts.map((post: any) => {
    const slug = post.url?.split('/').filter(Boolean).pop() || '';
    
    // Default image if not specified in frontmatter
    const defaultImage = "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&h=250&fit=crop&crop=center";
    
    return {
      title: post.frontmatter.title,
      description: post.frontmatter.description || '',
      image: post.frontmatter.image || defaultImage,
      slug: slug,
      tags: post.frontmatter.tags || [],
      tagId: post.frontmatter.tagId || [],
      category: Array.isArray(post.frontmatter.category) ? post.frontmatter.category : post.frontmatter.category ? [post.frontmatter.category] : [],
      categoryId: Array.isArray(post.frontmatter.categoryId) ? post.frontmatter.categoryId : post.frontmatter.categoryId ? [post.frontmatter.categoryId] : [],
      date: post.frontmatter.date || post.frontmatter.pubDate || '',
      readTime: post.frontmatter.readTime || post.frontmatter.readingTime || '5 min read',
      url: post.url || '',
    };
  });
  
  return posts;
}

/**
 * Sort blog posts by date (newest first)
 * @param posts - Array of blog posts
 * @returns Sorted array of blog posts
 */
export function sortPostsByDate(posts: BlogPost[]): BlogPost[] {
  return posts
    .filter(post => post.date) // Filter out posts without dates
    .sort((a, b) => {
      const dateA = new Date(a.date).getTime();
      const dateB = new Date(b.date).getTime();
      return dateB - dateA; // Descending order, newest first
    });
}

/**
 * Filter posts by category
 * @param posts - Array of blog posts
 * @param category - Category to filter by
 * @returns Filtered array of blog posts
 */
export function filterPostsByCategory(posts: BlogPost[], category: string): BlogPost[] {
  if (!category) return posts;
  
  return posts.filter(post => {
    // First check if post contains the current category ID
    if (post.categoryId && Array.isArray(post.categoryId)) {
      return post.categoryId.some(catId => 
        catId.toLowerCase() === category.toLowerCase()
      );
    }
    // If no categoryId, check category
    else if (post.category && Array.isArray(post.category)) {
      return post.category.some(cat => 
        cat.toLowerCase() === category.toLowerCase()
      );
    }
    return false;
  });
}

/**
 * Filter posts by tag
 * @param posts - Array of blog posts
 * @param tag - Tag to filter by
 * @returns Filtered array of blog posts
 */
export function filterPostsByTag(posts: BlogPost[], tag: string): BlogPost[] {
  if (!tag) return posts;
  
  return posts.filter(post => {
    // First check if post contains the current tag ID
    if (post.tagId && Array.isArray(post.tagId)) {
      return post.tagId.some(tagId => 
        tagId.toLowerCase() === tag.toLowerCase()
      );
    }
    // If no tagId, check tags
    else if (post.tags && Array.isArray(post.tags)) {
      return post.tags.some(postTag => 
        postTag.toLowerCase() === tag.toLowerCase()
      );
    }
    return false;
  });
}

/**
 * Extract categories from posts
 * @param posts - Array of blog posts
 * @returns Map of category names to category IDs
 */
export function extractCategories(posts: any[]): Map<string, string> {
  const allCategories = new Set<string>();
  const categoryMap = new Map<string, string>(); // Map of category name to ID

  posts.forEach(post => {
    // Process categories
    if (post.frontmatter?.category) {
      const categories = Array.isArray(post.frontmatter.category) 
        ? post.frontmatter.category 
        : [post.frontmatter.category];
      
      const categoryIds = Array.isArray(post.frontmatter.categoryId) 
        ? post.frontmatter.categoryId 
        : post.frontmatter.categoryId ? [post.frontmatter.categoryId] : [];
      
      // If categoryId exists, use mapping between categoryId and category
      if (categoryIds.length > 0 && categoryIds.length === categories.length) {
        categories.forEach((cat: string, index: number) => {
          if (cat && categoryIds[index]) {
            allCategories.add(cat);
            categoryMap.set(cat, categoryIds[index]);
          }
        });
      } else {
        // If no categoryId or lengths don't match, use category name as ID
        categories.forEach((cat: string) => {
          if (cat) {
            allCategories.add(cat);
            categoryMap.set(cat, cat.toLowerCase());
          }
        });
      }
    }
  });

  return categoryMap;
}

/**
 * Extract tags from posts
 * @param posts - Array of blog posts
 * @returns Map of tag names to tag IDs
 */
export function extractTags(posts: any[]): Map<string, string> {
  const allTags = new Set<string>();
  const tagMap = new Map<string, string>(); // Map of tag name to ID

  posts.forEach(post => {
    // Process tags
    if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
      const tags = post.frontmatter.tags;
      const tagIds = Array.isArray(post.frontmatter.tagId) 
        ? post.frontmatter.tagId 
        : post.frontmatter.tagId ? [post.frontmatter.tagId] : [];
      
      // If tagId exists, use mapping between tagId and tag
      if (tagIds.length > 0 && tagIds.length === tags.length) {
        tags.forEach((tag: string, index: number) => {
          if (tag && tagIds[index]) {
            allTags.add(tag);
            tagMap.set(tag, tagIds[index]);
          }
        });
      } else {
        // If no tagId or lengths don't match, use tag name as ID
        tags.forEach((tag: string) => {
          if (tag) {
            allTags.add(tag);
            tagMap.set(tag, tag.toLowerCase());
          }
        });
      }
    }
  });

  return tagMap;
}

/**
 * Get base URL for blog based on language
 * @param lang - Current language
 * @returns Base URL string
 */
export function getBlogBaseUrl(lang: Lang): string {
  return lang === defaultLang ? '/blog' : `/${lang}/blog`;
}

/**
 * Process raw blog post data from import.meta.glob
 * @param allPosts - Raw posts data from import.meta.glob
 * @param lang - Current language
 * @returns Processed blog posts array
 */
export function processRawBlogPosts(allPosts: Record<string, any>[] | any[], lang: Lang): BlogPost[] {
  // Process blog post data
  const posts: BlogPost[] = allPosts.map((post: any) => {
    const slug = post.url?.split('/').filter(Boolean).pop() || '';
    
    // Default image if not specified in frontmatter
    const defaultImage = "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&h=250&fit=crop&crop=center";
    
    // Default read time text based on language
    const defaultReadTime = lang === 'zh' ? '5 分钟阅读' : '5 min read';
    
    return {
      title: post.frontmatter.title,
      description: post.frontmatter.description || '',
      image: post.frontmatter.image || defaultImage,
      slug: slug,
      tags: post.frontmatter.tags || [],
      tagId: post.frontmatter.tagId || [],
      category: Array.isArray(post.frontmatter.category) ? post.frontmatter.category : post.frontmatter.category ? [post.frontmatter.category] : [],
      categoryId: Array.isArray(post.frontmatter.categoryId) ? post.frontmatter.categoryId : post.frontmatter.categoryId ? [post.frontmatter.categoryId] : [],
      date: post.frontmatter.date || post.frontmatter.pubDate || '',
      readTime: post.frontmatter.readTime || post.frontmatter.readingTime || defaultReadTime,
      url: post.url || '',
    };
  });
  
  return posts;
}

/**
 * Extract post metadata for categories and tags
 * @param posts - Array of blog posts
 * @returns Array of post metadata
 */
export function extractPostMetadata(posts: any[]) {
  return posts.map((post: any) => ({
    category: post.frontmatter?.category || [],
    categoryId: post.frontmatter?.categoryId || [],
    tags: post.frontmatter?.tags || [],
    tagId: post.frontmatter?.tagId || []
  }));
}

/**
 * Get all blog posts with processing for a taxonomy page (category or tag)
 * @param lang - Current language
 * @param options - Additional options for processing
 * @returns Object containing processed posts and metadata
 */
export async function getTaxonomyPageData(lang: Lang, options?: {
  category?: string;
  tag?: string;
}) {
  // Read all blog posts
  // Note: import.meta.glob only accepts literal strings, not variables
  let allPosts;
  
  // Use specific glob patterns based on language
  if (lang === 'zh') {
    allPosts = await import.meta.glob('/src/pages/zh/blog/posts/*.{md,mdx}', { eager: true });
  } else {
    allPosts = await import.meta.glob('/src/pages/blog/posts/*.{md,mdx}', { eager: true });
  }
  
  // Process blog post data
  const blogPosts = processRawBlogPosts(Object.values(allPosts), lang);
  
  // Apply filters if specified
  let filteredPosts = blogPosts;
  
  if (options?.category) {
    filteredPosts = filterPostsByCategory(filteredPosts, options.category);
  }
  
  if (options?.tag) {
    filteredPosts = filterPostsByTag(filteredPosts, options.tag);
  }
  
  // Sort posts by date
  const sortedBlogPosts = sortPostsByDate(filteredPosts);
  
  // Extract categories and tags from all posts for sidebar
  const allPostsMetadata = extractPostMetadata(Object.values(allPosts));
  
  // Get categories and tags for sidebar
  const categories = extractCategories(allPostsMetadata);
  const tags = extractTags(allPostsMetadata);
  
  return {
    posts: sortedBlogPosts,
    categories,
    tags,
    allPosts
  };
}