import logging
import os
import shutil
import sys
import tempfile
import zipfile
from datetime import datetime
from pathlib import Path
from typing import Optional

from fastapi import APIRouter, File, Form, HTTPException, UploadFile
from fastapi.responses import FileResponse


logger = logging.getLogger(__name__)

router = APIRouter()


@router.post(
    "/api/image/compress",
    tags=["image"],
    summary="图片压缩（HTTP API）",
    description=(
        "批量压缩图片，支持多种压缩类型和格式转换。\n\n"
        "输入格式：ZIP压缩包（包含图片文件）\n"
        "输出格式：ZIP压缩包（包含压缩后的图片文件）\n\n"
        "支持的压缩类型：\n"
        "- image_lossless（通用图片无损压缩）\n"
        "- image_extreme（通用图片极度压缩）\n"
        "- image_force_lossless（通用图片强制无损压缩）\n"
        "- image_ultra（通用图片超强压缩）\n"
        "- webp（转换为WebP格式）\n"
        "- avif（转换为AVIF格式）\n\n"
        "ZIP包中支持的图片格式：\n"
        "- PNG\n"
        "- JPG\n"
        "- JPEG\n"
        "- BMP\n"
        "- TIFF\n"
        "- GIF\n\n"
        "注意：此接口接受二进制文件上传，适合通过 HTTP API 直接调用。\n"
        "如需通过 MCP 调用，请使用独立的 MCP 服务器中的 compress_images 工具（支持目录路径参数）。"
    ),
    operation_id="compress_image_api_image_compress_post",
)
async def compress_images(
    file: UploadFile = File(..., description="包含图片的ZIP压缩包"),
    compression_type: str = Form(
        ..., description="压缩类型: image_lossless, image_extreme, image_force_lossless, image_ultra, webp, avif"
    ),
    max_size_kb: Optional[int] = Form(50, description="目标最大文件大小(KB)"),
    quality: Optional[int] = Form(80, description="WebP/AVIF质量 (0-100)"),
    keep_original_size: Optional[bool] = Form(False, description="是否保持原始尺寸"),
    optimize: Optional[bool] = Form(True, description="是否启用优化"),
    method: Optional[int] = Form(6, description="压缩方法 (0-6)"),
):
    """
    图片压缩API接口

    支持的压缩类型:

    通用图片压缩（支持所有格式）:
    - image_lossless: 通用图片无损压缩
    - image_extreme: 通用图片极度压缩（有损）
    - image_force_lossless: 通用图片强制无损压缩
    - image_ultra: 通用图片超强压缩（智能有损/无损）

    格式转换:
    - webp: 转换为WebP格式
    - avif: 转换为AVIF格式

    支持的输入格式: PNG, JPG, JPEG, BMP, TIFF, GIF
    输入: ZIP压缩包（包含图片文件）
    输出: ZIP压缩包（包含压缩后的图片文件）
    """

    # 验证文件类型
    if not file.filename.lower().endswith(".zip"):
        raise HTTPException(status_code=400, detail="文件必须是ZIP压缩包格式")

    # 验证压缩类型
    valid_compression_types = [
        # 通用图片压缩
        "image_lossless",
        "image_extreme",
        "image_force_lossless",
        "image_ultra",
        # 格式转换
        "webp",
        "avif",
    ]
    if compression_type not in valid_compression_types:
        raise HTTPException(
            status_code=400,
            detail=f"不支持的压缩类型。支持的类型: {', '.join(valid_compression_types)}",
        )

    # 动态导入图片压缩功能模块（packages/compress_image/entry.py）
    compress_image_pkg = Path(__file__).resolve().parent

    # 只在不存在时才添加到sys.path
    pkg_path = str(compress_image_pkg)
    path_added = False
    if pkg_path not in sys.path:
        sys.path.insert(0, pkg_path)
        path_added = True

    try:
        from entry import (  # type: ignore
            compress_image_lossless,
            compress_image_extreme,
            compress_image_force_lossless,
            compress_image_ultra,
            convert_to_webp,
            convert_to_avif,
        )
    except ImportError as e:
        raise HTTPException(status_code=500, detail=f"无法导入图片压缩模块: {str(e)}")
    finally:
        # 清理添加的路径，避免污染全局sys.path
        if path_added:
            try:
                sys.path.remove(pkg_path)
            except Exception:
                pass

    # 创建临时目录
    temp_dir = tempfile.mkdtemp()
    temp_path = Path(temp_dir)
    input_dir = temp_path / "input"
    output_dir = temp_path / "output"

    try:
        # 保存上传的ZIP文件
        zip_file_path = temp_path / file.filename
        contents = await file.read()
        with open(zip_file_path, "wb") as f:
            f.write(contents)

        # 解压ZIP文件
        with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
            zip_ref.extractall(input_dir)

        # 检查解压后是否有图片文件
        image_files = []
        for root, _, files in os.walk(input_dir):
            for file_name in files:
                if Path(file_name).suffix.lower() in {
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                }:
                    image_files.append(Path(root) / file_name)

        if not image_files:
            raise HTTPException(status_code=400, detail="ZIP文件中没有找到支持的图片文件")

        # 创建输出目录
        output_dir.mkdir(parents=True, exist_ok=True)

        # 根据压缩类型进行压缩
        if compression_type == "image_lossless":
            compress_image_lossless(
                input_dir, output_dir, max_size_kb=max_size_kb)
        elif compression_type == "image_extreme":
            compress_image_extreme(
                input_dir,
                output_dir,
                max_size_kb=max_size_kb,
                keep_original_size=keep_original_size,
            )
        elif compression_type == "image_force_lossless":
            compress_image_force_lossless(input_dir, output_dir)
        elif compression_type == "image_ultra":
            compress_image_ultra(
                input_dir,
                output_dir,
                max_size_kb=max_size_kb,
                lossless=(quality >= 95),
                keep_original_size=keep_original_size,
            )
        elif compression_type == "webp":
            convert_to_webp(
                input_dir,
                output_dir,
                quality=quality,
                optimize=optimize,
                method=method,
            )
        elif compression_type == "avif":
            convert_to_avif(input_dir, output_dir)

        # 检查输出目录是否有文件
        output_files = list(output_dir.glob("**/*"))
        output_files = [f for f in output_files if f.is_file()]

        if not output_files:
            raise HTTPException(status_code=500, detail="压缩过程中没有生成任何输出文件")

        # 创建输出ZIP文件
        output_zip_path = temp_path / \
            f"compressed_{compression_type}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip"

        with zipfile.ZipFile(output_zip_path, "w", zipfile.ZIP_DEFLATED) as zip_ref:
            for file_path in output_files:
                # 保持目录结构
                relative_path = file_path.relative_to(output_dir)
                zip_ref.write(file_path, relative_path)

        # 计算压缩统计信息
        original_size = sum(f.stat().st_size for f in image_files) / 1024  # KB
        compressed_size = output_zip_path.stat().st_size / 1024  # KB
        compression_ratio = (
            1 - compressed_size / original_size
        ) * 100 if original_size > 0 else 0

        logger.info(
            f"图片压缩完成 - 类型: {compression_type}, 原始大小: {original_size:.1f}KB, 压缩后大小: {compressed_size:.1f}KB, 压缩率: {compression_ratio:.1f}%"
        )

        # 将压缩后的ZIP文件移动到持久化临时位置
        persistent_temp_file = tempfile.NamedTemporaryFile(
            delete=False, suffix=".zip", prefix=f"compressed_{compression_type}_"
        )
        persistent_temp_file.close()
        persistent_temp_path = Path(persistent_temp_file.name)

        # 复制文件到持久化位置
        shutil.copy2(output_zip_path, persistent_temp_path)

        # 立即清理原临时目录
        shutil.rmtree(temp_path, ignore_errors=True)

        # 返回压缩后的ZIP文件
        return FileResponse(
            path=str(persistent_temp_path),
            filename=f"compressed_{compression_type}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip",
            media_type="application/zip",
            headers={
                "X-Compression-Type": compression_type,
                "X-Original-Size-KB": str(round(original_size, 1)),
                "X-Compressed-Size-KB": str(round(compressed_size, 1)),
                "X-Compression-Ratio": str(round(compression_ratio, 1)),
                "X-Processed-Files": str(len(image_files)),
            },
        )

    except zipfile.BadZipFile:
        shutil.rmtree(temp_path, ignore_errors=True)
        raise HTTPException(status_code=400, detail="无效的ZIP文件格式")
    except Exception as e:
        shutil.rmtree(temp_path, ignore_errors=True)
        logger.error(f"图片压缩过程中发生错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"图片压缩失败: {str(e)}")


@router.get("/api/image/compression-types")
async def get_compression_types():
    """获取支持的图片压缩类型和参数说明"""
    return {
        "compression_types": {
            # 通用图片压缩
            "image_lossless": {
                "name": "通用图片无损压缩",
                "description": "支持所有常用格式的无损压缩，保持透明度",
                "parameters": ["max_size_kb"],
                "output_format": "webp",
                "supports_transparency": True,
                "supported_formats": [
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                ],
                "category": "universal",
            },
            "image_extreme": {
                "name": "通用图片极度压缩",
                "description": "支持所有常用格式的有损压缩，可选择是否缩放",
                "parameters": ["max_size_kb", "keep_original_size"],
                "output_format": "webp",
                "supports_transparency": True,
                "supports_animation": True,
                "supported_formats": [
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                ],
                "category": "universal",
            },
            "image_force_lossless": {
                "name": "通用图片强制无损压缩",
                "description": "支持所有常用格式的强制无损压缩，忽略大小限制",
                "parameters": [],
                "output_format": "webp",
                "supports_transparency": True,
                "supported_formats": [
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                ],
                "category": "universal",
            },
            "image_ultra": {
                "name": "通用图片超强压缩",
                "description": "支持所有常用格式的超强压缩，自动根据质量选择有损/无损",
                "parameters": ["max_size_kb", "quality", "keep_original_size"],
                "output_format": "webp",
                "supports_transparency": True,
                "supports_animation": True,
                "supported_formats": [
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                ],
                "category": "universal",
            },
            # 格式转换
            "webp": {
                "name": "WebP格式转换",
                "description": "转换为WebP格式，支持透明度和动画",
                "parameters": ["quality", "optimize", "method"],
                "output_format": "webp",
                "supports_transparency": True,
                "supports_animation": True,
                "supported_formats": [
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                ],
                "category": "format_conversion",
            },
            "avif": {
                "name": "AVIF格式转换",
                "description": "转换为AVIF格式，更好的压缩效果",
                "parameters": [],
                "output_format": "avif",
                "supports_transparency": True,
                "supports_animation": False,
                "supported_formats": [
                    ".png",
                    ".jpg",
                    ".jpeg",
                    ".bmp",
                    ".tiff",
                    ".tif",
                    ".gif",
                ],
                "category": "format_conversion",
            },
        },
        "supported_input_formats": [
            ".png",
            ".jpg",
            ".jpeg",
            ".bmp",
            ".tiff",
            ".tif",
            ".gif",
        ],
        "parameters": {
            "max_size_kb": {
                "description": "目标最大文件大小（KB）",
                "type": "integer",
                "default": 50,
                "range": "1-10000",
            },
            "quality": {
                "description": "压缩质量（WebP/AVIF）",
                "type": "integer",
                "default": 80,
                "range": "0-100",
            },
            "keep_original_size": {
                "description": "是否保持原始尺寸（不缩放）",
                "type": "boolean",
                "default": False,
            },
            "optimize": {
                "description": "是否启用优化",
                "type": "boolean",
                "default": True,
            },
            "method": {
                "description": "压缩方法（0-6，6为最强压缩）",
                "type": "integer",
                "default": 6,
                "range": "0-6",
            },
        },
    }
