#!/usr/bin/env python3
"""
PowerPoint Fit to Page Script
Fits all content on a slide to ensure it fits on one page
"""

import os
import sys
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.shapes import MSO_SHAPE_TYPE

def get_slide_bounds(slide):
    """Get the bounding box of all shapes on a slide"""
    if not slide.shapes:
        return None
    
    min_left = float('inf')
    min_top = float('inf')
    max_right = float('-inf')
    max_bottom = float('-inf')
    
    for shape in slide.shapes:
        try:
            left = shape.left
            top = shape.top
            right = left + shape.width
            bottom = top + shape.height
            
            min_left = min(min_left, left)
            min_top = min(min_top, top)
            max_right = max(max_right, right)
            max_bottom = max(max_bottom, bottom)
        except:
            continue
    
    if min_left == float('inf'):
        return None
    
    return {
        'left': min_left,
        'top': min_top,
        'width': max_right - min_left,
        'height': max_bottom - min_top
    }

def fit_slide_to_page(prs, slide_num=0, margin_inches=0.5):
    """Fit all content on a slide to the page with margins"""
    slide = prs.slides[slide_num]
    
    # Get slide dimensions (in EMUs - English Metric Units)
    slide_width = prs.slide_width
    slide_height = prs.slide_height
    
    # Convert margin to EMUs (1 inch = 914400 EMUs)
    margin = int(margin_inches * 914400)
    
    # Available area for content
    available_width = slide_width - (2 * margin)
    available_height = slide_height - (2 * margin)
    
    # Get current content bounds
    content_bounds = get_slide_bounds(slide)
    
    if not content_bounds:
        print("No shapes found on slide")
        return False
    
    print(f"Slide dimensions: {slide_width/914400:.2f}\" x {slide_height/914400:.2f}\"")
    print(f"Content bounds: {content_bounds['width']/914400:.2f}\" x {content_bounds['height']/914400:.2f}\"")
    print(f"Content position: ({content_bounds['left']/914400:.2f}\", {content_bounds['top']/914400:.2f}\")")
    
    # Calculate scale factors
    scale_x = available_width / content_bounds['width']
    scale_y = available_height / content_bounds['height']
    scale = min(scale_x, scale_y, 1.0)  # Don't scale up, only down
    
    print(f"Scale factor: {scale:.3f}")
    
    if scale >= 1.0:
        print("Content already fits on page, just centering...")
        scale = 1.0
    
    # Calculate new position to center the scaled content
    scaled_width = content_bounds['width'] * scale
    scaled_height = content_bounds['height'] * scale
    
    new_left = margin + (available_width - scaled_width) / 2
    new_top = margin + (available_height - scaled_height) / 2
    
    # Calculate offset
    offset_x = new_left - (content_bounds['left'] * scale)
    offset_y = new_top - (content_bounds['top'] * scale)
    
    print(f"Moving content to: ({new_left/914400:.2f}\", {new_top/914400:.2f}\")")
    
    # Apply transformation to all shapes
    moved_count = 0
    scaled_count = 0
    
    for shape in slide.shapes:
        try:
            # Calculate new position
            old_left = shape.left
            old_top = shape.top
            
            new_shape_left = (old_left * scale) + offset_x
            new_shape_top = (old_top * scale) + offset_y
            
            # Move shape
            shape.left = int(new_shape_left)
            shape.top = int(new_shape_top)
            
            # Scale shape
            shape.width = int(shape.width * scale)
            shape.height = int(shape.height * scale)
            
            # Scale font sizes if it's a text shape
            if hasattr(shape, 'text_frame'):
                for paragraph in shape.text_frame.paragraphs:
                    for run in paragraph.runs:
                        if run.font.size:
                            try:
                                new_size = int(run.font.size * scale)
                                if new_size > 0:
                                    run.font.size = Pt(new_size)
                            except:
                                pass
            
            moved_count += 1
            scaled_count += 1
            
        except Exception as e:
            print(f"  Warning: Could not transform shape '{shape.name if hasattr(shape, 'name') else 'unknown'}': {e}")
            continue
    
    print(f"\nTransformed {moved_count} shapes")
    return True

def fit_powerpoint_to_page(pptx_path, output_path=None, margin_inches=0.5):
    """Main function to fit PowerPoint to one page"""
    if not os.path.exists(pptx_path):
        print(f"Error: File '{pptx_path}' not found!")
        return False
    
    try:
        # Load the presentation
        print(f"Loading presentation: {pptx_path}")
        prs = Presentation(pptx_path)
        
        total_slides = len(prs.slides)
        print(f"Processing {total_slides} slide(s)...\n")
        
        # Process each slide
        for slide_num in range(total_slides):
            print(f"=== Slide {slide_num + 1} ===")
            fit_slide_to_page(prs, slide_num, margin_inches)
            print()
        
        # Save the presentation
        if output_path is None:
            base_name = os.path.splitext(pptx_path)[0]
            output_path = f"{base_name}_fitted.pptx"
        
        print(f"Saving fitted presentation to: {output_path}")
        prs.save(output_path)
        
        print(f"\n✅ Fit to page completed successfully!")
        print(f"Fitted presentation saved as: {output_path}")
        
        return True
        
    except Exception as e:
        print(f"Error processing presentation: {str(e)}")
        import traceback
        traceback.print_exc()
        return False

def main():
    """Main function"""
    if len(sys.argv) < 2:
        print("Usage: python fit_powerpoint_to_page.py <input_file.pptx> [output_file.pptx] [margin_inches]")
        print("\nExample:")
        print("python fit_powerpoint_to_page.py El_Paraiso_Org_Chart_v3_cleaned.pptx")
        print("python fit_powerpoint_to_page.py input.pptx output.pptx 0.25")
        return
    
    input_file = sys.argv[1]
    output_file = sys.argv[2] if len(sys.argv) > 2 else None
    margin = float(sys.argv[3]) if len(sys.argv) > 3 else 0.5
    
    # Install required package if not available
    try:
        from pptx import Presentation
    except ImportError:
        print("Installing required package: python-pptx")
        os.system("pip install python-pptx")
        try:
            from pptx import Presentation
        except ImportError:
            print("Error: Could not install python-pptx. Please install it manually:")
            print("pip install python-pptx")
            return
    
    success = fit_powerpoint_to_page(input_file, output_file, margin)
    
    if not success:
        print("\n❌ Fit to page failed!")

if __name__ == "__main__":
    main()


