"""
智能爬虫
自动识别页面结构并提取数据
"""
import json
from typing import Optional, List, Dict, Any
from playwright.async_api import Page
from loguru import logger

from .basic import DataExtractor
from .pagination import PaginationExtractor
from .dynamic import DynamicContentExtractor
from .form import FormDataExtractor


class SmartScraper:
    """
    智能爬虫
    自动识别页面结构并提取数据
    """

    def __init__(self, page: Page):
        self.page = page
        self.extractor = DataExtractor(page)
        self.pagination = PaginationExtractor(page)
        self.dynamic = DynamicContentExtractor(page)
        self.form = FormDataExtractor(page)

    async def auto_detect_list(
        self,
        min_items: int = 3,
        similarity_threshold: float = 0.7,
    ) -> Optional[Dict[str, Any]]:
        """
        自动检测页面中的列表结构

        Args:
            min_items: 最小列表项数量
            similarity_threshold: 相似度阈值

        Returns:
            检测结果
        """
        result = await self.page.evaluate(f"""
            () => {{
                // 查找重复结构的容器
                const candidates = [];

                // 常见列表容器
                const listSelectors = [
                    'ul > li', 'ol > li',
                    'table tbody tr',
                    '.list > div', '.items > div',
                    '[class*="list"] > div', '[class*="item"]',
                    '.row > div', '.grid > div',
                ];

                for (const selector of listSelectors) {{
                    const items = document.querySelectorAll(selector);
                    if (items.length >= {min_items}) {{
                        // 分析第一个和第二个项的结构相似度
                        const item1 = items[0];
                        const item2 = items[1];

                        if (item1 && item2) {{
                            const struct1 = getItemStructure(item1);
                            const struct2 = getItemStructure(item2);
                            const similarity = calculateSimilarity(struct1, struct2);

                            if (similarity >= {similarity_threshold}) {{
                                candidates.push({{
                                    selector: selector,
                                    count: items.length,
                                    similarity: similarity,
                                    structure: struct1,
                                }});
                            }}
                        }}
                    }}
                }}

                // 辅助函数
                function getItemStructure(el) {{
                    return {{
                        children: el.children.length,
                        links: el.querySelectorAll('a').length,
                        images: el.querySelectorAll('img').length,
                        textLength: el.textContent.length,
                        classes: Array.from(el.classList),
                    }};
                }}

                function calculateSimilarity(a, b) {{
                    const keys = ['children', 'links', 'images'];
                    let matches = 0;
                    keys.forEach(k => {{
                        if (a[k] === b[k]) matches++;
                    }});
                    return matches / keys.length;
                }}

                return candidates.sort((a, b) => b.similarity - a.similarity)[0] || null;
            }}
        """)
        return result

    async def smart_extract_list(
        self,
        item_selector: Optional[str] = None,
        fields: Optional[List[str]] = None,
    ) -> List[Dict[str, Any]]:
        """
        智能提取列表数据 - 批量优化版

        Args:
            item_selector: 列表项选择器（自动检测如果为空）
            fields: 要提取的字段名（自动检测如果为空）

        Returns:
            数据列表
        """
        # 自动检测列表选择器
        if not item_selector:
            detected = await self.auto_detect_list()
            if detected:
                item_selector = detected["selector"]
            else:
                logger.warning("无法自动检测列表结构")
                return []

        try:
            # 自动检测字段模式
            if not fields:
                results = await self.page.evaluate(f"""
                    () => {{
                        const items = document.querySelectorAll('{item_selector}');
                        const results = [];

                        items.forEach(item => {{
                            const row = {{}};

                            // 提取文本和 HTML
                            row.text = item.textContent.trim();
                            row.html = item.innerHTML;

                            // 提取链接
                            const links = item.querySelectorAll('a[href]');
                            if (links.length > 0) {{
                                row.links = [];
                                links.forEach(link => {{
                                    row.links.push({{
                                        text: link.textContent.trim(),
                                        href: link.href,
                                    }});
                                }});
                            }}

                            // 提取图片
                            const images = item.querySelectorAll('img[src]');
                            if (images.length > 0) {{
                                row.images = [];
                                images.forEach(img => {{
                                    row.images.push({{
                                        src: img.src,
                                        alt: img.alt || '',
                                    }});
                                }});
                            }}

                            results.push(row);
                        }});

                        return results;
                    }}
                """)
            else:
                # 按指定字段提取
                fields_json = json.dumps(fields)

                results = await self.page.evaluate(f"""
                    () => {{
                        const items = document.querySelectorAll('{item_selector}');
                        const fields = {fields_json};
                        const results = [];

                        items.forEach(item => {{
                            const row = {{}};
                            fields.forEach(field => {{
                                const el = item.querySelector('[class*="' + field + '"], [id*="' + field + '"], [name*="' + field + '"]');
                                row[field] = el ? el.textContent.trim() : null;
                            }});
                            results.push(row);
                        }});

                        return results;
                    }}
                """)

            return results
        except Exception as e:
            logger.error(f"智能提取列表失败: {e}")
            return []

    async def extract_page_summary(self) -> Dict[str, Any]:
        """
        提取页面摘要信息

        Returns:
            页面摘要
        """
        summary = {
            "url": self.page.url,
            "title": await self.page.title(),
        }

        # 提取 meta 信息
        summary["meta"] = await self.extractor.extract_meta_tags()
        summary["open_graph"] = await self.extractor.extract_open_graph()
        summary["json_ld"] = await self.extractor.extract_json_ld()

        # 提取主要文本
        main_content = await self.page.evaluate("""
            () => {
                // 尝试找到主要内容区域
                const main = document.querySelector('main, article, .content, #content, [role="main"]');
                if (main) {
                    return main.textContent.trim().substring(0, 500);
                }
                return document.body.textContent.trim().substring(0, 500);
            }
        """)
        summary["content_preview"] = main_content

        # 统计页面元素
        stats = await self.page.evaluate("""
            () => ({
                headings: document.querySelectorAll('h1, h2, h3').length,
                paragraphs: document.querySelectorAll('p').length,
                links: document.querySelectorAll('a').length,
                images: document.querySelectorAll('img').length,
                forms: document.querySelectorAll('form').length,
                tables: document.querySelectorAll('table').length,
                lists: document.querySelectorAll('ul, ol').length,
            })
        """)
        summary["stats"] = stats

        return summary

    async def extract_all_text(self) -> Dict[str, str]:
        """
        提取页面所有文本内容（按区域）

        Returns:
            区域文本字典
        """
        text_content = await self.page.evaluate("""
            () => {
                const result = {};

                // 标题
                const h1 = document.querySelector('h1');
                if (h1) result.title = h1.textContent.trim();

                // 副标题
                const h2s = document.querySelectorAll('h2');
                if (h2s.length > 0) {
                    result.subtitles = Array.from(h2s).map(h => h.textContent.trim());
                }

                // 段落
                const paragraphs = document.querySelectorAll('p');
                if (paragraphs.length > 0) {
                    result.paragraphs = Array.from(paragraphs).map(p => p.textContent.trim()).filter(t => t);
                }

                // 导航
                const nav = document.querySelector('nav, .nav, .navigation');
                if (nav) result.navigation = nav.textContent.trim();

                // 页脚
                const footer = document.querySelector('footer, .footer');
                if (footer) result.footer = footer.textContent.trim();

                // 侧边栏
                const sidebar = document.querySelector('aside, .sidebar, .side');
                if (sidebar) result.sidebar = sidebar.textContent.trim();

                return result;
            }
        """)
        return text_content

    async def extract_contact_info(self) -> Dict[str, List[str]]:
        """
        提取页面中的联系信息

        Returns:
            联系信息字典
        """
        import re

        page_text = await self.page.evaluate("() => document.body.textContent")
        contact_info = {
            "emails": [],
            "phones": [],
            "addresses": [],
        }

        # 提取邮箱
        email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
        emails = re.findall(email_pattern, page_text or "")
        contact_info["emails"] = list(set(emails))

        # 提取电话号码
        phone_pattern = r'(?:\+?86[-\s]?)?(?:1[3-9]\d{9}|(?:\d{3,4}[-\s]?)?\d{7,8})'
        phones = re.findall(phone_pattern, page_text or "")
        contact_info["phones"] = list(set(phones))

        return contact_info

    async def extract_social_links(self) -> Dict[str, str]:
        """
        提取社交媒体链接

        Returns:
            社交媒体链接字典
        """
        social_links = await self.page.evaluate("""
            () => {
                const result = {};
                const patterns = {
                    weibo: /weibo\\.com/,
                    wechat: /weixin\\.qq\\.com|wechat/,
                    twitter: /twitter\\.com|x\\.com/,
                    facebook: /facebook\\.com|fb\\.com/,
                    instagram: /instagram\\.com/,
                    linkedin: /linkedin\\.com/,
                    youtube: /youtube\\.com|youtu\\.be/,
                    github: /github\\.com/,
                    tiktok: /tiktok\\.com|douyin\\.com/,
                };

                document.querySelectorAll('a[href]').forEach(a => {
                    const href = a.href;
                    for (const [platform, pattern] of Object.entries(patterns)) {
                        if (pattern.test(href)) {
                            result[platform] = href;
                            break;
                        }
                    }
                });

                return result;
            }
        """)
        return social_links

    async def smart_scrape(
        self,
        url: Optional[str] = None,
        extract_type: str = "auto",
    ) -> Dict[str, Any]:
        """
        智能爬取页面

        Args:
            url: 目标URL（可选，默认当前页面）
            extract_type: 提取类型 auto/list/article/product

        Returns:
            爬取结果
        """
        if url:
            await self.page.goto(url)
            await self.page.wait_for_load_state("networkidle")

        result = {
            "url": self.page.url,
            "title": await self.page.title(),
        }

        # 根据类型选择提取策略
        if extract_type == "auto":
            # 自动判断页面类型
            list_detected = await self.auto_detect_list()
            if list_detected and list_detected.get("count", 0) >= 3:
                result["type"] = "list"
                result["data"] = await self.smart_extract_list()
            else:
                result["type"] = "article"
                result["data"] = await self.extract_all_text()
                result["summary"] = await self.extract_page_summary()

        elif extract_type == "list":
            result["type"] = "list"
            result["data"] = await self.smart_extract_list()

        elif extract_type == "article":
            result["type"] = "article"
            result["data"] = await self.extract_all_text()
            result["summary"] = await self.extract_page_summary()

        else:
            result["type"] = "full"
            result["data"] = await self.extract_all_text()
            result["links"] = await self.extractor.extract_links()
            result["images"] = await self.extractor.extract_images()
            result["summary"] = await self.extract_page_summary()

        return result
