"""插件基类"""

from abc import ABC, abstractmethod
from typing import Dict, Any, Callable, List, Optional
from playwright.sync_api import Page

from ..reference import MODULEDATA, INFO


class PluginBase(ABC):
    """插件基类

    所有插件必须继承此类并实现必要方法。
    """

    # 插件元信息
    name: str = "base_plugin"
    version: str = "1.0.0"
    description: str = "Base plugin"
    author: str = ""

    def __init__(self, page: Page = None):
        """初始化插件

        Args:
            page: Playwright Page 实例
        """
        self._page = page
        self._keywords: Dict[str, Callable] = {}
        self._element_data: Dict[str, Any] = {}
        self._config: Dict[str, Any] = {}
        self._initialized = False

    @abstractmethod
    def setup(self) -> None:
        """插件初始化

        子类必须实现此方法，用于：
        - 注册关键字
        - 加载元素数据
        - 初始化配置
        """
        pass

    def teardown(self) -> None:
        """插件清理

        子类可选实现，用于清理资源。
        """
        pass

    def register_keyword(self, name: str, handler: Callable) -> None:
        """注册关键字

        Args:
            name: 关键字名称
            handler: 处理函数
        """
        self._keywords[name] = handler
        INFO(f"[{self.name}] 注册关键字: {name}")

    def register_keywords(self, keywords: Dict[str, Callable]) -> None:
        """批量注册关键字

        Args:
            keywords: 关键字字典
        """
        for name, handler in keywords.items():
            self.register_keyword(name, handler)

    def load_element_data(self, data: Dict[str, Any]) -> None:
        """加载元素数据

        Args:
            data: 元素数据字典
        """
        self._element_data.update(data)
        INFO(f"[{self.name}] 加载元素数据: {len(data)} 个模块")

    def load_element_data_from_file(self, file_path: str) -> None:
        """从文件加载元素数据

        Args:
            file_path: YAML 文件路径
        """
        try:
            import yaml
            from pathlib import Path

            path = Path(file_path)
            if not path.exists():
                INFO(f"[{self.name}] 元素数据文件不存在: {file_path}", "WARNING")
                return

            with open(path, 'r', encoding='utf-8') as f:
                data = yaml.safe_load(f) or {}
                self.load_element_data(data)

        except ImportError:
            INFO(f"[{self.name}] PyYAML 未安装，无法加载 YAML 文件", "WARNING")
        except Exception as e:
            INFO(f"[{self.name}] 加载元素数据失败: {e}", "ERROR")

    def load_config(self, config: Dict[str, Any]) -> None:
        """加载配置

        Args:
            config: 配置字典
        """
        self._config.update(config)

    def load_config_from_file(self, file_path: str) -> None:
        """从 INI 文件加载配置

        Args:
            file_path: INI 文件路径
        """
        try:
            import configparser
            from pathlib import Path

            path = Path(file_path)
            if not path.exists():
                INFO(f"[{self.name}] 配置文件不存在: {file_path}", "WARNING")
                return

            config = configparser.ConfigParser()
            config.read(str(path), encoding='utf-8')

            for section in config.sections():
                self._config[section] = dict(config.items(section))

            INFO(f"[{self.name}] 加载配置: {list(self._config.keys())}")

        except Exception as e:
            INFO(f"[{self.name}] 加载配置失败: {e}", "ERROR")

    @property
    def keywords(self) -> Dict[str, Callable]:
        """获取所有关键字"""
        return self._keywords.copy()

    @property
    def element_data(self) -> Dict[str, Any]:
        """获取元素数据"""
        return self._element_data.copy()

    @property
    def config(self) -> Dict[str, Any]:
        """获取配置"""
        return self._config.copy()

    @property
    def page(self) -> Optional[Page]:
        """获取 Page 实例"""
        return self._page

    def set_page(self, page: Page) -> None:
        """设置 Page 实例

        Args:
            page: Playwright Page 实例
        """
        self._page = page

    def initialize(self) -> None:
        """初始化插件（内部调用）"""
        if not self._initialized:
            self.setup()
            self._initialized = True

            # 存储到全局
            MODULEDATA[self.name] = {
                'keywords': self._keywords,
                'element_data': self._element_data,
                'config': self._config,
            }

    def __repr__(self) -> str:
        return f"<Plugin {self.name} v{self.version}>"
