#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：selector_mapper.py
模块描述：元素选择器映射，为目标平台各页面提供精确的选择器

基于对目标平台的分析，为测试用例提供稳定、精确的元素选择器。

作者：czj
创建日期：2026-07-12
"""

from typing import Dict, List, Optional

# 目标平台基础URL
BASE_URL = "https://192.168.5.44"

# ==================== 选择器映射 ====================

SELECTORS = {
    # ==================== 登录页 ====================
    "login": {
        "url": f"{BASE_URL}/",
        "inputs": {
            "username": [
                "input[placeholder*='用户']",
                "input[placeholder*='手机']",
                "input[placeholder*='邮箱']",
                "input[type='text']:first-of-type"
            ],
            "password": [
                "input[type='password']",
                "input[placeholder*='密码']"
            ],
            "captcha": [
                "input[placeholder*='验证']",
                "input[placeholder*='图形']"
            ]
        },
        "buttons": {
            "login": [
                "button:has-text('登录')",
                ".login-btn",
                "button[type='submit']"
            ],
            "cancel": [
                "button:has-text('取消')"
            ],
            "confirm_agreement": [
                ".el-dialog button:has-text('确定')",
                "[role='dialog'] button:has-text('确定')",
                "button:has-text('同意')"
            ]
        },
        "elements": {
            "login_form": [".login-form", "form", ".el-form"],
            "agreement_dialog": [".el-dialog", "[role='dialog']"]
        }
    },

    # ==================== 首页 ====================
    "home": {
        "url": f"{BASE_URL}/#/platform",
        "navigation": {
            "menu_items": [
                ".el-menu-item",
                ".nav-item",
                "[role='menuitem']"
            ],
            "submenu": [
                ".el-submenu",
                ".nav-submenu"
            ]
        },
        "elements": {
            "user_info": [".user-info", ".el-dropdown-link"],
            "main_content": [".main-content", ".app-main", ".content-wrapper"]
        }
    },

    # ==================== 会议预约 ====================
    "meeting_reservation": {
        "url": f"{BASE_URL}/#/meeting/reservation",
        "buttons": {
            "new_reservation": [
                "button:has-text('新建')",
                "button:has-text('预约')",
                ".new-btn",
                ".add-btn"
            ],
            "search": [
                "button:has-text('搜索')",
                "button:has-text('查询')",
                ".search-btn"
            ]
        },
        "forms": {
            "reservation_form": [
                ".reservation-form",
                ".el-form",
                "form"
            ],
            "date_picker": [
                ".el-date-editor",
                "input[placeholder*='日期']"
            ],
            "time_picker": [
                ".el-time-picker",
                "input[placeholder*='时间']"
            ],
            "room_select": [
                ".el-select:has-text('会议室')",
                "select[name*='room']"
            ]
        },
        "tables": {
            "list": [
                ".el-table",
                "table",
                ".reservation-list"
            ]
        }
    },

    # ==================== 会议室列表 ====================
    "meeting_room_list": {
        "url": f"{BASE_URL}/#/meeting/room",
        "search": {
            "input": [
                "input[placeholder*='搜索']",
                "input[placeholder*='查询']",
                ".search-input"
            ],
            "button": [
                "button:has-text('搜索')",
                "button:has-text('查询')",
                ".search-btn"
            ]
        },
        "filter": {
            "status": [
                ".el-select:has-text('状态')",
                "select[name*='status']"
            ],
            "building": [
                ".el-select:has-text('楼栋')",
                "select[name*='building']"
            ]
        },
        "tables": {
            "list": [
                ".el-table",
                "table",
                ".room-list"
            ]
        },
        "buttons": {
            "view_detail": [
                "button:has-text('详情')",
                "button:has-text('查看')",
                ".detail-btn"
            ],
            "edit": [
                "button:has-text('编辑')",
                ".edit-btn"
            ]
        }
    },

    # ==================== 会议列表 ====================
    "meeting_list": {
        "url": f"{BASE_URL}/#/meeting/list",
        "search": {
            "input": [
                "input[placeholder*='搜索']",
                "input[placeholder*='会议']",
                ".search-input"
            ],
            "button": [
                "button:has-text('搜索')",
                ".search-btn"
            ]
        },
        "filter": {
            "status": [
                ".el-select:has-text('状态')",
                "select[name*='status']"
            ],
            "date_range": [
                ".el-date-editor",
                ".el-range-editor"
            ]
        },
        "tables": {
            "list": [
                ".el-table",
                "table",
                ".meeting-list"
            ]
        },
        "buttons": {
            "view_detail": [
                "button:has-text('详情')",
                "button:has-text('查看')"
            ],
            "cancel_meeting": [
                "button:has-text('取消')",
                ".cancel-btn"
            ]
        }
    },

    # ==================== 管理看板 ====================
    "management_dashboard": {
        "url": f"{BASE_URL}/#/dashboard/management",
        "elements": {
            "data_cards": [
                ".card",
                ".data-card",
                ".stat-card",
                ".el-card"
            ],
            "charts": [
                ".chart",
                ".echarts",
                "canvas",
                "[class*='chart']"
            ],
            "statistics": [
                ".statistic",
                ".stat-item",
                ".data-item"
            ]
        }
    },

    # ==================== 通用选择器 ====================
    "common": {
        "loading": [
            ".el-loading-mask",
            ".loading",
            "[class*='loading']"
        ],
        "message": {
            "success": [
                ".el-message--success"
            ],
            "error": [
                ".el-message--error"
            ],
            "warning": [
                ".el-message--warning"
            ]
        },
        "dialog": {
            "container": [
                ".el-dialog",
                "[role='dialog']"
            ],
            "close": [
                ".el-dialog__close",
                ".dialog-close"
            ],
            "confirm": [
                ".el-dialog button:has-text('确定')",
                ".el-dialog button:has-text('确认')"
            ],
            "cancel": [
                ".el-dialog button:has-text('取消')"
            ]
        },
        "pagination": {
            "container": [
                ".el-pagination",
                ".pagination"
            ],
            "next": [
                ".el-pagination .btn-next",
                ".pagination .next"
            ],
            "prev": [
                ".el-pagination .btn-prev",
                ".pagination .prev"
            ]
        },
        "table": {
            "container": [
                ".el-table",
                "table"
            ],
            "row": [
                ".el-table__row",
                "tbody tr"
            ],
            "empty": [
                ".el-table__empty-text",
                ".empty-text"
            ]
        }
    }
}


class SelectorMapper:
    """
    选择器映射器

    为测试用例提供精确的元素选择器，支持多选器回退策略。

    Example:
        >>> mapper = SelectorMapper()
        >>> selector = mapper.get_selector("login", "inputs", "username")
        >>> print(selector)
        'input[placeholder*="用户"]'
    """

    def __init__(self):
        self.selectors = SELECTORS

    def get_selector(
        self,
        page: str,
        category: str,
        element: str,
        index: int = 0
    ) -> Optional[str]:
        """
        获取选择器

        Args:
            page (str): 页面名称
            category (str): 元素类别
            element (str): 元素名称
            index (int): 选择器索引（用于多选器场景）

        Returns:
            Optional[str]: 选择器字符串
        """
        try:
            selector_list = self.selectors[page][category][element]
            if isinstance(selector_list, list) and len(selector_list) > index:
                return selector_list[index]
            return None
        except KeyError:
            return None

    def get_all_selectors(
        self,
        page: str,
        category: str,
        element: str
    ) -> List[str]:
        """
        获取所有备选选择器

        Args:
            page (str): 页面名称
            category (str): 元素类别
            element (str): 元素名称

        Returns:
            List[str]: 选择器列表
        """
        try:
            return self.selectors[page][category][element]
        except KeyError:
            return []

    def get_page_url(self, page: str) -> Optional[str]:
        """
        获取页面URL（动态替换 base URL，支持运行时切换目标系统）

        Args:
            page (str): 页面名称

        Returns:
            Optional[str]: 页面URL
        """
        try:
            url = self.selectors[page]["url"]
            # 运行时替换 base URL（SELECTORS 在模块导入时已通过 f-string 烘焙旧 URL）
            from app.config import settings
            if settings.TARGET_URL and url:
                from urllib.parse import urlparse
                parsed = urlparse(url)
                if parsed.netloc:
                    old_base = f"{parsed.scheme}://{parsed.netloc}"
                    return url.replace(old_base, settings.TARGET_URL.rstrip('/'), 1)
            return url
        except KeyError:
            return None

    def get_login_selectors(self) -> Dict:
        """获取登录相关选择器"""
        return self.selectors.get("login", {})

    def get_common_selectors(self) -> Dict:
        """获取通用选择器"""
        return self.selectors.get("common", {})

    def resolve_selectors(
        self,
        page_key: Optional[str] = None,
        element_key: Optional[str] = None,
    ) -> List[str]:
        """
        通过 page_key + element_key 解析完整选择器链

        会在 SELECTORS 中查找以 page_key 为根的所有 category，
        收集 element_key 对应的选择器列表。

        Args:
            page_key (Optional[str]): 页面标识（如 "login"）
            element_key (Optional[str]): 元素标识（如 "username"）

        Returns:
            List[str]: 选择器列表（可能为空）
        """
        if not page_key or not element_key:
            return []

        page_def = self.selectors.get(page_key)
        if not isinstance(page_def, dict):
            return []

        collected: List[str] = []

        # 情况1：element_key 直接映射到顶层列表（如 common.loading）
        top_candidate = page_def.get(element_key)
        if isinstance(top_candidate, list) and top_candidate:
            collected.extend(top_candidate)

        # 情况2：element_key 嵌套在某个 category 下
        for category_name, category in page_def.items():
            # 跳过非字典字段（如 url）
            if not isinstance(category, dict):
                continue
            # 直接以 element_key 为键的列表
            candidate = category.get(element_key)
            if isinstance(candidate, list) and candidate:
                collected.extend(candidate)

        # 去重但保留顺序
        seen = set()
        deduped: List[str] = []
        for s in collected:
            if s not in seen:
                seen.add(s)
                deduped.append(s)
        return deduped


# 全局选择器映射器实例
mapper = SelectorMapper()


def get_smart_selector(
    page_key: str,
    element_type: str,
    element_name: str,
    fallback: str = "body"
) -> str:
    """
    智能获取选择器，带回退策略

    Args:
        page_key (str): 页面标识
        element_type (str): 元素类型
        element_name (str): 元素名称
        fallback (str): 回退选择器

    Returns:
        str: 选择器字符串
    """
    selector = mapper.get_selector(page_key, element_type, element_name)
    return selector or fallback


# 导出
__all__ = [
    "SELECTORS",
    "SelectorMapper",
    "mapper",
    "get_smart_selector",
]
