"""Excel 测试用例解析器"""

from typing import List, Dict, Any, Optional, Tuple
from pathlib import Path

from ...reference import INFO
from ...common import EXCEL_COLUMNS


class ExcelReader:
    """Excel 测试用例读取器

    兼容原 kdtest Excel 格式，解析测试用例文件。
    """

    def __init__(self, file_path: str):
        """初始化 Excel 读取器

        Args:
            file_path: Excel 文件路径
        """
        self._file_path = Path(file_path)
        self._workbook = None
        self._sheets: List[str] = []

        if not self._file_path.exists():
            raise FileNotFoundError(f"Excel 文件不存在: {file_path}")

        self._load_workbook()

    def _load_workbook(self) -> None:
        """加载工作簿"""
        try:
            import openpyxl
            self._workbook = openpyxl.load_workbook(str(self._file_path), data_only=True)
            self._sheets = self._workbook.sheetnames
            INFO(f"加载 Excel: {self._file_path.name}, Sheets: {self._sheets}")
        except ImportError:
            raise ImportError("请安装 openpyxl: pip install openpyxl")

    @property
    def sheet_names(self) -> List[str]:
        """获取所有 Sheet 名称"""
        return self._sheets.copy()

    def read_sheet(self, sheet_name: str) -> List[Dict[str, Any]]:
        """读取指定 Sheet 的测试用例

        Args:
            sheet_name: Sheet 名称

        Returns:
            List[Dict]: 测试用例列表
        """
        if sheet_name not in self._sheets:
            raise ValueError(f"Sheet 不存在: {sheet_name}")

        sheet = self._workbook[sheet_name]
        cases = []
        current_case = None
        steps = []

        for row_idx, row in enumerate(sheet.iter_rows(min_row=1, values_only=True), start=1):
            # 跳过空行
            if not any(row):
                continue

            # 获取各列值
            case_id = self._get_cell_value(row, 0)
            case_name = self._get_cell_value(row, 1)
            description = self._get_cell_value(row, 2)
            keyword = self._get_cell_value(row, 3)

            # 获取定位信息 (E-N 列，索引 4-13)
            locator_info = []
            for i in range(4, 14):
                val = self._get_cell_value(row, i)
                if val:
                    locator_info.append(val)

            # 获取操作值 (O 列，索引 14)
            value = self._get_cell_value(row, 14)

            # 判断是否是用例开始行
            if case_id or case_name:
                # 保存上一个用例
                if current_case and steps:
                    current_case['steps'] = steps
                    cases.append(current_case)

                # 开始新用例
                current_case = {
                    'id': case_id or f"case_{len(cases) + 1}",
                    'name': case_name or f"用例{len(cases) + 1}",
                    'sheet': sheet_name,
                    'row': row_idx,
                    'steps': []
                }
                steps = []

                # 如果当前行有关键字，也作为第一个步骤
                if keyword:
                    steps.append({
                        'row': row_idx,
                        'description': description,
                        'keyword': keyword,
                        'locator': locator_info,
                        'value': value
                    })
            elif keyword:
                # 步骤行
                steps.append({
                    'row': row_idx,
                    'description': description,
                    'keyword': keyword,
                    'locator': locator_info,
                    'value': value
                })

        # 保存最后一个用例
        if current_case and steps:
            current_case['steps'] = steps
            cases.append(current_case)

        INFO(f"读取 {sheet_name}: {len(cases)} 个用例")
        return cases

    def read_all_sheets(self, include_sheets: List[str] = None) -> Dict[str, List[Dict[str, Any]]]:
        """读取所有或指定 Sheet 的测试用例

        Args:
            include_sheets: 要包含的 Sheet 列表，None 表示全部

        Returns:
            Dict[sheet_name, cases]: Sheet 名称到用例列表的映射
        """
        result = {}
        sheets_to_read = include_sheets or self._sheets

        for sheet_name in sheets_to_read:
            if sheet_name in self._sheets:
                result[sheet_name] = self.read_sheet(sheet_name)

        return result

    def _get_cell_value(self, row: tuple, index: int) -> Optional[str]:
        """获取单元格值

        Args:
            row: 行数据
            index: 列索引

        Returns:
            单元格值（字符串）
        """
        if index >= len(row):
            return None

        value = row[index]
        if value is None:
            return None

        return str(value).strip()

    def get_case_count(self, sheet_name: str = None) -> int:
        """获取用例数量

        Args:
            sheet_name: Sheet 名称，None 表示全部

        Returns:
            int: 用例数量
        """
        if sheet_name:
            return len(self.read_sheet(sheet_name))

        total = 0
        for sheet in self._sheets:
            total += len(self.read_sheet(sheet))
        return total

    def close(self) -> None:
        """关闭工作簿"""
        if self._workbook:
            self._workbook.close()
            self._workbook = None

    def __enter__(self) -> 'ExcelReader':
        return self

    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        self.close()


class TestCase:
    """测试用例数据类"""

    def __init__(self, data: Dict[str, Any]):
        self.id = data.get('id', '')
        self.name = data.get('name', '')
        self.sheet = data.get('sheet', '')
        self.row = data.get('row', 0)
        self.steps: List['TestStep'] = []

        for step_data in data.get('steps', []):
            self.steps.append(TestStep(step_data))

    def __repr__(self) -> str:
        return f"TestCase(id={self.id}, name={self.name}, steps={len(self.steps)})"


class TestStep:
    """测试步骤数据类"""

    def __init__(self, data: Dict[str, Any]):
        self.row = data.get('row', 0)
        self.description = data.get('description', '')
        self.keyword = data.get('keyword', '')
        self.locator = data.get('locator', [])
        self.value = data.get('value')

    def __repr__(self) -> str:
        return f"TestStep(keyword={self.keyword}, value={self.value})"
