#!/usr/bin/env python3
import argparse
import os
import sys
from io import BytesIO

def main():
    parser = argparse.ArgumentParser(description="Convert and compress images to low-resolution monochrome PNG/WebP.")
    parser.add_argument("-i", "--input", required=True, help="Path to input image file")
    parser.add_argument("-o", "--output", required=True, help="Path to save output image file")
    parser.add_argument("-d", "--max-dim", type=int, default=256, help="Maximum dimension (width or height) of output image")
    parser.add_argument("-t", "--threshold", type=int, default=128, help="Binarization threshold (0-255) for black & white conversion")
    parser.add_argument("-m", "--mode", choices=["1", "L"], default="1", help="Output color mode: '1' (binary black/white), 'L' (grayscale)")
    
    args = parser.parse_args()

    if not os.path.exists(args.input):
        print(f"Error: Input file {args.input} does not exist.", file=sys.stderr)
        sys.exit(1)

    try:
        from PIL import Image
    except ImportError:
        print("Error: Pillow library is required. Install with: pip install Pillow", file=sys.stderr)
        sys.exit(1)

    try:
        with Image.open(args.input) as img:
            # 1. Ensure image is loaded
            img.load()
            orig_size = img.size
            orig_bytes = os.path.getsize(args.input)

            # 2. Resize maintaining aspect ratio
            w, h = img.size
            scale = min(1.0, float(args.max_dim) / float(max(w, h)))
            target_size = (max(1, int(round(w * scale))), max(1, int(round(h * scale))))
            resized = img.resize(target_size, Image.Resampling.LANCZOS)

            # 3. Convert mode
            if args.mode == "1":
                # Convert to grayscale first, then apply threshold
                gray = resized.convert("L")
                final_img = gray.point(lambda x: 0 if x < args.threshold else 255, "1")
            else:
                final_img = resized.convert("L")

            # 4. Save with optimal compression
            out_ext = os.path.splitext(args.output)[1].lower()
            if not out_ext:
                out_ext = ".png"
                args.output += ".png"

            # Ensure directory exists
            out_dir = os.path.dirname(args.output)
            if out_dir:
                os.makedirs(out_dir, exist_ok=True)

            if out_ext == ".webp":
                # WebP doesn't natively support 1-bit mode "1" inside Pillow directly without converting to L/RGB first.
                # So we convert to "L" for saving as WebP
                save_img = final_img.convert("L") if final_img.mode == "1" else final_img
                save_img.save(args.output, format="WEBP", lossless=True, quality=100)
            else:
                # Save as PNG with optimization
                final_img.save(args.output, format="PNG", optimize=True)

            compressed_bytes = os.path.getsize(args.output)
            savings = (1 - (compressed_bytes / orig_bytes)) * 100 if orig_bytes > 0 else 0

            print(f"Success: Image compressed and saved to {args.output}")
            print(f"  Dimensions: {orig_size[0]}x{orig_size[1]} -> {final_img.size[0]}x{final_img.size[1]}")
            print(f"  File Size : {orig_bytes / 1024:.2f} KB -> {compressed_bytes / 1024:.2f} KB ({savings:.1f}% reduction)")

    except Exception as e:
        print(f"Error processing image: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
