import {chromium} from 'playwright';
import {Injectable} from "@nestjs/common";
import axios from "axios";
import {XCacheService} from "../x-cache/x-cache.service";

@Injectable()
export class XReaderService {
    constructor(private readonly cacheService: XCacheService) {
    }

    async readXPostViaBrowserV2(url) {
        // Normalize URL
        console.log(`[X] XReaderService -> readXPostViaBrowserV2...`);

        url = url.replace('twitter.com', 'x.com').split('?')[0];
        // url = url.replace('x.com', 'nitter.net').split('?')[0];

        const match = url.match(/status\/(\d+)/);
        if (!match) throw new Error('URL X không hợp lệ');
        const tweetId = match[1];
        console.log({tweetId, url});
        const browser = await chromium.launch({
            headless: false,
            args: ['--no-sandbox', '--disable-blink-features=AutomationControlled']
        });

        const context = await browser.newContext({
            userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
            viewport: {width: 1280, height: 900},
            locale: 'en-US'
        });

        // Inject cookie auth nếu có
        // if (process.env.X_AUTH_TOKEN) {
        //     await context.addCookies([
        //         {
        //             name: 'auth_token',
        //             value: process.env.X_AUTH_TOKEN,
        //             domain: '.x.com',
        //             path: '/',
        //             httpOnly: true,
        //             secure: true,
        //             sameSite: 'None'
        //         },
        //         {
        //             name: 'ct0',
        //             value: process.env.X_CT0,
        //             domain: '.x.com',
        //             path: '/',
        //             secure: true,
        //             sameSite: 'Lax'
        //         }
        //     ]);
        // }

        const page = await context.newPage();
        try {
            await page.goto(url, {waitUntil: 'domcontentloaded', timeout: 45000});
            console.log(`==> 1`);
            await Promise.race([
                page.waitForSelector('article[data-testid="tweet"]', {timeout: 20000}),
                page.waitForSelector('[data-testid="tweetText"]', {timeout: 20000}),

                //nitter
                // page.waitForSelector('div.main-tweet', {timeout: 20000})
            ])
            console.log(`==> 2`);
            // Đợi media load
            await page.waitForTimeout(2000);
            console.log(`==> 2.1`);
            const data = await page.evaluate(
                (tweetId) => {
                    console.log(`==> 2.2`);
                    // ===== HELPER: parse 1 block tweet (dùng cho cả main + quoted) =====
                    const parseBlock = (root, isQuoted = false) => {
                        console.log(`==> 2.3`);
                        if (!root) return null;
                        console.log(`==> 3`);
                        // Text
                        const textEl = root.querySelector('[data-testid="tweetText"]');
                        const text = textEl?.innerText || '';
                        console.log(`==> 4`);
                        // User info
                        const userEl = root.querySelector('[data-testid="User-Name"]');
                        const userLines = userEl?.innerText.split('\n') || [];
                        const author = userLines[0] || 'Unknown';
                        const handle = userLines.find(s => s.startsWith('@')) || '';
                        console.log(`==> 5`);
                        // Time
                        const timeEl = root.querySelector('time');
                        const time = timeEl?.getAttribute('datetime') || '';
                        console.log(`==> 6`);
                        // Images — lọc avatar, emoji, card icons
                        const images = Array.from(root.querySelectorAll('img'))
                            // @ts-ignore
                            .map(i => i.src)
                            .filter(src =>
                                src.includes('pbs.twimg.com/media') &&
                                !src.includes('profile') &&
                                !src.includes('emoji')
                            );
                        console.log(`==> 7`);
                        // Videos
                        const videos = Array.from(root.querySelectorAll('video'))
                            // @ts-ignore
                            .map(v => v.src || v.querySelector('source')?.src)
                            .filter(Boolean);

                        // Video poster (ảnh thumbnail khi không lấy được URL video)
                        const videoPosters = Array.from(root.querySelectorAll('video'))
                            // @ts-ignore
                            .map(v => v.poster)
                            .filter(Boolean);
                        console.log(`==> 8`);
                        return {
                            text,
                            author,
                            handle,
                            time,
                            images: [...new Set(images)],
                            videos,
                            videoPosters,
                            ...(isQuoted ? {} : {})
                        };
                    };

                    // ===== MAIN TWEET =====
                    const article = document.querySelector('article[data-testid="tweet"]');
                    console.log(`==> 2.2.1`);
                    if (!article) return null;
                    console.log(`==> 9`);
                    // ===== TÌM QUOTED TWEET =====
                    // Quoted tweet là div[role="link"] bên trong article chính,
                    // có chứa [data-testid="tweetText"] hoặc User-Name riêng
                    let quotedEl = null;
                    const innerLinks = article.querySelectorAll('div[role="link"]');
                    console.log(`==> 10`);
                    for (const el of innerLinks) {
                        // Quoted phải có cả User-Name (tránh nhầm với card link)
                        if (
                            el.querySelector('[data-testid="User-Name"]') &&
                            (el.querySelector('[data-testid="tweetText"]') ||
                                el.querySelector('img[src*="pbs.twimg.com/media"]'))
                        ) {
                            // @ts-ignore
                            quotedEl = el;
                            break;
                        }
                    }
                    console.log(`==> 11`);

                    // ===== CLONE article và REMOVE quoted để parse main cho sạch =====
                    // (tránh ảnh/text của quoted bị gộp vào main)
                    const articleClone = article.cloneNode(true) as Document;
                    if (quotedEl) {
                        const clonedQuoted = articleClone.querySelector('div[role="link"]');
                        // Tìm đúng node quoted trong clone
                        const innerLinksClone = articleClone.querySelectorAll('div[role="link"]');
                        for (const el of innerLinksClone) {
                            if (
                                el.querySelector('[data-testid="User-Name"]') &&
                                (el.querySelector('[data-testid="tweetText"]') ||
                                    el.querySelector('img[src*="pbs.twimg.com/media"]'))
                            ) {
                                el.remove();
                                break;
                            }
                        }
                    }
                    console.log(`==> 12`);

                    const main = parseBlock(articleClone);
                    const quoted = quotedEl ? parseBlock(quotedEl, true) : null;

                    // ===== STATS (like, retweet, reply, view) =====
                    const stats: any = {};
                    const statGroup = article.querySelector('[role="group"]');
                    if (statGroup) {
                        console.log(`==> 13`);

                        const buttons = statGroup.querySelectorAll('[data-testid]');
                        buttons.forEach(btn => {
                            const testId = btn.getAttribute('data-testid');
                            const label = btn.getAttribute('aria-label') || '';
                            if (testId === 'reply') stats.replies = label;
                            if (testId === 'retweet') stats.retweets = label;
                            if (testId === 'like') stats.likes = label;
                        });
                        // View count thường nằm trong link riêng
                        const viewLink = article.querySelector('a[href*="/analytics"]');
                        if (viewLink) stats.views = viewLink.getAttribute('aria-label') || '';
                    }

                    // ===== Extract quoted URL từ href (nếu có) =====
                    let quotedUrl = null;
                    if (quotedEl) {
                        console.log(`==> 14`);

                        // @ts-ignore
                        const href = quotedEl.querySelector('a[href*="/status/"]')?.getAttribute('href');
                        if (href) { // @ts-ignore
                            quotedUrl = 'https://x.com' + href.split('/photo')[0].split('/video')[0];
                        }
                    }

                    return {
                        ...main,
                        stats,
                        quoted: quoted ? {...quoted, url: quotedUrl} : {},
                        via: 'browser',
                        tweetId: tweetId,
                    };
                }
                , tweetId);

            await browser.close();
            if (!data) throw new Error(`Không parse được tweet ${tweetId} (có thể bị ẩn/xoá)`);
            return data;
        } catch (err) {
            try {
                await page.screenshot({path: `./downloads/x_error_${tweetId}.png`});
                console.log(`📸 Screenshot: ./downloads/x_error_${tweetId}.png`);
            } catch {
            }
            await browser.close();
            console.log(err);
            throw new Error(`Lỗi đọc X: ${err.message}`);
        }
    }

    async readXPostViaApi(url) {
        console.log(`[X] XReaderService -> readXPostViaApi...`);

        // Extract tweet ID từ URL
        const match = url.match(/status\/(\d+)/);
        if (!match) throw new Error('URL X không hợp lệ');
        const tweetId = match[1];

        // Token này là public token của syndication API (stable nhiều năm)
        const token = ((Number(tweetId) / 1e15) * Math.PI)
            .toString(6 ** 2)
            .replace(/(0+|\.)/g, '');

        const apiUrl = `https://cdn.syndication.twimg.com/tweet-result?id=${tweetId}&token=${token}&lang=en`;

        try {
            const {data} = await axios.get(apiUrl, {
                headers: {
                    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
                    'Accept': 'application/json'
                },
                timeout: 15000
            });

            // ===== MEDIA =====
            const images = (data.mediaDetails || [])
                .filter(m => m.type === 'photo')
                .map(m => m.media_url_https + '?format=jpg&name=large'); // lấy size lớn nhất

            const videos = (data.mediaDetails || [])
                .filter(m => ['video', 'animated_gif'].includes(m.type))
                .map(m => {
                    const mp4 = (m.video_info?.variants || [])
                        .filter(v => v.content_type === 'video/mp4')
                        .sort((a, b) => (b.bitrate || 0) - (a.bitrate || 0))[0];
                    return mp4?.url;
                })
                .filter(Boolean);

            // ===== QUOTED TWEET (tweet trích dẫn) =====
            let quoted = null;
            if (data.quoted_tweet) {
                const q = data.quoted_tweet;
                // @ts-ignore
                quoted = {
                    text: q.text,
                    author: q.user?.name,
                    handle: '@' + q.user?.screen_name,
                    images: (q.mediaDetails || [])
                        .filter(m => m.type === 'photo')
                        .map(m => m.media_url_https)
                };
            }

            // ===== CARD (link preview) =====
            let card = null;
            if (data.card) {
                const values = data.card.binding_values || {};
                // @ts-ignore
                card = {
                    title: values.title?.string_value,
                    description: values.description?.string_value,
                    url: values.card_url?.string_value,
                    image: values.thumbnail_image_large?.image_value?.url
                };
            }

            // ===== POLL =====
            let poll = null;
            if (data.card?.name?.includes('poll')) {
                const v = data.card.binding_values;
                // @ts-ignore
                poll = {
                    choices: Object.keys(v)
                        .filter(k => k.startsWith('choice') && k.endsWith('_label'))
                        .map(k => v[k].string_value)
                };
            }

            return {
                via: 'api',
                apiUrl,
                tweetId: tweetId,
                text: data.text || '',
                author: data.user?.name || 'Unknown',
                handle: '@' + (data.user?.screen_name || ''),
                avatar: data.user?.profile_image_url_https,
                verified: data.user?.verified || data.user?.is_blue_verified,
                time: data.created_at || '',
                lang: data.lang,
                images,
                videos,
                quoted,
                card,
                poll,
                url: `https://x.com/${data.user?.screen_name}/status/${tweetId}`,
                // Raw để debug nếu cần
                _raw: data
            };
        } catch (err) {
            if (err.response?.status === 404) {
                throw new Error('Tweet không tồn tại hoặc bị xoá');
            }
            throw new Error(`Lỗi syndication API: ${err.message}`);
        }
    }

    async readXPost(url, crawlerType: string = 'any') {
        console.log(`[X] XReaderService -> readXPost...`);
        url = url.replace('twitter.com', 'x.com').split('?')[0];
        const match = url.match(/status\/(\d+)/);
        if (!match) throw new Error('URL X không hợp lệ');
        const tweetId = match[1];
        console.log({tweetId, url});
        await this.cacheService.setCacheTweetUrlById(tweetId, url);
        if (crawlerType === 'browser') {
            return await this.readXPostViaBrowserV2(url);
        }
        try {
            console.log('[X] Thử syndication API...');
            return await this.readXPostViaApi(url);
        } catch (err) {
            console.log(`[X] API fail (${err.message}), fallback sang browser...`);
            return await this.readXPostViaBrowserV2(url);
        }
    }
}
