"""菜单导航关键字 - 支持多级菜单结构"""

import json
from playwright.sync_api import Page, Locator
from typing import Optional, Dict, Any, List
from pathlib import Path

from ..base_keyword import BaseKeyword
from ...reference import INFO, MODULEDATA, set_element_value


class ElMenuKeyword(BaseKeyword):
    """多级菜单导航关键字

    支持 modularInformation.json 格式的菜单配置：
    {
        "一级菜单": {
            "selfLocatin": ["xpath", "定位表达式"],
            "subordinate": {
                "二级菜单": {
                    "iframe": "iframe名称",
                    "locatingNodes": ["xpath", "定位表达式"],
                    "submodule": {...},  // 三级菜单
                    "tagPage": [...]     // 页签
                }
            }
        }
    }
    """

    def __init__(self, page: Page):
        super().__init__(page)
        self._menu_data: Dict[str, Any] = {}
        self._current_iframe: Optional[str] = None

    def load_menu_data(self, file_path: str = None, *, content: str = None) -> None:
        """加载菜单配置文件

        Args:
            file_path: modularInformation.json 文件路径
            content: 文件路径 (关键字调用时使用)
        """
        # 支持两种调用方式
        path_str = content or file_path
        if not path_str:
            INFO("未指定菜单配置文件路径", "ERROR")
            return

        path = Path(path_str)
        if not path.exists():
            INFO(f"菜单配置文件不存在: {path_str}", "ERROR")
            return

        with open(path, 'r', encoding='utf-8') as f:
            self._menu_data = json.load(f)

        MODULEDATA['menuData'] = self._menu_data
        INFO(f"加载菜单配置: {len(self._menu_data)} 个一级菜单")

    def set_menu_data(self, menu_data: Dict[str, Any]) -> None:
        """直接设置菜单数据

        Args:
            menu_data: 菜单数据字典
        """
        self._menu_data = menu_data
        MODULEDATA['menuData'] = self._menu_data

    # ==================== 菜单导航关键字 ====================

    def menu_navigate(
        self,
        targeting: str = None,
        element: str = None,
        index: Optional[int] = None,
        *,
        content: str
    ) -> None:
        """导航到指定菜单

        支持多种格式：
        - "一级菜单" - 只点击一级菜单
        - "一级菜单/二级菜单" - 导航到二级菜单
        - "一级菜单/二级菜单/三级菜单" - 导航到三级菜单
        - "一级菜单/二级菜单#页签索引" - 导航到二级菜单并点击页签

        Args:
            targeting: 未使用
            element: 未使用
            index: 未使用
            content: 菜单路径
        """
        menu_path = str(content)
        INFO(f"菜单导航: {menu_path}")

        # 解析页签
        tag_index = None
        if '#' in menu_path:
            menu_path, tag_str = menu_path.rsplit('#', 1)
            tag_index = int(tag_str)

        # 解析菜单层级
        levels = [level.strip() for level in menu_path.split('/')]

        if len(levels) >= 1:
            # 点击一级菜单
            self._click_first_level_menu(levels[0])

        if len(levels) >= 2:
            # 点击二级菜单
            self._click_second_level_menu(levels[0], levels[1])

        if len(levels) >= 3:
            # 点击三级菜单
            self._click_third_level_menu(levels[0], levels[1], levels[2])

        # 点击页签
        if tag_index is not None and len(levels) >= 2:
            self._click_tag_page(levels[0], levels[1], tag_index)

    def menu_click_first(self, *, content: str) -> None:
        """点击一级菜单

        Args:
            content: 一级菜单名称
        """
        self._click_first_level_menu(content)

    def menu_click_second(self, *, content: str) -> None:
        """点击二级菜单

        Args:
            content: 格式 "一级菜单/二级菜单"
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 2:
            INFO(f"二级菜单格式错误: {content}", "ERROR")
            return

        self._click_first_level_menu(levels[0])
        self._click_second_level_menu(levels[0], levels[1])

    def menu_click_third(self, *, content: str) -> None:
        """点击三级菜单

        Args:
            content: 格式 "一级菜单/二级菜单/三级菜单"
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 3:
            INFO(f"三级菜单格式错误: {content}", "ERROR")
            return

        self._click_first_level_menu(levels[0])
        self._click_second_level_menu(levels[0], levels[1])
        self._click_third_level_menu(levels[0], levels[1], levels[2])

    def menu_click_tag(self, *, content: str, tag_index: int = 0) -> None:
        """点击页签

        Args:
            content: 格式 "一级菜单/二级菜单"
            tag_index: 页签索引 (从0开始)
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 2:
            INFO(f"菜单格式错误: {content}", "ERROR")
            return

        self._click_tag_page(levels[0], levels[1], tag_index)

    def menu_switch_iframe(self, *, content: str) -> None:
        """切换到菜单对应的 iframe

        Args:
            content: 格式 "一级菜单/二级菜单"
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 2:
            INFO(f"菜单格式错误: {content}", "ERROR")
            return

        first_menu = levels[0]
        second_menu = levels[1]

        menu_info = self._get_second_menu_info(first_menu, second_menu)
        if not menu_info:
            return

        iframe_name = menu_info.get('iframe', '')
        if iframe_name:
            self._switch_to_iframe(iframe_name)
        else:
            INFO(f"菜单 {content} 没有 iframe 配置")

    def menu_exit_iframe(self) -> None:
        """退出当前 iframe，返回主文档"""
        self.frame_default()
        self._current_iframe = None
        INFO("退出 iframe，返回主文档")

    # ==================== 内部方法 ====================

    def _click_first_level_menu(self, menu_name: str) -> None:
        """点击一级菜单

        Args:
            menu_name: 一级菜单名称
        """
        if menu_name not in self._menu_data:
            INFO(f"一级菜单不存在: {menu_name}", "ERROR")
            return

        menu_config = self._menu_data[menu_name]
        locator_info = menu_config.get('selfLocatin', [])

        if len(locator_info) >= 2:
            targeting = locator_info[0]
            element = locator_info[1]

            # 确保在主文档中
            self.frame_default()

            loc = self.locator(targeting, element)
            loc.click()
            self.page.wait_for_timeout(300)
            INFO(f"点击一级菜单: {menu_name}")
        else:
            INFO(f"一级菜单 {menu_name} 缺少定位信息", "ERROR")

    def _click_second_level_menu(self, first_menu: str, second_menu: str) -> None:
        """点击二级菜单

        Args:
            first_menu: 一级菜单名称
            second_menu: 二级菜单名称
        """
        menu_info = self._get_second_menu_info(first_menu, second_menu)
        if not menu_info:
            return

        locator_info = menu_info.get('locatingNodes', [])

        if len(locator_info) >= 2:
            targeting = locator_info[0]
            element = locator_info[1]

            # 确保在主文档中（二级菜单通常在主文档）
            self.frame_default()

            loc = self.locator(targeting, element)
            loc.click()
            self.page.wait_for_timeout(500)
            INFO(f"点击二级菜单: {first_menu}/{second_menu}")

            # 自动切换到 iframe（如果配置了）
            iframe_name = menu_info.get('iframe', '')
            if iframe_name:
                self._switch_to_iframe(iframe_name)
        else:
            INFO(f"二级菜单 {first_menu}/{second_menu} 缺少定位信息", "ERROR")

    def _click_third_level_menu(self, first_menu: str, second_menu: str, third_menu: str) -> None:
        """点击三级菜单

        Args:
            first_menu: 一级菜单名称
            second_menu: 二级菜单名称
            third_menu: 三级菜单名称
        """
        menu_info = self._get_second_menu_info(first_menu, second_menu)
        if not menu_info:
            return

        submodule = menu_info.get('submodule')
        if not submodule or third_menu not in submodule:
            INFO(f"三级菜单不存在: {first_menu}/{second_menu}/{third_menu}", "ERROR")
            return

        third_menu_info = submodule[third_menu]
        locator_info = third_menu_info.get('locatingNodes', [])

        if len(locator_info) >= 2:
            targeting = locator_info[0]
            element = locator_info[1]

            loc = self.locator(targeting, element)
            loc.click()
            self.page.wait_for_timeout(300)
            INFO(f"点击三级菜单: {first_menu}/{second_menu}/{third_menu}")

            # 三级菜单可能也有自己的 iframe
            iframe_name = third_menu_info.get('iframe', '')
            if iframe_name:
                self._switch_to_iframe(iframe_name)
        else:
            INFO(f"三级菜单 {third_menu} 缺少定位信息", "ERROR")

    def _click_tag_page(self, first_menu: str, second_menu: str, tag_index: int) -> None:
        """点击页签

        Args:
            first_menu: 一级菜单名称
            second_menu: 二级菜单名称
            tag_index: 页签索引
        """
        menu_info = self._get_second_menu_info(first_menu, second_menu)
        if not menu_info:
            return

        tag_pages = menu_info.get('tagPage')
        if not tag_pages:
            INFO(f"菜单 {first_menu}/{second_menu} 没有页签配置", "WARNING")
            return

        if tag_index >= len(tag_pages):
            INFO(f"页签索引超出范围: {tag_index} (共 {len(tag_pages)} 个页签)", "ERROR")
            return

        locator_info = tag_pages[tag_index]
        if len(locator_info) >= 2:
            targeting = locator_info[0]
            element = locator_info[1]

            loc = self.locator(targeting, element)
            loc.click()
            self.page.wait_for_timeout(300)
            INFO(f"点击页签 [{tag_index}]: {first_menu}/{second_menu}")
        else:
            INFO(f"页签 {tag_index} 缺少定位信息", "ERROR")

    def _get_second_menu_info(self, first_menu: str, second_menu: str) -> Optional[Dict[str, Any]]:
        """获取二级菜单配置

        Args:
            first_menu: 一级菜单名称
            second_menu: 二级菜单名称

        Returns:
            二级菜单配置字典
        """
        if first_menu not in self._menu_data:
            INFO(f"一级菜单不存在: {first_menu}", "ERROR")
            return None

        subordinate = self._menu_data[first_menu].get('subordinate', {})
        if second_menu not in subordinate:
            INFO(f"二级菜单不存在: {first_menu}/{second_menu}", "ERROR")
            return None

        return subordinate[second_menu]

    def _switch_to_iframe(self, iframe_name: str) -> None:
        """切换到指定 iframe

        Args:
            iframe_name: iframe 名称或 ID
        """
        if not iframe_name:
            return

        # 先回到主文档
        self.frame_default()

        # 切换到目标 iframe
        try:
            # 尝试通过 name 或 id 定位
            frame_locator = self.page.frame_locator(f'iframe[name="{iframe_name}"], iframe#{iframe_name}, #{iframe_name}')
            self._current_frame = frame_locator
            self._current_iframe = iframe_name
            INFO(f"切换到 iframe: {iframe_name}")
        except Exception as e:
            INFO(f"切换 iframe 失败: {iframe_name} - {e}", "ERROR")

    # ==================== 辅助方法 ====================

    def menu_get_first_menus(self) -> List[str]:
        """获取所有一级菜单名称

        Returns:
            List[str]: 一级菜单名称列表
        """
        return list(self._menu_data.keys())

    def menu_get_second_menus(self, *, content: str) -> List[str]:
        """获取指定一级菜单下的所有二级菜单

        Args:
            content: 一级菜单名称

        Returns:
            List[str]: 二级菜单名称列表
        """
        if content not in self._menu_data:
            return []

        subordinate = self._menu_data[content].get('subordinate', {})
        return list(subordinate.keys())

    def menu_get_tag_count(self, *, content: str) -> int:
        """获取菜单的页签数量

        Args:
            content: 格式 "一级菜单/二级菜单"

        Returns:
            int: 页签数量
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 2:
            return 0

        menu_info = self._get_second_menu_info(levels[0], levels[1])
        if not menu_info:
            return 0

        tag_pages = menu_info.get('tagPage')
        return len(tag_pages) if tag_pages else 0

    def menu_has_iframe(self, *, content: str) -> bool:
        """检查菜单是否有 iframe

        Args:
            content: 格式 "一级菜单/二级菜单"

        Returns:
            bool: 是否有 iframe
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 2:
            return False

        menu_info = self._get_second_menu_info(levels[0], levels[1])
        if not menu_info:
            return False

        return bool(menu_info.get('iframe'))

    def menu_get_iframe_name(self, *, content: str) -> str:
        """获取菜单的 iframe 名称

        Args:
            content: 格式 "一级菜单/二级菜单"

        Returns:
            str: iframe 名称
        """
        levels = [level.strip() for level in content.split('/')]
        if len(levels) < 2:
            return ''

        menu_info = self._get_second_menu_info(levels[0], levels[1])
        if not menu_info:
            return ''

        return menu_info.get('iframe', '')
