// apps/api/src/services/intent.service.js

const axios = require('axios');
const cheerio = require('cheerio');
const axiosRetry = require('axios-retry').default;
const PUBLIC_SOURCES = require('../config/publicSources');

axiosRetry(axios, {
    retries: 3,
    retryDelay: axiosRetry.exponentialDelay,
    retryCondition: (error) => axiosRetry.isNetworkOrIdempotentRequestError(error)
});

class IntentService {
    constructor() {
        this.userAgents = [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
            'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
        ];

        // DEMAND SIGNALS: Someone explicitly looking to buy, hire, or locate a provider
        this.intentPhrases = [
            'need', 'needs', 'needed', 'require', 'requires', 'required',
            'looking for', 'searching for', 'in search of', 'seeking', 'seeks',
            'hire', 'hires', 'hiring', 'want to hire', 'looking to hire',
            'freelancer needed', 'contractor needed', 'agency needed',
            'urgent', 'urgently', 'asap', 'budget', 'quote', 'estimate',
            'can someone', 'anyone know', 'recommend', 'suggest', 'referral',
            'who can', 'where can i find', 'need help with', 'request for proposal', 'rfp'
        ];

        // NOISE EXCLUSIONS: Generic informational markers
        this.excludeWords = [
            'what is', 'how to', 'tutorial', 'wikipedia', 'definition',
            'meaning of', 'vs ', 'course', 'learn', 'explain',
            'difference between', 'example', 'sample', 'guide'
        ];

        // SUPPLY SIGNALS (THE NOISE KILLER): Flag entries selling services, seeking market validation, or asking for feedback
        this.supplyPhrases = [
            'would you pay', 'honest opinions', 'looking for feedback', 'opinion from',
            'market research', 'rate my', 'critique my', 'thoughts on my',
            'we offer', 'i offer', 'our services', 'introducing our', 'proud to announce',
            'we build', 'i will build', 'i can create', 'our team can', 'check out my portfolio',
            'launched my', 'just launched', 'package includes', 'per month', 'fixed pricing starting'
        ];

        this.serviceCategories = {
            webdev: ['web developer', 'frontend developer', 'backend developer', 'fullstack', 'wordpress', 'shopify', 'web design', 'web development'],
            marketing: ['seo expert', 'seo specialist', 'facebook ads', 'google ads', 'lead generation', 'digital marketer', 'seo scaling'],
            design: ['graphic designer', 'logo designer', 'ui ux designer', 'brand designer', 'illustrator'],
            writing: ['content writer', 'copywriter', 'ghostwriter', 'technical writer', 'blog writer']
        };
    }

    async delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    getRandomUserAgent() {
        return this.userAgents[Math.floor(Math.random() * this.userAgents.length)];
    }

    async randomDelay() {
        const ms = Math.floor(Math.random() * 4000) + 2000;
        await this.delay(ms);
    }

    generateIntentQueries(service) {
        return [
            `need ${service}`,
            `looking for ${service}`,
            `hire ${service}`,
            `hiring ${service}`,
            `"${service}" needed`,
            `freelance ${service}`,
            `looking for someone to ${service}`
        ];
    }

    analyzeIntent(text) {
        let score = 0;
        const lower = text.toLowerCase();

        // Step 1: Base information exclusion check
        for (const word of this.excludeWords) {
            if (lower.includes(word)) {
                return { isIntent: false, score: 0 };
            }
        }

        // Step 2: Supply-side / Competitor marketing protection filter
        let supplyHits = 0;
        for (const supplyPhrase of this.supplyPhrases) {
            if (lower.includes(supplyPhrase)) {
                supplyHits++;
            }
        }
        
        // If it looks like market feedback or a pitch, kill intent score immediately
        if (supplyHits >= 1) {
            return { isIntent: false, score: 0, reason: 'supply_side_noise' };
        }

        // Step 3: Parse real demand metrics
        let hasIntent = false;
        for (const phrase of this.intentPhrases) {
            if (lower.includes(phrase)) {
                hasIntent = true;
                score += 4;
            }
        }

        if (!hasIntent) {
            return { isIntent: false, score: 0 };
        }

        // Contextual urgency/budget weights
        if (lower.includes('urgent')) score += 5;
        if (lower.includes('asap')) score += 5;
        if (lower.includes('budget')) score += 3;
        if (lower.includes('hire') || lower.includes('hiring')) score += 3;

        let category = null;
        for (const [key, values] of Object.entries(this.serviceCategories)) {
            for (const value of values) {
                if (lower.includes(value)) {
                    category = key;
                    score += 4;
                }
            }
        }

        const emails = this.extractEmails(text);
        const phones = this.extractPhones(text);
        if (emails.length) score += 3;
        if (phones.length) score += 3;

        const location = this.extractLocation(text);
        if (location) score += 2;

        return {
            isIntent: score >= 8, // Elevated baseline to avoid accidental matches
            score,
            category,
            emails,
            phones,
            location
        };
    }

    extractEmails(text) {
        if (!text) return [];
        // Strict, non-backtracking email validator
        const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}/g;
        return [...new Set(text.match(emailRegex) || [])];
    }

    extractPhones(text) {
        if (!text) return [];
        // Captures international (e.g., +254...) and domestic local formats cleanly
        const phoneRegex = /(?:\+?\d{1,3}[-\s.]?)?\(?\d{3}\)?[-\s.]?\d{3}[-\s.]?\d{4,6}/g;
        return [...new Set(text.match(phoneRegex) || [])];
    }

    extractLocation(text) {
        const locations = ['nairobi', 'kenya', 'lagos', 'nigeria', 'kampala', 'remote', 'worldwide'];
        const lower = text.toLowerCase();
        for (const loc of locations) {
            if (lower.includes(loc)) return loc;
        }
        return null;
    }

    async googleSearch(query) {
        try {
            await this.randomDelay();
            const url = `https://www.google.com/search?q=${encodeURIComponent(query)}&num=15`;
            
            // Clean browser emulation parameters to prevent immediate 0-result blocks
            const response = await axios.get(url, {
                headers: {
                    'User-Agent': this.getRandomUserAgent(),
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
                    'Accept-Language': 'en-US,en;q=0.5',
                    'Referer': 'https://www.google.com/',
                    'Sec-Fetch-Dest': 'document',
                    'Sec-Fetch-Mode': 'navigate',
                    'Sec-Fetch-Site': 'same-origin'
                },
                timeout: 20000
            });
            
            const $ = cheerio.load(response.data);
            const results = [];
            
            $('div.g').each((i, el) => {
                const title = $(el).find('h3').text();
                const snippet = $(el).find('.VwiC3b').text() || $(el).find('.st').text();
                let link = $(el).find('a').attr('href');
                
                if (link && link.startsWith('/url?')) {
                    // Safe WHATWG URL migration replacing legacy url.parse()
                    const urlObj = new URL(link, 'https://www.google.com');
                    link = urlObj.searchParams.get('q');
                }
                
                if (!title || !snippet || !link) return;
                results.push({ title, snippet, url: link, source: 'google', timestamp: new Date() });
            });
            return results;
        } catch (err) {
            console.log(`❌ Google core extraction failure:`, err.message);
            return [];
        }
    }

    async searchGoogleSiteQueries(searchQueries, sourceName) {
        const results = [];
        const queries = Array.isArray(searchQueries) ? searchQueries : [];
        for (const query of queries) {
            try {
                const googleResults = await this.googleSearch(query);
                for (const result of googleResults) {
                    const combined = `${result.title} ${result.snippet}`;
                    const lead = this.analyzeIntent(combined);
                    if (!lead.isIntent) continue;
                    results.push({
                        title: result.title,
                        snippet: result.snippet,
                        url: result.url,
                        source: sourceName,
                        score: lead.score,
                        category: lead.category,
                        emails: lead.emails,
                        phones: lead.phones,
                        location: lead.location,
                        timestamp: new Date()
                    });
                }
            } catch (err) {
                console.log(`❌ Engine anomaly on ${sourceName}:`, err.message);
            }
        }
        return results;
    }

    async searchReddit(service) {
        const results = [];
        const queries = this.generateIntentQueries(service);
        const subreddits = PUBLIC_SOURCES && PUBLIC_SOURCES.reddit ? PUBLIC_SOURCES.reddit : [' freelance', 'webdev', 'smallbusiness'];
        
        for (const sub of subreddits) {
            for (const query of queries.slice(0, 3)) {
                try {
                    await this.randomDelay();
                    const url = `https://www.reddit.com/r/${sub}/search.json?q=${encodeURIComponent(query)}&restrict_sr=1&sort=new&limit=10`;
                    const response = await axios.get(url, {
                        headers: { 'User-Agent': this.getRandomUserAgent() },
                        timeout: 15000
                    });
                    const posts = response.data?.data?.children || [];
                    for (const child of posts) {
                        const post = child.data;
                        const text = `${post.title} ${post.selftext}`;
                        const lead = this.analyzeIntent(text);
                        if (!lead.isIntent) continue;
                        results.push({
                            title: post.title,
                            snippet: post.selftext?.substring(0, 400),
                            url: `https://reddit.com${post.permalink}`,
                            source: `reddit/${sub}`,
                            score: lead.score,
                            category: lead.category,
                            emails: lead.emails,
                            phones: lead.phones,
                            location: lead.location,
                            timestamp: new Date(post.created_utc * 1000)
                        });
                    }
                } catch (err) {
                    console.log(`❌ Reddit extraction skip on /r/${sub}:`, err.message);
                }
            }
        }
        return results;
    }

    async searchFacebookPublic() { return this.searchGoogleSiteQueries(PUBLIC_SOURCES?.facebookSearches || [], 'facebook-public'); }
    async searchLinkedInPublic() { return this.searchGoogleSiteQueries(PUBLIC_SOURCES?.linkedinSearches || [], 'linkedin-public'); }
    async searchTwitterPublic() { return this.searchGoogleSiteQueries(PUBLIC_SOURCES?.twitterSearches || [], 'twitter-public'); }
    async searchClassifieds() { return this.searchGoogleSiteQueries(PUBLIC_SOURCES?.classifiedSearches || [], 'classifieds'); }
    async searchStartupCommunities() { return this.searchGoogleSiteQueries(PUBLIC_SOURCES?.startupSearches || [], 'startup-communities'); }

    deduplicate(results) {
        const seen = new Set();
        return results.filter(item => {
            if (seen.has(item.url)) return false;
            seen.add(item.url);
            return true;
        });
    }

    sortLeads(results) {
        return results.sort((a, b) => b.score - a.score);
    }

    async comprehensiveSearch(service) {
        const [redditResults, googleResults, facebookResults, linkedinResults, twitterResults, classifiedResults, startupResults] = await Promise.all([
            this.searchReddit(service),
            this.searchGoogleSiteQueries(this.generateIntentQueries(service), 'google-intent'),
            this.searchFacebookPublic(),
            this.searchLinkedInPublic(),
            this.searchTwitterPublic(),
            this.searchClassifieds(),
            this.searchStartupCommunities()
        ]);

        let allResults = [...redditResults, ...googleResults, ...facebookResults, ...linkedinResults, ...twitterResults, ...classifiedResults, ...startupResults];
        allResults = this.deduplicate(allResults);
        return this.sortLeads(allResults);
    }

    detectIntent(text) {
        const result = this.analyzeIntent(text);
        const computedConfidence = result.isIntent ? Math.min(100, Math.round((result.score / 25) * 100)) : 0;
        return {
            isIntent: result.isIntent,
            confidence: computedConfidence,
            hasStrongIntent: result.score >= 12,
            hasServiceWord: result.category !== null,
            isQuestion: text.trim().endsWith('?'),
            isInformational: !result.isIntent
        };
    }

    classifyService(text) {
        const result = this.analyzeIntent(text);
        return result.category || null;
    }

    summarize(text, maxLength = 200) {
        if (!text) return '';
        if (text.length <= maxLength) return text;
        return text.substring(0, maxLength) + '...';
    }
}

module.exports = new IntentService();