# -*- coding: utf-8 -*-
# filename: base.py
# @Time    : 2025-01-20
# @Author  : Claude Code
# @Email   : noreply@anthropic.com
# @Software: PyCharm
"""Base file handler for file preview tool"""
import logging
from abc import ABC, abstractmethod
from datetime import datetime
from pathlib import Path

from tf_tools_mcp.tools.file_preview_tools.file_preview_types import (
    ErrorCode,
    FileMetadata,
    FilePreviewOptions,
    FilePreviewStatus,
    SingleFileResult,
)

logger = logging.getLogger(__name__)


def format_file_size(bytes_size: int) -> str:
    """格式化文件大小为人类可读格式

    Args:
        bytes_size: 文件大小（字节）

    Returns:
        格式化后的字符串，如 "12.5 MB"
    """
    for unit in ["B", "KB", "MB", "GB", "TB"]:
        if bytes_size < 1024.0:
            return f"{bytes_size:.2f} {unit}"
        bytes_size /= 1024.0
    return f"{bytes_size:.2f} PB"


class BaseFileHandler(ABC):
    """文件处理器基类"""

    # 子类需要定义支持的扩展名和 MIME 类型
    supported_extensions: set[str] = set()
    supported_mime_types: set[str] = set()

    def __init__(self, options: FilePreviewOptions):
        self.options = options

    @abstractmethod
    async def extract_metadata(self, file_path: str) -> dict:
        """提取格式特定的元数据

        Args:
            file_path: 文件路径

        Returns:
            格式特定的元数据字典
        """
        pass

    @abstractmethod
    async def generate_summary(self, file_path: str) -> str | None:
        """生成内容描述（可选）

        Args:
            file_path: 文件路径

        Returns:
            内容描述文本，如果不需要生成则返回 None
        """
        pass

    async def get_file_metadata(self, file_path: str) -> FileMetadata:
        """获取基础文件元数据

        Args:
            file_path: 文件路径

        Returns:
            FileMetadata 对象
        """
        path = Path(file_path)

        # 获取文件状态
        stat = path.stat()

        # 获取 MIME 类型（简化版本）
        import mimetypes

        mime_type, _ = mimetypes.guess_type(file_path)
        if mime_type is None:
            mime_type = "application/octet-stream"

        return FileMetadata(
            filename=path.name,
            file_size=stat.st_size,
            file_type=mime_type,
            created_at=datetime.fromtimestamp(stat.st_ctime).isoformat()
            if stat.st_ctime
            else None,
            modified_at=datetime.fromtimestamp(stat.st_mtime).isoformat()
            if stat.st_mtime
            else None,
        )

    def supports_file(self, file_path: str, mime_type: str | None = None) -> bool:
        """检查是否支持该文件类型

        Args:
            file_path: 文件路径
            mime_type: 可选的 MIME 类型

        Returns:
            是否支持该文件类型
        """
        path = Path(file_path)
        ext = path.suffix.lower()

        # 优先检查扩展名
        if ext in self.supported_extensions:
            return True

        # 如果提供了 MIME 类型，也检查
        if mime_type and mime_type in self.supported_mime_types:
            return True

        return False

    async def process(self, file_path: str) -> SingleFileResult:
        """处理单个文件的完整流程

        Args:
            file_path: 文件路径

        Returns:
            SingleFileResult 对象
        """
        try:
            # 获取基础元数据
            metadata = await self.get_file_metadata(file_path)

            # 提取格式特定元数据
            format_metadata = await self.extract_metadata(file_path)

            # 生成内容描述（可选）
            content_summary = await self.generate_summary(file_path)

            return SingleFileResult(
                file_path=file_path,
                status=FilePreviewStatus.SUCCESS,
                metadata=metadata,
                format_metadata=format_metadata,
                content_summary=content_summary,
            )

        except FileNotFoundError as e:
            logger.error(f"File not found: {file_path} - {e}")
            return SingleFileResult(
                file_path=file_path,
                status=FilePreviewStatus.FAILED,
                error_code=ErrorCode.FILE_NOT_FOUND,
                error_message=f"File not found: {e}",
                metadata=FileMetadata(
                    filename=Path(file_path).name,
                    file_size=0,
                    file_type="unknown",
                ),
                format_metadata={},
            )

        except Exception as e:
            logger.error(f"Error processing file {file_path}: {e}")
            return SingleFileResult(
                file_path=file_path,
                status=FilePreviewStatus.FAILED,
                error_code=ErrorCode.PARSE_ERROR,
                error_message=str(e),
                metadata=FileMetadata(
                    filename=Path(file_path).name,
                    file_size=0,
                    file_type="unknown",
                ),
                format_metadata={},
            )
