# -*- coding: utf-8 -*-
# filename: excel.py
# @Time    : 2025-01-20
# @Author  : Claude Code
# @Email   : noreply@anthropic.com
# @Software: PyCharm
"""Excel file handler for file preview tool"""
import logging
from pathlib import Path

import pandas as pd

from tf_tools_mcp.tools.file_preview_tools.file_preview_types import (
    FilePreviewOptions,
    SheetInfo,
)
from tf_tools_mcp.tools.file_preview_tools.handlers.base import (
    BaseFileHandler,
    format_file_size,
)

logger = logging.getLogger(__name__)


class ExcelHandler(BaseFileHandler):
    """Excel 处理器"""

    supported_extensions = {".xlsx", ".xls", ".csv"}
    supported_mime_types = {
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "application/vnd.ms-excel",
        "text/csv",
    }

    async def extract_metadata(self, file_path: str) -> dict:
        """提取 Excel 元数据

        Args:
            file_path: Excel 文件路径

        Returns:
            Excel 元数据字典
        """
        path = Path(file_path)
        ext = path.suffix.lower()

        # 读取所有 sheet
        if ext == ".csv":
            # CSV 只有一个 sheet
            sheets_dict = {"Sheet1": pd.read_csv(file_path)}
        elif ext == ".xls":
            # 旧版 .xls 文件需要使用 xlrd 引擎
            try:
                sheets_dict = pd.read_excel(file_path, sheet_name=None, engine="xlrd")
            except ImportError:
                # xlrd 未安装，尝试使用 openpyxl（可能失败）
                logger.warning("xlrd not installed, trying openpyxl for .xls file")
                sheets_dict = pd.read_excel(
                    file_path, sheet_name=None, engine="openpyxl"
                )
            except Exception as e:
                # 如果 xlrd 也无法读取，返回错误信息
                logger.error(f"Failed to read .xls file: {e}")
                return {
                    "sheet_names": [],
                    "sheets": {},
                }
        else:
            # Excel 文件可能有多个 sheet（使用 openpyxl）
            sheets_dict = pd.read_excel(file_path, sheet_name=None, engine="openpyxl")

        # 获取所有 sheet 名称
        sheet_names = list(sheets_dict.keys())

        # 提取每个 sheet 的元数据（仅包含有内容的 sheet）
        sheets_info = {}
        for sheet_name, df in sheets_dict.items():
            # 跳过完全空白的 sheet
            if df.empty or df.size == 0:
                continue

            # 获取列名
            columns = df.columns.tolist()

            # 获取形状
            shape = df.shape  # (rows, cols)

            # 获取数据类型
            dtypes = {col: str(dtype) for col, dtype in df.dtypes.items()}

            # 智能采样前 5 行，跳过空行
            sample_rows = []
            sample_count = 0
            for _idx, row in df.iterrows():
                # 跳过完全空白的行
                if row.isna().all():
                    continue

                # 将行转换为字典
                row_dict = {}
                for col in columns:
                    val = row[col]
                    # 处理 NaN 值
                    if pd.isna(val):
                        row_dict[col] = None
                    else:
                        row_dict[col] = val

                sample_rows.append(row_dict)
                sample_count += 1

                # 最多采样 5 行
                if sample_count >= 5:
                    break

            sheet_info = SheetInfo(
                columns=columns,
                shape=shape,
                dtypes=dtypes,
                sample_rows=sample_rows,
            )

            sheets_info[sheet_name] = sheet_info.model_dump()

        return {
            "sheet_names": sheet_names,
            "sheets": sheets_info,
        }

    async def generate_summary(self, file_path: str) -> str | None:
        """Excel 格式生成内容摘要（渲染元数据）

        Args:
            file_path: Excel 文件路径

        Returns:
            格式化的内容摘要
        """
        # 获取元数据
        metadata = await self.get_file_metadata(file_path)
        format_metadata = await self.extract_metadata(file_path)

        # 构建摘要
        lines = [
            f"文件名：{metadata.filename}",
            f"大小：{format_file_size(metadata.file_size)}",
            f"类型：{metadata.file_type}",
        ]

        # 添加Sheet信息
        sheet_names = format_metadata.get("sheet_names", [])
        sheets = format_metadata.get("sheets", {})

        lines.append(f"\nSheet数量：{len(sheet_names)}")

        # 限制summary总长度
        max_summary_length = 1000

        for sheet_name in sheet_names:
            sheet_info = sheets.get(sheet_name, {})
            if not sheet_info:
                continue

            # 添加当前sheet信息前检查长度
            current_length = len("\n".join(lines))
            if current_length >= max_summary_length:
                lines.append("\n... (内容已截断)")
                break

            lines.append(f"\n【{sheet_name}】")
            lines.append(f"- 列数：{len(sheet_info.get('columns', []))}")

            shape = sheet_info.get("shape", [0, 0])
            lines.append(f"- 行数：{shape[0]}")

            columns = sheet_info.get("columns", [])
            if columns:
                # 限制显示的列名数量
                display_columns = columns[:10]
                columns_str = ", ".join(display_columns)
                if len(columns) > 10:
                    columns_str += f" ...等{len(columns)}列"
                lines.append(f"- 列名：{columns_str}")

            # 显示样本行（最多3行）
            sample_rows = sheet_info.get("sample_rows", [])
            if sample_rows:
                lines.append(f"- 样本行（前{min(3, len(sample_rows))}行）：")
                for row in sample_rows[:3]:
                    row_str = "  | ".join([f"{k}: {v}" for k, v in row.items()])
                    lines.append(f"  {row_str}")

        return "\n".join(lines)
