#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
JPG照片压缩脚本
自动压缩超过3MB的JPG格式照片到小于3MB
"""

import os
from PIL import Image
import argparse
from pathlib import Path

def compress_jpg_to_size(file_path, max_size_mb=1, quality=85, step=5):
    """
    压缩JPG图片到指定大小以下
    
    Args:
        file_path: 图片文件路径
        max_size_mb: 最大文件大小(MB)
        quality: 初始压缩质量(1-95)
        step: 每次降低质量的步长
    
    Returns:
        bool: 是否成功压缩
        str: 结果信息
    """
    try:
        # 获取文件大小
        original_size = os.path.getsize(file_path)
        original_size_mb = original_size / (1024 * 1024)
        
        print(f"原始文件: {os.path.basename(file_path)}")
        print(f"原始大小: {original_size_mb:.2f}MB")
        
        # 如果文件已经小于目标大小，直接返回
        if original_size_mb <= max_size_mb:
            return True, f"文件已小于{max_size_mb}MB，无需压缩"
        
        # 打开图片
        with Image.open(file_path) as img:
            # 确保是RGB模式
            if img.mode != 'RGB':
                img = img.convert('RGB')
            
            # 获取图片尺寸
            width, height = img.size
            print(f"图片尺寸: {width}x{height}")
            
            # 如果图片尺寸很大，先调整尺寸
            max_dimension = 4000  # 最大边长限制
            if width > max_dimension or height > max_dimension:
                if width > height:
                    new_width = max_dimension
                    new_height = int(height * max_dimension / width)
                else:
                    new_height = max_dimension
                    new_width = int(width * max_dimension / height)
                
                img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
                print(f"调整尺寸至: {new_width}x{new_height}")
            
            # 尝试不同质量等级进行压缩
            current_quality = quality
            
            while current_quality >= 20:  # 最低质量限制
                # 保存为临时文件来检查大小
                temp_output = f"{file_path}.temp.jpg"
                img.save(temp_output, format='JPEG', quality=current_quality, optimize=True)
                
                # 检查压缩后的大小
                compressed_size = os.path.getsize(temp_output)
                compressed_size_mb = compressed_size / (1024 * 1024)
                
                print(f"尝试质量{current_quality}%: {compressed_size_mb:.2f}MB")
                
                if compressed_size_mb <= max_size_mb:
                    # 压缩成功，替换原文件
                    os.replace(temp_output, file_path)
                    
                    compression_ratio = (original_size - compressed_size) / original_size * 100
                    return True, f"压缩成功！质量:{current_quality}%, 大小:{compressed_size_mb:.2f}MB, 压缩率:{compression_ratio:.1f}%"
                else:
                    # 删除临时文件，继续尝试更低质量
                    os.remove(temp_output)
                    current_quality -= step
            
            # 如果还是太大，尝试进一步调整尺寸
            print("质量压缩不足，尝试调整尺寸...")
            
            # 逐步减小尺寸
            scale_factor = 0.9
            current_quality = quality  # 重置质量
            
            while scale_factor >= 0.5:  # 最小尺寸限制
                new_width = int(width * scale_factor)
                new_height = int(height * scale_factor)
                
                resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
                
                temp_output = f"{file_path}.temp.jpg"
                resized_img.save(temp_output, format='JPEG', quality=current_quality, optimize=True)
                
                compressed_size = os.path.getsize(temp_output)
                compressed_size_mb = compressed_size / (1024 * 1024)
                
                print(f"尝试尺寸{new_width}x{new_height} + 质量{current_quality}%: {compressed_size_mb:.2f}MB")
                
                if compressed_size_mb <= max_size_mb:
                    os.replace(temp_output, file_path)
                    
                    compression_ratio = (original_size - compressed_size) / original_size * 100
                    return True, f"压缩成功！尺寸:{new_width}x{new_height}, 质量:{current_quality}%, 大小:{compressed_size_mb:.2f}MB, 压缩率:{compression_ratio:.1f}%"
                else:
                    os.remove(temp_output)
                    scale_factor -= 0.1
            
            return False, "无法压缩到目标大小，图片可能过于复杂"
            
    except Exception as e:
        return False, f"压缩失败: {str(e)}"

def compress_single_file(file_path, max_size_mb=1):
    """
    压缩单个文件
    """
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"文件不存在: {file_path}")
        return False
    
    # 检查文件扩展名
    if not file_path.lower().endswith(('.jpg', '.jpeg')):
        print(f"不是JPG格式文件: {file_path}")
        return False
    
    success, message = compress_jpg_to_size(file_path, max_size_mb)
    print(message)
    return success

def compress_directory(directory_path, max_size_mb=1, recursive=True):
    """
    压缩目录中的所有JPG文件
    """
    if not os.path.exists(directory_path):
        print(f"目录不存在: {directory_path}")
        return
    
    success_count = 0
    failed_count = 0
    skipped_count = 0
    
    # 获取所有JPG文件
    jpg_files = []
    if recursive:
        for root, dirs, files in os.walk(directory_path):
            for file in files:
                if file.lower().endswith(('.jpg', '.jpeg')):
                    jpg_files.append(os.path.join(root, file))
    else:
        for file in os.listdir(directory_path):
            if file.lower().endswith(('.jpg', '.jpeg')):
                full_path = os.path.join(directory_path, file)
                if os.path.isfile(full_path):
                    jpg_files.append(full_path)
    
    print(f"找到 {len(jpg_files)} 个JPG文件")
    print("-" * 50)
    
    # 处理每个文件
    for i, file_path in enumerate(jpg_files, 1):
        print(f"\\n[{i}/{len(jpg_files)}] 处理: {os.path.basename(file_path)}")
        
        # 检查文件大小
        file_size_mb = os.path.getsize(file_path) / (1024 * 1024)
        
        if file_size_mb <= max_size_mb:
            print(f"文件已小于{max_size_mb}MB，跳过")
            skipped_count += 1
            continue
        
        success, message = compress_jpg_to_size(file_path, max_size_mb)
        if success:
            success_count += 1
        else:
            failed_count += 1
            print(f"失败: {message}")
    
    # 打印统计结果
    print("\\n" + "=" * 50)
    print(f"处理完成！")
    print(f"成功: {success_count}")
    print(f"失败: {failed_count}")
    print(f"跳过: {skipped_count}")
    print(f"总计: {len(jpg_files)}")

def main():
    """
    主函数
    """
    parser = argparse.ArgumentParser(description='JPG照片压缩工具')
    parser.add_argument('path', help='文件或目录路径')
    parser.add_argument('-s', '--size', type=float, default=3, help='目标文件大小(MB)，默认3MB')
    parser.add_argument('-r', '--recursive', action='store_true', help='递归处理子目录')
    parser.add_argument('-q', '--quality', type=int, default=60, help='初始压缩质量(1-95)，默认85')
    
    args = parser.parse_args()
    
    if os.path.isfile(args.path):
        compress_single_file(args.path, args.size)
    elif os.path.isdir(args.path):
        compress_directory(args.path, args.size, args.recursive)
    else:
        print(f"路径不存在: {args.path}")

if __name__ == "__main__":
    # 如果没有命令行参数，使用交互模式
    if len(os.sys.argv) == 1:
        print("JPG照片压缩工具")
        print("=" * 30)
        
        path = input("请输入文件或目录路径: ").strip()
        if not path:
            print("未输入路径，退出程序")
            exit()
        
        if os.path.isfile(path):
            compress_single_file(path)
        elif os.path.isdir(path):
            recursive = input("是否递归处理子目录?(y/n): ").lower().strip() == 'y'
            compress_directory(path, recursive=recursive)
        else:
            print(f"路径不存在: {path}")
    else:
        main()