const axios = require('axios');
const Parser = require('rss-parser');
const News = require('../models/News');
const NewsSource = require('../models/NewsSource');
const NewsCategory = require('../models/NewsCategory');

class NewsService {
    constructor() {
        this.parser = new Parser();
        this.cache = new Map();
        this.cacheTimeout = 5 * 60 * 1000; // 5 minutes
    }

    // NewsAPI integration
    async fetchFromNewsAPI(category = 'general', pageSize = 100) {
        try {
            const apiKey = '4a039be72844448a9adcd837fb920bbc';
            const baseUrl = 'https://newsapi.org/v2/everything';
            
            // Map our categories to NewsAPI categories
            const categoryMapping = {
                'career-and-skills': 'career',
                'technology': 'technology',
                'startups-and-innovation': 'business',
                'education': 'education',
                'sports': 'sports',
                'movies-and-entertainment': 'entertainment',
                'business-and-economy': 'business',
                'politics': 'politics',
                'health-and-wellness': 'health',
                'environment-and-climate': 'science',
                'art-and-culture': 'entertainment'
            };

            const query = categoryMapping[category] || 'general';
            
            console.log(`🔄 Fetching from NewsAPI for category: ${category}`);
            
            const response = await axios.get(baseUrl, {
                params: {
                    q: query,
                    apiKey: apiKey,
                    pageSize: Math.min(pageSize, 50), // Limit to 50 to avoid rate limits
                    sortBy: 'publishedAt',
                    language: 'en'
                },
                timeout: 60000 // Increased to 60 seconds
            });

            if (response.data.status === 'ok') {
                const articles = this.processNewsAPIArticles(response.data.articles, category);
                console.log(`✅ NewsAPI returned ${articles.length} articles for ${category}`);
                return articles;
            } else {
                throw new Error(`NewsAPI error: ${response.data.message}`);
            }
        } catch (error) {
            console.error(`❌ NewsAPI fetch error for ${category}:`, error.message);
            // Return empty array instead of throwing to continue with other sources
            return [];
        }
    }

    // Currents API integration
    async fetchFromCurrents(category = 'general', pageSize = 100) {
        try {
            const apiKey = 'OwUf8-lpvINu6cfU20IfxPNxlEO9oYYZnch-3l-k6afTJ0Xu';
            const baseUrl = 'https://api.currentsapi.services/v1/search';
            
            // Map our categories to Currents categories
            const categoryMapping = {
                'career-and-skills': 'career',
                'technology': 'technology',
                'startups-and-innovation': 'business',
                'education': 'education',
                'sports': 'sports',
                'movies-and-entertainment': 'entertainment',
                'business-and-economy': 'business',
                'politics': 'politics',
                'health-and-wellness': 'health',
                'environment-and-climate': 'science',
                'art-and-culture': 'entertainment'
            };

            const query = categoryMapping[category] || 'general';
            
            console.log(`🔄 Fetching from Currents API for category: ${category}`);
            
            const response = await axios.get(baseUrl, {
                params: {
                    apiKey: apiKey,
                    keywords: query,
                    language: 'en',
                    limit: Math.min(pageSize, 50) // Limit to 50 to avoid timeouts
                },
                timeout: 60000 // Increased to 60 seconds
            });

            if (response.data.status === 'ok') {
                const articles = this.processCurrentsArticles(response.data.news, category);
                console.log(`✅ Currents API returned ${articles.length} articles for ${category}`);
                return articles;
            } else {
                throw new Error(`Currents API error: ${response.data.message}`);
            }
        } catch (error) {
            console.error(`❌ Currents API fetch error for ${category}:`, error.message);
            // Return empty array instead of throwing to continue with other sources
            return [];
        }
    }

    // RSS Feed integration
    async fetchFromRSS(rssUrl, category) {
        try {
            const feed = await this.parser.parseURL(rssUrl);
            return this.processRSSArticles(feed.items, category);
        } catch (error) {
            console.error('RSS fetch error:', error.message);
            throw error;
        }
    }

    // Process NewsAPI articles
    processNewsAPIArticles(articles, category) {
        return articles.map(article => ({
            title: article.title,
            description: article.description,
            content: article.content,
            url: article.url,
            imageUrl: article.urlToImage,
            source: 'newsapi',
            sourceName: article.source.name,
            category: category, // This should already be the correct internal category
            publishedAt: new Date(article.publishedAt),
            author: article.author,
            tags: this.extractTags(article.title + ' ' + article.description)
        }));
    }

    // Process Currents API articles
    processCurrentsArticles(articles, category) {
        return articles.map(article => ({
            title: article.title,
            description: article.description,
            content: article.content,
            url: article.url,
            imageUrl: article.image,
            source: 'currents',
            sourceName: article.author || 'Currents API',
            category: category, // This should already be the correct internal category
            publishedAt: new Date(article.published),
            author: article.author,
            tags: this.extractTags(article.title + ' ' + article.description)
        }));
    }

    // Process RSS articles
    processRSSArticles(items, category) {
        return items.map(item => ({
            title: item.title,
            description: item.contentSnippet || item.content,
            content: item.content,
            url: item.link,
            imageUrl: this.extractImageFromContent(item.content),
            source: 'rss',
            sourceName: 'RSS Feed',
            category: category,
            publishedAt: new Date(item.pubDate),
            author: item.creator,
            tags: this.extractTags(item.title + ' ' + item.contentSnippet)
        }));
    }

    // Extract tags from content
    extractTags(content) {
        if (!content) return [];
        
        const commonWords = ['the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'may', 'might', 'can', 'this', 'that', 'these', 'those'];
        
        const words = content.toLowerCase()
            .replace(/[^\w\s]/g, ' ')
            .split(/\s+/)
            .filter(word => word.length > 3 && !commonWords.includes(word))
            .slice(0, 10); // Limit to 10 tags
        
        return [...new Set(words)]; // Remove duplicates
    }

    // Extract image from RSS content
    extractImageFromContent(content) {
        if (!content) return null;
        
        const imgMatch = content.match(/<img[^>]+src="([^"]+)"/i);
        return imgMatch ? imgMatch[1] : null;
    }

    // Auto-categorize articles based on content
    categorizeArticle(title, description, content) {
        const text = `${title} ${description} ${content}`.toLowerCase();
        
        const categoryKeywords = {
            'career-and-skills': ['job', 'career', 'skill', 'employment', 'work', 'professional', 'resume', 'interview', 'hiring', 'recruitment', 'vacancy', 'position', 'opportunity'],
            'technology': ['tech', 'software', 'programming', 'ai', 'artificial intelligence', 'machine learning', 'coding', 'developer', 'app', 'digital', 'computer', 'internet', 'cyber', 'data', 'algorithm'],
            'startups-and-innovation': ['startup', 'innovation', 'entrepreneur', 'venture', 'funding', 'investor', 'disrupt', 'unicorn', 'incubator', 'accelerator'],
            'education': ['education', 'school', 'university', 'college', 'student', 'learning', 'academic', 'degree', 'course', 'teacher', 'professor', 'campus'],
            'sports': ['sport', 'football', 'basketball', 'cricket', 'tennis', 'olympic', 'championship', 'match', 'game', 'athlete', 'team', 'league'],
            'movies-and-entertainment': ['movie', 'film', 'cinema', 'entertainment', 'actor', 'actress', 'hollywood', 'bollywood', 'music', 'song', 'concert', 'theater', 'drama'],
            'business-and-economy': ['business', 'economy', 'market', 'stock', 'finance', 'banking', 'investment', 'revenue', 'profit', 'company', 'corporate', 'trading', 'economic', 'financial'],
            'politics': ['politics', 'government', 'election', 'minister', 'president', 'parliament', 'policy', 'democracy', 'political', 'vote', 'campaign', 'senate', 'congress'],
            'astrology': ['astrology', 'horoscope', 'zodiac', 'star', 'planet', 'moon', 'sun', 'astrological', 'constellation', 'cosmic'],
            'health-and-wellness': ['health', 'medical', 'doctor', 'hospital', 'medicine', 'wellness', 'fitness', 'diet', 'nutrition', 'healthcare', 'treatment', 'therapy'],
            'environment-and-climate': ['environment', 'climate', 'global warming', 'pollution', 'green', 'sustainable', 'renewable', 'carbon', 'ecology', 'conservation'],
            'art-and-culture': ['art', 'culture', 'museum', 'gallery', 'painting', 'sculpture', 'literature', 'poetry', 'theater', 'cultural', 'heritage', 'exhibition'],
            'knowledge-bytes-and-facts': ['fact', 'knowledge', 'science', 'research', 'study', 'discovery', 'breakthrough', 'innovation', 'scientific', 'experiment', 'theory'],
            'jobs': ['job', 'career', 'employment', 'hiring', 'recruitment', 'vacancy', 'position', 'opportunity', 'workplace', 'career']
        };

        let bestMatch = 'technology'; // Default to technology instead of general
        let maxScore = 0;

        for (const [category, keywords] of Object.entries(categoryKeywords)) {
            let score = 0;
            keywords.forEach(keyword => {
                if (text.includes(keyword)) {
                    score++;
                }
            });
            
            if (score > maxScore) {
                maxScore = score;
                bestMatch = category;
            }
        }

        // If no keywords matched, try to detect category from common patterns
        if (maxScore === 0) {
            if (text.includes('stock') || text.includes('market') || text.includes('financial') || text.includes('investment')) {
                bestMatch = 'business-and-economy';
            } else if (text.includes('tech') || text.includes('software') || text.includes('digital')) {
                bestMatch = 'technology';
            } else if (text.includes('sport') || text.includes('game') || text.includes('team')) {
                bestMatch = 'sports';
            } else if (text.includes('movie') || text.includes('film') || text.includes('entertainment')) {
                bestMatch = 'movies-and-entertainment';
            } else if (text.includes('health') || text.includes('medical') || text.includes('doctor')) {
                bestMatch = 'health-and-wellness';
            } else if (text.includes('education') || text.includes('school') || text.includes('university')) {
                bestMatch = 'education';
            } else if (text.includes('politics') || text.includes('government') || text.includes('election')) {
                bestMatch = 'politics';
            } else {
                bestMatch = 'technology'; // Default fallback
            }
        }

        return bestMatch;
    }

    // Save articles to database
    async saveArticles(articles) {
        const savedArticles = [];
        const errors = [];

        console.log(`📝 Processing ${articles.length} articles...`);

        for (const article of articles) {
            try {
                // Check if article already exists
                const existingArticle = await News.findOne({ url: article.url });
                if (existingArticle) {
                    console.log(`⚠️ Duplicate article skipped: ${article.title}`);
                    continue; // Skip duplicate
                }

                // Auto-categorize if not provided
                if (!article.category || article.category === 'general') {
                    article.category = this.categorizeArticle(
                        article.title, 
                        article.description, 
                        article.content
                    );
                }
                
                // Ensure category is valid, fallback to 'technology' if not
                const validCategories = [
                    'career-and-skills', 'technology', 'startups-and-innovation',
                    'education', 'sports', 'movies-and-entertainment',
                    'business-and-economy', 'politics', 'astrology',
                    'health-and-wellness', 'environment-and-climate',
                    'art-and-culture', 'knowledge-bytes-and-facts', 'jobs'
                ];
                
                if (!validCategories.includes(article.category)) {
                    console.log(`⚠️ Invalid category '${article.category}', defaulting to 'technology'`);
                    article.category = 'technology';
                }

                // Generate hash for deduplication
                const crypto = require('crypto');
                const hashString = `${article.title || ''}-${article.source || ''}-${article.publishedAt || ''}-${article.url || ''}`;
                article.hash = crypto.createHash('md5').update(hashString).digest('hex');

                // Ensure required fields are present
                if (!article.title || !article.url || !article.publishedAt) {
                    console.log(`⚠️ Skipping article with missing required fields: ${article.title}`);
                    continue;
                }

                // Truncate author name if too long
                if (article.author && article.author.length > 200) {
                    article.author = article.author.substring(0, 197) + '...';
                }

                // Create new article
                const newsArticle = new News(article);
                await newsArticle.save();
                savedArticles.push(newsArticle);
                console.log(`✅ Saved article: ${article.title}`);
            } catch (error) {
                console.error('Error saving article:', error.message);
                console.error('Article data:', {
                    title: article.title,
                    url: article.url,
                    source: article.source,
                    category: article.category
                });
                errors.push({ article: article.title, error: error.message });
            }
        }

        console.log(`📊 Saved ${savedArticles.length} articles, ${errors.length} errors`);
        return { savedArticles, errors };
    }

    // Fetch and save news from all sources
    async fetchAllNews(categories = null) {
        const allCategories = categories || [
            'career-and-skills',
            'technology',
            'startups-and-innovation',
            'education',
            'sports',
            'movies-and-entertainment',
            'business-and-economy',
            'politics',
            'astrology',
            'health-and-wellness',
            'environment-and-climate',
            'art-and-culture',
            'knowledge-bytes-and-facts',
            'jobs'
        ];

        const results = {
            totalFetched: 0,
            totalSaved: 0,
            errors: [],
            sources: {}
        };

        for (const category of allCategories) {
            try {
                console.log(`Fetching news for category: ${category}`);
                
                // Fetch from NewsAPI
                try {
                    const newsApiArticles = await this.fetchFromNewsAPI(category, 50);
                    const { savedArticles, errors } = await this.saveArticles(newsApiArticles);
                    results.sources.newsapi = (results.sources.newsapi || 0) + savedArticles.length;
                    results.totalFetched += newsApiArticles.length;
                    results.totalSaved += savedArticles.length;
                    results.errors.push(...errors);
                } catch (error) {
                    console.error(`NewsAPI error for ${category}:`, error.message);
                    results.errors.push({ source: 'newsapi', category, error: error.message });
                }

                // Fetch from Currents API
                try {
                    const currentsArticles = await this.fetchFromCurrents(category, 50);
                    const { savedArticles, errors } = await this.saveArticles(currentsArticles);
                    results.sources.currents = (results.sources.currents || 0) + savedArticles.length;
                    results.totalFetched += currentsArticles.length;
                    results.totalSaved += savedArticles.length;
                    results.errors.push(...errors);
                } catch (error) {
                    console.error(`Currents API error for ${category}:`, error.message);
                    results.errors.push({ source: 'currents', category, error: error.message });
                }

                // Add delay between requests to respect rate limits
                await new Promise(resolve => setTimeout(resolve, 1000));
            } catch (error) {
                console.error(`Error processing category ${category}:`, error.message);
                results.errors.push({ category, error: error.message });
            }
        }

        return results;
    }

    // Get cached news or fetch fresh
    async getNews(category = null, page = 1, limit = 20, forceRefresh = false) {
        const cacheKey = `news_${category}_${page}_${limit}`;
        
        // Skip cache if force refresh is requested
        if (!forceRefresh && this.cache.has(cacheKey)) {
            const cached = this.cache.get(cacheKey);
            if (Date.now() - cached.timestamp < this.cacheTimeout) {
                return cached.data;
            }
        }

        let query = { isActive: true };
        if (category) {
            query.category = category;
        }

        const news = await News.find(query)
            .sort({ publishedAt: -1 })
            .skip((page - 1) * limit)
            .limit(limit);

        const total = await News.countDocuments(query);

        const result = {
            news,
            pagination: {
                page,
                limit,
                total,
                pages: Math.ceil(total / limit)
            }
        };

        // Update cache with fresh data
        this.cache.set(cacheKey, {
            data: result,
            timestamp: Date.now()
        });

        return result;
    }

    // Search news
    async searchNews(query, page = 1, limit = 20) {
        const searchQuery = {
            $and: [
                { isActive: true },
                {
                    $or: [
                        { title: { $regex: query, $options: 'i' } },
                        { description: { $regex: query, $options: 'i' } },
                        { content: { $regex: query, $options: 'i' } },
                        { tags: { $in: [new RegExp(query, 'i')] } }
                    ]
                }
            ]
        };

        const news = await News.find(searchQuery)
            .sort({ publishedAt: -1 })
            .skip((page - 1) * limit)
            .limit(limit);

        const total = await News.countDocuments(searchQuery);

        return {
            news,
            pagination: {
                page,
                limit,
                total,
                pages: Math.ceil(total / limit)
            }
        };
    }

    // Clear cache
    clearCache() {
        this.cache.clear();
        console.log('🗑️ News cache cleared');
    }

    // Force refresh news data
    async forceRefreshNews(category = null) {
        console.log(`🔄 Force refreshing news for category: ${category || 'all'}`);
        
        // Clear cache first
        this.clearCache();
        
        // Fetch fresh news from APIs
        const results = await this.fetchAllNews(category ? [category] : null);
        
        console.log(`✅ Force refresh completed: ${results.totalSaved} new articles saved`);
        return results;
    }

    // Get news categories
    async getNewsCategories() {
        try {
            console.log('📂 Fetching news categories...');
            
            // Get categories from database with article counts
            const categories = await NewsCategory.find({ isActive: true })
                .sort({ sortOrder: 1, name: 1 });
            
            // Get article counts for each category
            const categoriesWithCounts = await Promise.all(
                categories.map(async (category) => {
                    const articleCount = await News.countDocuments({ 
                        category: category.slug, 
                        isActive: true 
                    });
                    
                    return {
                        _id: category._id,
                        id: category.slug,
                        name: category.name,
                        slug: category.slug,
                        description: category.description,
                        icon: category.icon,
                        color: category.color,
                        articleCount: articleCount,
                        isFollowing: false, // This would come from user preferences in a real app
                        isActive: category.isActive,
                        sortOrder: category.sortOrder,
                        keywords: category.keywords || [],
                        lastUpdated: category.updatedAt || category.createdAt
                    };
                })
            );
            
            console.log(`✅ Found ${categoriesWithCounts.length} categories`);
            return categoriesWithCounts;
        } catch (error) {
            console.error('❌ Error fetching categories:', error.message);
            throw error;
        }
    }
}

module.exports = new NewsService();
