import {Injectable, Logger} from '@nestjs/common';
import {ConfigService} from '@nestjs/config';
import googleTrends from '@shaivpidadi/trends-js';
import {TrendItem, CollectorResult} from '../../common/interfaces/trend-item.interface';
import {_JsonParseSafe} from "../../shared/helper";

@Injectable()
export class GoogleTrendsService {
    private readonly logger = new Logger(GoogleTrendsService.name);

    constructor(private readonly configService: ConfigService) {
    }

    async collect(googleTrendsGeo: string = 'JP'): Promise<CollectorResult> {
        const start = Date.now();
        const items: TrendItem[] = [];
        const errors: string[] = [];

        // 1. Daily trends
        try {
            const daily = await this.getDailyTrends(googleTrendsGeo);
            items.push(...daily);
        } catch (e) {
            errors.push(`dailyTrends: ${e.message}`);
        }

        // 2. Real-time trends (nếu available)
        try {
            // const realtime = await this.getRealtimeTrends();
            // items.push(...realtime);
        } catch (e) {
            errors.push(`realtimeTrends: ${e.message}`);
        }

        return {
            source: 'google-trends',
            items,
            collectedAt: new Date(),
            durationMs: Date.now() - start,
            error: errors.length > 0 ? errors.join('; ') : undefined,
        };
    }

    /**
     * Daily trending searches — 100% FREE
     */
    private async getDailyTrends(googleTrendsGeo: string = 'JP'): Promise<TrendItem[]> {
        console.debug('google-trends:getDailyTrends :'+googleTrendsGeo);
        const {data: results} = await googleTrends.dailyTrends({
            trendDate: new Date(),
            geo: googleTrendsGeo,
        });

        // const parsed = _JsonParseSafe(results);

        const days = results.allTrendingStories || [];
        // const days = results.s || [];
        console.log(days);
        const allTrends = days.splice(0,15).map((trend) => {
                const article = trend.articles?.[0];
                const traffic = trend.formattedTraffic || '0';
                const trafficNum = this.parseTraffic(traffic);

                return {
                    source: 'google-trends:daily',
                    title: trend.title || '',
                    description: article?.snippet || trend.title || '',
                    url: article?.url || `https://trends.google.com/trends/explore?q=${encodeURIComponent(trend.title || '')}`,
                    score: 10,//this.calculateScore(trafficNum, index),
                    timestamp: new Date(),
                    category: this.detectCategory(trend),
                    tags: (trend.relatedQueries || [])
                        .map((q: any) => q.query)
                        .slice(0, 5),
                    engagement: {
                        views: trafficNum,
                    },
                    raw: {
                        formattedTraffic: traffic,
                        image: trend.image,
                        articles: (trend.articles || []).map((a: any) => ({
                            title: a.title,
                            url: a.url,
                            source: a.source,
                        })),
                    },
                };
            }
        );

        this.logger.log(`Google Trends daily: ${allTrends.length} items`);
        return allTrends;
    }

    /**
     * Realtime trending topics
     */
    private async getRealtimeTrends(googleTrendsGeo: string = 'JP'): Promise<TrendItem[]> {
        try {
            console.debug('google-trends:getRealtimeTrends');
            const results = await googleTrends.realTimeTrends({
                geo: googleTrendsGeo,
                category: 'all',
            });

            const parsed = JSON.parse(results);
            const stories = parsed.storySummaries?.trendingStories || [];

            const items: TrendItem[] = stories.map((story: any, index: number) => ({
                source: 'google-trends:realtime',
                title: story.title || story.entityNames?.join(', ') || '',
                description: story.articles?.[0]?.articleTitle || '',
                url: story.articles?.[0]?.url || '',
                score: Math.max(95 - index * 4, 10),
                timestamp: new Date(),
                tags: story.entityNames || [],
                engagement: {
                    shares: story.articles?.length || 0,
                },
                raw: {
                    entityNames: story.entityNames,
                    articleCount: story.articles?.length,
                },
            }));

            this.logger.log(`Google Trends realtime: ${items.length} items`);
            return items;
        } catch (error) {
            // realTimeTrends không phải lúc nào cũng available cho mọi geo
            this.logger.warn(`Realtime trends not available: ${error.message}`);
            return [];
        }
    }

    /**
     * Tra cứu interest cho 1 keyword cụ thể — dùng cho scoring
     */
    async getInterestScore(keyword: string, googleTrendsGeo: string = 'JP'): Promise<number> {
        try {
            const result = await googleTrends.interestByRegion({
                keyword,
                startTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
                geo: googleTrendsGeo,
            });
            const parsed = JSON.parse(result);
            const timeline = parsed.default?.timelineData || [];
            if (timeline.length === 0) return 0;

            return timeline[timeline.length - 1].value?.[0] || 0;
        } catch {
            return 0;
        }
    }

    private parseTraffic(formatted: string): number {
        // "200K+" → 200000, "1M+" → 1000000
        const clean = formatted.replace(/[+,]/g, '').trim();
        const match = clean.match(/^(\d+(?:\.\d+)?)\s*(K|M|B)?$/i);
        if (!match) return 0;

        const num = parseFloat(match[1]);
        const unit = (match[2] || '').toUpperCase();
        const multipliers: Record<string, number> = {K: 1000, M: 1000000, B: 1000000000};
        return Math.round(num * (multipliers[unit] || 1));
    }

    private calculateScore(traffic: number, index: number): number {
        // Kết hợp traffic volume + ranking position
        const trafficScore = traffic > 0 ? Math.min(Math.log10(traffic) * 15, 60) : 30;
        const positionScore = Math.max(40 - index * 3, 0);
        return Math.min(Math.round(trafficScore + positionScore), 100);
    }

    private detectCategory(trend: any): string {
        // Basic category detection dựa trên articles
        const sources = (trend.articles || [])
            .map((a: any) => (a.source || '').toLowerCase())
            .join(' ');

        if (/sport|bóng|goal|fifa|nfl|nba/i.test(sources)) return 'sports';
        if (/tech|crypto|ai|apple|google|meta/i.test(sources)) return 'tech';
        if (/politic|chính trị|quốc hội/i.test(sources)) return 'politics';
        return 'general';
    }
}
