#!/usr/bin/env python3
"""
Apply crop coordinates from curation.json and produce production-ready files.
Usage: python3 apply-crops.py <curation.json> [--quality 92] [--out-dir <path>]
"""
import json, sys, os, argparse
from pathlib import Path

try:
    from PIL import Image
except ImportError:
    print("PIL not found. Installing...")
    os.system("pip3 install pillow -q")
    from PIL import Image

# Section output aspect ratios (w, h)
SECTION_AR = {
    'hero':      (16, 5),
    'strip':     (21, 5),
    'grid':      (1,  1),
    'alongside': (4,  3),
}

def apply_crop(img: Image.Image, crop: dict, target_w: int, target_h: int) -> Image.Image:
    """Crop and scale to target dimensions using saved crop coordinates (percentages)."""
    nw, nh = img.size
    # Convert pct to pixels
    sx = int(nw * crop['x'] / 100)
    sy = int(nh * crop['y'] / 100)
    sw = int(nw * crop['w'] / 100)
    sh = int(nh * crop['h'] / 100)
    # Clamp
    sx = max(0, min(sx, nw-1)); sy = max(0, min(sy, nh-1))
    sw = max(1, min(sw, nw-sx)); sh = max(1, min(sh, nh-sy))
    
    cropped = img.crop((sx, sy, sx+sw, sy+sh))
    
    # Cover-scale to target
    scale = max(target_w/sw, target_h/sh)
    dw, dh = int(sw*scale), int(sh*scale)
    scaled = cropped.resize((dw, dh), Image.LANCZOS)
    
    # Center-crop to exact target
    ox = (dw - target_w) // 2
    oy = (dh - target_h) // 2
    return scaled.crop((ox, oy, ox+target_w, oy+target_h))

def cover_crop(img: Image.Image, target_w: int, target_h: int) -> Image.Image:
    """Smart center cover crop (no explicit crop box)."""
    nw, nh = img.size
    scale = max(target_w/nw, target_h/nh)
    dw, dh = int(nw*scale), int(nh*scale)
    scaled = img.resize((dw, dh), Image.LANCZOS)
    ox = (dw - target_w) // 2
    oy = (dh - target_h) // 2
    return scaled.crop((ox, oy, ox+target_w, oy+target_h))

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('curation', help='Path to revolut-curation.json')
    parser.add_argument('--quality', type=int, default=92)
    parser.add_argument('--out-dir', default=None, help='Output directory (default: assets/production/)')
    parser.add_argument('--width', type=int, default=1600, help='Base output width in px')
    args = parser.parse_args()

    with open(args.curation) as f:
        data = json.load(f)

    assets_dir = Path(__file__).parent.parent.parent / 'public/etoro-competition/revolut/assets'
    out_dir = Path(args.out_dir) if args.out_dir else assets_dir / 'production'
    out_dir.mkdir(parents=True, exist_ok=True)

    crops_map = data.get('crops', {})
    assignments = data.get('assignments', {})
    processed = []

    for section, files in assignments.items():
        if not files: continue
        ar = SECTION_AR.get(section)
        if not ar: continue
        tw, th = args.width, int(args.width * ar[1] / ar[0])

        for fname in files:
            src = assets_dir / fname
            if not src.exists():
                print(f"⚠  Missing: {fname}")
                continue

            img = Image.open(src).convert('RGB')
            crop = crops_map.get(fname)

            if crop and crop.get('w', 0) > 2 and crop.get('h', 0) > 2:
                result = apply_crop(img, crop, tw, th)
                crop_label = 'cropped'
            else:
                result = cover_crop(img, tw, th)
                crop_label = 'auto'

            stem = Path(fname).stem
            out_name = f"{stem}-{section}-{tw}w.jpg"
            out_path = out_dir / out_name
            result.save(out_path, 'JPEG', quality=args.quality, optimize=True)
            kb = out_path.stat().st_size // 1024
            processed.append(out_name)
            print(f"✓ {section:10s}  {fname:40s}  →  {out_name}  ({kb}KB, {crop_label})")

    print(f"\n✅ {len(processed)} files written to {out_dir}")
    
    # Write manifest
    manifest = {'section_files': {s: [f"{Path(f).stem}-{s}-{args.width}w.jpg" for f in files] for s,files in assignments.items() if files}}
    with open(out_dir / 'manifest.json', 'w') as f:
        json.dump(manifest, f, indent=2)
    print(f"📋 Manifest: {out_dir}/manifest.json")

if __name__ == '__main__':
    main()
