# coding:utf-8
"""GIF 分割工具 MCP 服务器"""

from __future__ import annotations

import logging
import os
import sys
from pathlib import Path
from typing import Any, Dict, List

from mcp.server.fastmcp import FastMCP
from PIL import Image, ImageSequence

# 配置日志输出到 stderr，避免干扰 MCP stdio 传输
logging.basicConfig(
    level=logging.INFO if os.getenv('MCP_DEBUG') == '1' else logging.WARNING,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    stream=sys.stderr,
)

logger = logging.getLogger(__name__)

# 默认帧时长（毫秒）
DEFAULT_FRAME_DURATION_MS = 100

# 支持的输出格式
SUPPORTED_FORMATS = {
    "PNG": "png",
    "WEBP": "webp",
    "JPEG": "jpg",
    "JPG": "jpg",
    "TIFF": "tiff",
    "BMP": "bmp",
}


class GifSplitError(Exception):
    """GIF分割异常"""
    pass


def _normalize_path(file_path: str) -> Path:
    """
    规范化路径并验证文件存在性

    Args:
        file_path: 文件路径字符串

    Returns:
        Path对象

    Raises:
        GifSplitError: 文件不存在或不是文件
    """
    path = Path(file_path).expanduser().resolve()

    if not path.exists():
        raise GifSplitError(f"文件不存在: {path}")

    if not path.is_file():
        raise GifSplitError(f"路径不是文件: {path}")

    return path


def _ensure_directory(target_dir: str | None, source_file: Path) -> Path:
    """
    确保输出目录存在

    Args:
        target_dir: 用户指定的输出目录（可选）
        source_file: 源GIF文件路径

    Returns:
        输出目录Path对象
    """
    if target_dir:
        dir_path = Path(target_dir).expanduser().resolve()
    else:
        # 默认在GIF文件同级创建 <文件名>_frames 目录
        dir_path = source_file.parent / f"{source_file.stem}_frames"

    dir_path.mkdir(parents=True, exist_ok=True)
    logger.debug(f"输出目录: {dir_path}")

    return dir_path


def _validate_gif_format(image: Image.Image, file_path: Path) -> None:
    """
    验证文件是否为GIF格式

    Args:
        image: PIL Image对象
        file_path: 文件路径

    Raises:
        GifSplitError: 文件不是GIF格式
    """
    if image.format != "GIF":
        raise GifSplitError(f"文件不是GIF格式: {file_path} (实际格式: {image.format})")


# 初始化 FastMCP 服务器
mcp = FastMCP("GIF分割工具")


@mcp.tool()
async def split_gif_frames(
    file_path: str,
    output_dir: str | None = None,
    filename_prefix: str = "frame",
    image_format: str = "PNG",
    keep_transparency: bool = True,
) -> Dict[str, Any]:
    """
    将 GIF 动画拆分为多张静态图片。

    Args:
        file_path: GIF文件路径（必填）
        output_dir: 输出目录，默认为 <GIF文件名>_frames
        filename_prefix: 输出文件名前缀，默认为 "frame"
        image_format: 输出图片格式，支持 PNG/WEBP/JPEG/TIFF/BMP，默认为 "PNG"
        keep_transparency: 是否保留透明通道，默认为 True

    Returns:
        包含处理结果的字典:
        - output_dir: 输出目录路径
        - frame_count: 导出的帧数量
        - image_format: 实际使用的图片格式
        - files: 所有导出文件的路径列表

    Raises:
        GifSplitError: 处理失败时抛出异常

    Examples:
    """
    try:
        # 1. 验证输入文件
        gif_path = _normalize_path(file_path)
        logger.info(f"开始处理GIF文件: {gif_path}")

        # 2. 准备输出目录
        out_dir = _ensure_directory(output_dir, gif_path)

        # 3. 规范化输出格式
        format_upper = image_format.upper()
        if format_upper not in SUPPORTED_FORMATS:
            logger.warning(f"未知的格式 {format_upper}，将尝试使用原始格式")
            extension = format_upper.lower()
        else:
            extension = SUPPORTED_FORMATS[format_upper]

        # 4. 打开并验证GIF文件
        saved_files: List[str] = []

        with Image.open(gif_path) as image:
            _validate_gif_format(image, gif_path)

            # 获取帧数信息
            total_frames = getattr(image, "n_frames", 1)
            logger.info(f"GIF包含 {total_frames} 帧")

            # 5. 逐帧处理并保存
            for index, frame in enumerate(ImageSequence.Iterator(image)):
                try:
                    # 复制帧避免修改原图
                    frame_copy = frame.copy()

                    # 转换颜色模式
                    if keep_transparency:
                        # 保留透明度，转换为RGBA
                        if frame_copy.mode in ("RGBA", "LA", "P"):
                            converted = frame_copy.convert("RGBA")
                        else:
                            converted = frame_copy.convert("RGBA")
                    else:
                        # 不保留透明度，转换为RGB
                        converted = frame_copy.convert("RGB")

                    # 生成文件名（三位数编号，如 frame_000.png）
                    filename = f"{filename_prefix}_{index:03d}.{extension}"
                    destination = out_dir / filename

                    # 保存文件
                    converted.save(destination, format=format_upper)
                    saved_files.append(str(destination))

                    logger.debug(f"已保存第 {index + 1}/{total_frames} 帧: {destination}")

                except Exception as e:
                    logger.error(f"处理第 {index + 1} 帧时出错: {e}")
                    raise GifSplitError(f"处理第 {index + 1} 帧失败: {e}")

        # 6. 返回结果
        result = {
            "output_dir": str(out_dir),
            "frame_count": len(saved_files),
            "image_format": format_upper,
            "files": saved_files,
        }

        logger.info(f"✅ 成功导出 {len(saved_files)} 帧到 {out_dir}")
        return result

    except GifSplitError:
        raise
    except Exception as e:
        logger.error(f"GIF分割过程中发生错误: {e}")
        raise GifSplitError(f"GIF分割失败: {e}")


def main() -> None:
    """启动 GIF 分割 MCP 服务器（stdio 模式）"""
    import argparse

    parser = argparse.ArgumentParser(description='MCP GIF分割服务器')
    parser.add_argument(
        'transport',
        nargs='?',
        default='stdio',
        choices=['stdio', 'sse'],
        help='传输协议类型'
    )
    args = parser.parse_args()

    try:
        logger.info(f"🚀 启动 MCP GIF分割服务器 (transport: {args.transport})")

        if args.transport == 'sse':
            mcp.run(transport='sse', sse_host='127.0.0.1', sse_port=8080)
        else:
            mcp.run(transport='stdio')

    except KeyboardInterrupt:
        logger.info("接收到中断信号，正在退出...")
    except Exception as e:
        logger.error(f"服务器运行错误: {e}")
        raise


if __name__ == "__main__":
    main()
