const News = require('../models/News');
const NewsCategory = require('../models/NewsCategory');
const NewsSource = require('../models/NewsSource');
const newsService = require('../services/newsService');

// Get all news with pagination and filtering
const getNews = async (req, res) => {
    try {
        const {
            category,
            source,
            page = 1,
            limit = 20,
            sortBy = 'publishedAt',
            sortOrder = 'desc',
            forceRefresh = false
        } = req.query;

        // Use newsService.getNews with force refresh if requested
        const result = await newsService.getNews(
            category, 
            parseInt(page), 
            parseInt(limit), 
            forceRefresh === 'true' || forceRefresh === true
        );

        res.json({
            success: true,
            data: result
        });
    } catch (error) {
        console.error('Get news error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch news',
            error: error.message
        });
    }
};

// Get news by category
const getNewsByCategory = async (req, res) => {
    try {
        const { category } = req.params;
        const { page = 1, limit = 20 } = req.query;

        const news = await News.getByCategory(category, parseInt(page), parseInt(limit));
        const total = await News.countDocuments({ category, isActive: true });

        res.json({
            success: true,
            data: {
                news,
                pagination: {
                    page: parseInt(page),
                    limit: parseInt(limit),
                    total,
                    pages: Math.ceil(total / limit)
                }
            }
        });
    } catch (error) {
        console.error('Get news by category error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch news by category',
            error: error.message
        });
    }
};

// Get news by source
const getNewsBySource = async (req, res) => {
    try {
        const { source } = req.params;
        const { page = 1, limit = 20 } = req.query;

        const news = await News.find({ source, isActive: true })
            .sort({ publishedAt: -1 })
            .skip((page - 1) * limit)
            .limit(parseInt(limit));

        const total = await News.countDocuments({ source, isActive: true });

        res.json({
            success: true,
            data: {
                news,
                pagination: {
                    page: parseInt(page),
                    limit: parseInt(limit),
                    total,
                    pages: Math.ceil(total / limit)
                }
            }
        });
    } catch (error) {
        console.error('Get news by source error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch news by source',
            error: error.message
        });
    }
};

// Search news
const searchNews = async (req, res) => {
    try {
        const { q: query, page = 1, limit = 20 } = req.query;

        if (!query || query.trim().length < 2) {
            return res.status(400).json({
                success: false,
                message: 'Search query must be at least 2 characters long'
            });
        }

        const result = await newsService.searchNews(query, parseInt(page), parseInt(limit));

        res.json({
            success: true,
            data: result
        });
    } catch (error) {
        console.error('Search news error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to search news',
            error: error.message
        });
    }
};

// Get single news article
const getNewsById = async (req, res) => {
    try {
        const { id } = req.params;

        const news = await News.findById(id);
        if (!news) {
            return res.status(404).json({
                success: false,
                message: 'News article not found'
            });
        }

        // Increment view count
        news.viewCount += 1;
        await news.save();

        res.json({
            success: true,
            data: news
        });
    } catch (error) {
        console.error('Get news by ID error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch news article',
            error: error.message
        });
    }
};

// Get full article content (scrape from original URL)
const getFullArticleContent = async (req, res) => {
    try {
        const { id } = req.params;
        const axios = require('axios');
        const cheerio = require('cheerio');

        const news = await News.findById(id);
        if (!news) {
            return res.status(404).json({
                success: false,
                message: 'News article not found'
            });
        }

        // If we already have full content, return it
        if (news.content && news.content.length > 500) {
            return res.json({
                success: true,
                data: {
                    id: news._id,
                    title: news.title,
                    content: news.content,
                    url: news.url,
                    source: news.source,
                    publishedAt: news.publishedAt
                }
            });
        }

        // Try to scrape content from the original URL
        try {
            console.log(`🔍 Scraping content from: ${news.url}`);
            const response = await axios.get(news.url, {
                timeout: 30000,
                headers: {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
                }
            });

            const $ = cheerio.load(response.data);
            
            // Try different selectors to find article content
            let content = '';
            
            // Common article content selectors
            const selectors = [
                'article',
                '.article-content',
                '.post-content',
                '.entry-content',
                '.content',
                '.story-body',
                '.article-body',
                '[role="main"]',
                'main',
                '.post',
                '.entry'
            ];

            for (const selector of selectors) {
                const element = $(selector);
                if (element.length > 0) {
                    content = element.text().trim();
                    if (content.length > 200) {
                        break;
                    }
                }
            }

            // If no specific content found, try to get paragraphs
            if (!content || content.length < 200) {
                const paragraphs = $('p').map((i, el) => $(el).text().trim()).get();
                content = paragraphs.join('\n\n');
            }

            // Clean up the content
            content = content
                .replace(/\s+/g, ' ')
                .replace(/\n\s*\n/g, '\n\n')
                .trim();

            // Update the article with full content
            if (content.length > 200) {
                news.content = content;
                news.wordCount = content.split(/\s+/).length;
                news.readingTime = Math.ceil(news.wordCount / 200); // 200 words per minute
                await news.save();
            }

            res.json({
                success: true,
                data: {
                    id: news._id,
                    title: news.title,
                    content: content || news.content || 'Content not available',
                    url: news.url,
                    source: news.source,
                    publishedAt: news.publishedAt,
                    wordCount: news.wordCount,
                    readingTime: news.readingTime
                }
            });

        } catch (scrapeError) {
            console.error('Scraping error:', scrapeError.message);
            
            // Return what we have
            res.json({
                success: true,
                data: {
                    id: news._id,
                    title: news.title,
                    content: news.content || 'Content not available. Please visit the original article.',
                    url: news.url,
                    source: news.source,
                    publishedAt: news.publishedAt,
                    note: 'Unable to fetch full content. Please visit the original article.'
                }
            });
        }

    } catch (error) {
        console.error('Get full article content error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch full article content',
            error: error.message
        });
    }
};

// Get news categories
const getCategories = async (req, res) => {
    try {
        const categories = await NewsCategory.getActiveCategories();
        
        // Get article count for each category
        const categoriesWithCount = await Promise.all(
            categories.map(async (category) => {
                const count = await News.countDocuments({ 
                    category: category.slug, 
                    isActive: true 
                });
                return {
                    ...category.toObject(),
                    articleCount: count
                };
            })
        );

        res.json({
            success: true,
            data: categoriesWithCount
        });
    } catch (error) {
        console.error('Get categories error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch categories',
            error: error.message
        });
    }
};

// Get news sources
const getSources = async (req, res) => {
    try {
        const sources = await NewsSource.getActiveSources();

        res.json({
            success: true,
            data: sources
        });
    } catch (error) {
        console.error('Get sources error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch sources',
            error: error.message
        });
    }
};

// Refresh news (fetch from APIs)
const refreshNews = async (req, res) => {
    try {
        const { categories } = req.body;

        console.log('Starting news refresh...');
        const result = await newsService.fetchAllNews(categories);

        res.json({
            success: true,
            message: 'News refresh completed',
            data: result
        });
    } catch (error) {
        console.error('Refresh news error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to refresh news',
            error: error.message
        });
    }
};

// Get trending news (most viewed)
const getTrendingNews = async (req, res) => {
    try {
        const { limit = 10, days = 7 } = req.query;

        const dateLimit = new Date();
        dateLimit.setDate(dateLimit.getDate() - parseInt(days));

        const news = await News.find({
            isActive: true,
            publishedAt: { $gte: dateLimit }
        })
        .sort({ viewCount: -1, publishedAt: -1 })
        .limit(parseInt(limit));

        res.json({
            success: true,
            data: news
        });
    } catch (error) {
        console.error('Get trending news error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch trending news',
            error: error.message
        });
    }
};

// Get latest news
const getLatestNews = async (req, res) => {
    try {
        const { limit = 20 } = req.query;

        const news = await News.find({ isActive: true })
            .sort({ publishedAt: -1 })
            .limit(parseInt(limit));

        res.json({
            success: true,
            data: news
        });
    } catch (error) {
        console.error('Get latest news error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch latest news',
            error: error.message
        });
    }
};

// Get news statistics
const getNewsStats = async (req, res) => {
    try {
        const totalArticles = await News.countDocuments({ isActive: true });
        const totalCategories = await NewsCategory.countDocuments({ isActive: true });
        const totalSources = await NewsSource.countDocuments({ isActive: true });

        // Get articles by category
        const articlesByCategory = await News.aggregate([
            { $match: { isActive: true } },
            { $group: { _id: '$category', count: { $sum: 1 } } },
            { $sort: { count: -1 } }
        ]);

        // Get articles by source
        const articlesBySource = await News.aggregate([
            { $match: { isActive: true } },
            { $group: { _id: '$source', count: { $sum: 1 } } },
            { $sort: { count: -1 } }
        ]);

        // Get recent articles (last 24 hours)
        const yesterday = new Date();
        yesterday.setDate(yesterday.getDate() - 1);
        const recentArticles = await News.countDocuments({
            isActive: true,
            publishedAt: { $gte: yesterday }
        });

        res.json({
            success: true,
            data: {
                totalArticles,
                totalCategories,
                totalSources,
                recentArticles,
                articlesByCategory,
                articlesBySource
            }
        });
    } catch (error) {
        console.error('Get news stats error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch news statistics',
            error: error.message
        });
    }
};

// Clear news cache
const clearCache = async (req, res) => {
    try {
        newsService.clearCache();
        
        res.json({
            success: true,
            message: 'News cache cleared successfully'
        });
    } catch (error) {
        console.error('Clear cache error:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to clear cache',
            error: error.message
        });
    }
};

module.exports = {
    getNews,
    getNewsByCategory,
    getNewsBySource,
    searchNews,
    getNewsById,
    getFullArticleContent,
    getCategories,
    getSources,
    refreshNews,
    getTrendingNews,
    getLatestNews,
    getNewsStats,
    clearCache
};
