import io
import zipfile
import boto3
import fitz
import requests
from PIL import Image, ImageOps, UnidentifiedImageError, ImageFile
from botocore.exceptions import NoCredentialsError, ClientError
from pdf2image import convert_from_bytes
import math
import subprocess
import qrcode
from io import BytesIO
import mysql.connector
from datetime import datetime
import argparse
import os
import sys
Image.MAX_IMAGE_PIXELS = None
import PIL.Image
PIL.Image.MAX_IMAGE_PIXELS = None

ImageFile.MAXBLOCK = 2**10
db_config = {
    "host": "localhost",
    "user": "upload15_uploadtransfers01",
    "password": "2!oum10ZDS",
    "database": "upload15_uploadtransfers01"
}


def resize_image(image, width, height):
    if image.mode == 'P':
        if 'transparency' in image.info:
            image = image.convert('RGBA')
        else:
            image = image.convert('RGB')
    if image.width != width or image.height != height:
        return image.resize((width, height), Image.LANCZOS)
    return image

def resize_image_by_width(image, target_width):
    # Calculate the proportional height
    aspect_ratio = image.height / image.width
    target_height = int(target_width * aspect_ratio)


    if image.width != target_width:
        return image.resize((target_width, target_height), Image.LANCZOS)
    return image

def resize_pdf(pdf_bytes, width_inch, height_inch):
    dpi = 300
    pdf_document = fitz.open(stream=pdf_bytes, filetype="pdf")
    png_images = []

    for page_num in range(len(pdf_document)):
        page = pdf_document.load_page(page_num)
        matrix = fitz.Matrix(dpi / 72, dpi / 72)  
        pix = page.get_pixmap(matrix=matrix, alpha=True)
        img_bytes = pix.tobytes(output="png")

        img = Image.open(BytesIO(img_bytes))
        original_width, original_height = img.size

        img = img.convert("RGBA")
        data = img.getdata()

        min_x, min_y, max_x, max_y = original_width, original_height, 0, 0
        for y in range(original_height):
            for x in range(original_width):
                r, g, b, a = img.getpixel((x, y))
                if a != 0:  
                    min_x = min(min_x, x)
                    min_y = min(min_y, y)
                    max_x = max(max_x, x)
                    max_y = max(max_y, y)

        img_cropped = img.crop((min_x, min_y, max_x + 1, max_y + 1))

        margin_x = int((max_x - min_x + 1) * 0.001)
        margin_y = int((max_y - min_y + 1) * 0.001)

        width_pixels = int(width_inch * dpi)
        height_pixels = int(height_inch * dpi)

        img_resized = img_cropped.resize((width_pixels, height_pixels), Image.LANCZOS)

        img_io = BytesIO()
        img_resized.save(img_io, format="PNG", dpi=(dpi, dpi))
        img_io.seek(0)

        png_images.append(img_io.read())

    return png_images


def resize_pdf_New_one(pdf_bytes, width_inch, height_inch):
    dpi = 300
    width_pixels = int(width_inch * dpi)
    height_pixels = int(height_inch * dpi)
    png_images = []

    # Convert PDF to images
    images = convert_from_bytes(pdf_bytes, dpi=dpi)

    # Use only the first page
    img = images[0].convert("RGBA")
    original_width, original_height = img.size

    # Crop non-transparent region
    min_x, min_y, max_x, max_y = original_width, original_height, 0, 0
    for y in range(original_height):
        for x in range(original_width):
            _, _, _, a = img.getpixel((x, y))
            if a != 0:
                min_x = min(min_x, x)
                min_y = min(min_y, y)
                max_x = max(max_x, x)
                max_y = max(max_y, y)

    # Add small margin (optional, currently 0.1%)
    margin_x = int((max_x - min_x + 1) * 0.001)
    margin_y = int((max_y - min_y + 1) * 0.001)

    cropped_box = (
        max(0, min_x - margin_x),
        max(0, min_y - margin_y),
        min(original_width, max_x + 1 + margin_x),
        min(original_height, max_y + 1 + margin_y),
    )
    img_cropped = img.crop(cropped_box)

    # Resize to target dimensions
    img_resized = img_cropped.resize((width_pixels, height_pixels), Image.LANCZOS)

    # Save to PNG in memory
    img_io = BytesIO()
    img_resized.save(img_io, format="PNG", dpi=(dpi, dpi))
    img_io.seek(0)

    png_images.append(img_io.read())
    return png_images


DPI = 300  
def inches_to_pixels(inches):
    return int(inches * DPI)

def create_image_grid(image_bytes, new_width_inch, new_height_inch, num_images=30, limitwidth=22.5):
    margin_inch = 0.25
    output_width_inch = limitwidth

    image_width_px = inches_to_pixels(new_width_inch)
    image_height_px = inches_to_pixels(new_height_inch)
    margin_px = inches_to_pixels(margin_inch)
    output_width_px = inches_to_pixels(output_width_inch)
    tempo = 0

    if image_height_px < image_width_px:
        tempo = image_height_px
        image_height_px = image_width_px
        image_width_px = tempo

    images_per_row = max((output_width_px + margin_px) // (image_width_px + margin_px), 1)
    images_per_row = min(images_per_row, num_images)
    actual_output_width_px = images_per_row * image_width_px + (images_per_row - 1) * margin_px
    output_width_px = min(output_width_px, actual_output_width_px)

    num_rows = math.ceil(num_images / images_per_row)
    total_height_px = num_rows * image_height_px + (num_rows - 1) * margin_px

    output_image = Image.new('RGBA', (output_width_px, total_height_px), (255, 255, 255, 0))

    original_image = Image.open(BytesIO(image_bytes)).convert("RGBA")
    if tempo > 0:
        original_image = original_image.rotate(90, expand=True)
    
    original_image = original_image.resize((image_width_px, image_height_px))

    for row in range(num_rows):
        images_in_this_row = images_per_row if (row + 1) * images_per_row <= num_images else num_images % images_per_row or images_per_row

        for col in range(images_in_this_row):
            idx = row * images_per_row + col
            if idx >= num_images:
                break

            x = col * (image_width_px + margin_px)  
            y = row * (image_height_px + margin_px)  

            output_image.paste(original_image, (x, y), original_image)

    return output_image

def add_qr_to_image_jpg(image, qr_content):
    qr = qrcode.QRCode(
        version=1,
        box_size=10,
        border=4
    )
    image = Image.open(BytesIO(image))
    qr.add_data(qr_content)
    qr.make(fit=True)
    qr_img = qr.make_image(fill_color="black", back_color="white").convert('RGBA')

    qr_size = max(100, image.width // 6)
    qr_img = qr_img.resize((qr_size, qr_size))

    # Add white margin above QR code
    margin = 20  # You can change this
    qr_with_margin = Image.new('RGBA', (qr_img.width, qr_img.height + margin), (255, 255, 255, 255))  # solid white
    qr_with_margin.paste(qr_img, (0, margin), mask=qr_img)

    # Create new image with enough height
    new_height = image.height + qr_with_margin.height
    new_image = Image.new("RGBA", (image.width, new_height), (255, 255, 255, 255))  # also white background
    new_image.paste(image, (0, 0))
    qr_x = (image.width - qr_with_margin.width) // 2
    new_image.paste(qr_with_margin, (qr_x, image.height), mask=qr_with_margin)

    output = BytesIO()
    new_image.convert("RGB").save(output, format="JPEG")
    output.seek(0)
    return output
def round_half_up(x):
    return math.floor(x + 0.5)
def add_qr_code_to_image_test_old(image_bytes, qr_content, image_format='PNG', product_id=-1, dpinfo=False):

    original_image = Image.open(BytesIO(image_bytes))
    dpi_info = original_image.info.get("dpi")

    if dpi_info and dpi_info[0] and dpinfo is True:
        dpi_value = round_half_up(dpi_info[0])
    else:
        dpi_value = 300



    original_width, original_height = original_image.size
    qr_size = 300 
    if original_width < 300:
        qr_size = original_width


    if product_id == 31981:
        padded_qr_height = qr_size  
    else:
        padded_qr_height = 2 * qr_size  
    if product_id == 31981:
        margin_height = padded_qr_height + 50
    else:
        margin_height = padded_qr_height + 20  

    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    qr.add_data(qr_content)
    qr.make(fit=True)

    qr_image = qr.make_image(fill_color="black", back_color="white")
    qr_image = qr_image.resize((qr_size, qr_size), Image.Resampling.LANCZOS)

    if product_id == 31981:
        padded_qr_image = Image.new('RGBA', (qr_size, padded_qr_height), (255, 255, 255, 255))
    else:
        padded_qr_image = Image.new('RGBA', (qr_size, padded_qr_height), (0, 0, 0, 0))

    qr_rgba = Image.new('RGBA', qr_image.size, (255, 255, 255, 255))
    qr_rgba.paste(qr_image, (0, 0))

    qr_data = qr_rgba.getdata()
    new_qr_data = [(255, 255, 255, 0) if r > 200 and g > 200 and b > 200 else (r, g, b, a)
                   for r, g, b, a in qr_data]
    qr_rgba.putdata(new_qr_data)

    qr_y_in_padded = padded_qr_height - qr_size
    padded_qr_image.paste(qr_rgba, (0, qr_y_in_padded), qr_rgba)

    used_text = qr_content
    if '.' in qr_content:
        used_text = qr_content.split('.')[0]
    target_width = 400 if original_width < 300 else qr_size
    result = subprocess.run(
        ['python3', '/home/upload15/api.uploadtransfers.com/createimage.py', used_text, str(target_width)],
        capture_output=True,
        text=False
    )

    if result.returncode != 0:
        print("Subprocess error:", result.stderr.decode())
        text_img = None

    else:

        try:
            text_img = Image.open(BytesIO(result.stdout))
            if text_img.mode != 'RGBA':
                text_img = text_img.convert('RGBA')
        except UnidentifiedImageError:
            print("Failed to open image from subprocess output")
            text_img = None

    text_img_height = text_img.height if text_img else 0
    total_new_height = original_height + margin_height + text_img_height + 10  # +10 px padding below QR

    if original_image.mode in ('RGBA', 'LA'):
        if product_id == 31981:
            new_image = Image.new('RGBA', (original_width, total_new_height), (255, 255, 255, 255))
        else:
            new_image = Image.new('RGBA', (original_width, total_new_height), (0, 0, 0, 0))
        new_image.paste(original_image, (0, 0))
    else:
        if product_id == 31981:
            original_image = original_image.convert('RGB')
            new_image = Image.new('RGB', (original_width, total_new_height), (255, 255, 255))
            new_image.paste(original_image, (0, 0))
        else:
            background_color = (255, 255, 255) if original_image.mode == 'RGB' else 255
            new_image = Image.new(original_image.mode, (original_width, total_new_height), background_color)
            new_image.paste(original_image, (0, 0))

    qr_x = (original_width - qr_size) // 2
    qr_y = original_height + (margin_height - padded_qr_height) // 2
    if new_image.mode == 'RGBA':
        new_image.paste(padded_qr_image, (qr_x, qr_y), padded_qr_image)
    else:
        rgb_qr = Image.new('RGB', padded_qr_image.size, (255, 255, 255))
        rgb_qr.paste(padded_qr_image, (0, 0), padded_qr_image)
        new_image.paste(rgb_qr, (qr_x, qr_y))

    if text_img:
        text_x = (original_width - text_img.width) // 2
        text_y = qr_y + padded_qr_height + 10  # 10 pixels padding below QR
        new_image.paste(text_img, (text_x, text_y), text_img)


    img_io = BytesIO()
    new_image.save(img_io, format=image_format, dpi=(dpi_value, dpi_value))
    img_io.seek(0)
    return img_io


def add_qr_code_to_image_test(image_bytes, qr_content, image_format='PNG', product_id=-1, dpinfo=False, dropshipping=0):
    from PIL import Image
    from io import BytesIO
    import qrcode
    import subprocess
    import requests

    original_image = Image.open(BytesIO(image_bytes))
    dpi_info = original_image.info.get("dpi")

    if dpi_info and dpi_info[0] and dpinfo is True:
        dpi_value = round_half_up(dpi_info[0])
    else:
        dpi_value = 300

    original_width, original_height = original_image.size
    qr_size = 300 
    if original_width < 300:
        qr_size = original_width

    if product_id == 31981:
        padded_qr_height = qr_size  
    else:
        padded_qr_height = 2 * qr_size  
    if product_id == 31981:
        margin_height = padded_qr_height + 50
    else:
        margin_height = padded_qr_height + 20  

    # Determine if we should use transparent background
    use_transparent = (image_format.upper() == 'PNG' and product_id != 31981)

    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    qr.add_data(qr_content)
    qr.make(fit=True)

    # Create QR code with transparent background for PNG format
    if use_transparent:
        qr_image = qr.make_image(fill_color="black", back_color="transparent")
    else:
        qr_image = qr.make_image(fill_color="black", back_color="white")
    
    qr_image = qr_image.resize((qr_size, qr_size), Image.Resampling.LANCZOS)

    # Create padded QR image with appropriate background
    if product_id == 31981:
        padded_qr_image = Image.new('RGBA', (qr_size, padded_qr_height), (255, 255, 255, 255))
    else:
        if use_transparent:
            padded_qr_image = Image.new('RGBA', (qr_size, padded_qr_height), (0, 0, 0, 0))
        else:
            padded_qr_image = Image.new('RGBA', (qr_size, padded_qr_height), (0, 0, 0, 0))

    # Convert QR to RGBA with appropriate background
    if use_transparent:
        qr_rgba = Image.new('RGBA', qr_image.size, (0, 0, 0, 0))
    else:
        qr_rgba = Image.new('RGBA', qr_image.size, (255, 255, 255, 255))
    
    qr_rgba.paste(qr_image, (0, 0))

    # Make white pixels transparent for the QR code
    qr_data = qr_rgba.getdata()
    new_qr_data = [(255, 255, 255, 0) if r > 200 and g > 200 and b > 200 else (r, g, b, a)
                   for r, g, b, a in qr_data]
    qr_rgba.putdata(new_qr_data)

    qr_y_in_padded = padded_qr_height - qr_size
    padded_qr_image.paste(qr_rgba, (0, qr_y_in_padded), qr_rgba)

    # Fetch and process logo
    logo_img = None
    logo_height = 0
    logo_padding = 10  # padding between text and logo
    
    try:
        if dropshipping != 1:
            logo_url = "https://uploadtransfers.com/wp-content/uploads/2021/03/main-logo-e1648138042828.png"
            response = requests.get(logo_url, timeout=5)
            
            if response.status_code == 200:
                logo_img = Image.open(BytesIO(response.content))
                if logo_img.mode != 'RGBA':
                    logo_img = logo_img.convert('RGBA')
                
                # Resize logo to fit nicely (max width = qr_size or 80% of original_width)
                max_logo_width = min(qr_size, int(original_width * 0.8))
                aspect_ratio = logo_img.height / logo_img.width
                new_logo_width = max_logo_width
                new_logo_height = int(new_logo_width * aspect_ratio)
                logo_img = logo_img.resize((new_logo_width, new_logo_height), Image.Resampling.LANCZOS)
                logo_height = new_logo_height
    except Exception as e:
        print(f"Failed to fetch/process logo: {e}")
        logo_img = None
        logo_height = 0

    used_text = qr_content
    if '.' in qr_content:
        used_text = qr_content.split('.')[0]
    target_width = 400 if original_width < 300 else qr_size
    result = subprocess.run(
        ['python3', '/home/upload15/api.uploadtransfers.com/createimage.py', used_text, str(target_width)],
        capture_output=True,
        text=False
    )

    if result.returncode != 0:
        print("Subprocess error:", result.stderr.decode())
        text_img = None
    else:
        try:
            text_img = Image.open(BytesIO(result.stdout))
            if text_img.mode != 'RGBA':
                text_img = text_img.convert('RGBA')
        except:
            print("Failed to open image from subprocess output")
            text_img = None

    text_img_height = text_img.height if text_img else 0
    
    # Add logo height to total height calculation
    if dropshipping != 1:
        total_new_height = original_height + margin_height + text_img_height + 10 + logo_height + (logo_padding if logo_img else 0)
    else:
        total_new_height = original_height + margin_height + text_img_height + 10

    # Create new image with appropriate background
    if original_image.mode in ('RGBA', 'LA') or use_transparent:
        if product_id == 31981:
            new_image = Image.new('RGBA', (original_width, total_new_height), (255, 255, 255, 255))
        else:
            if use_transparent:
                # Transparent background for PNG format
                new_image = Image.new('RGBA', (original_width, total_new_height), (0, 0, 0, 0))
            else:
                new_image = Image.new('RGBA', (original_width, total_new_height), (0, 0, 0, 0))
        
        # Convert original image to RGBA if needed for PNG format
        if use_transparent and original_image.mode != 'RGBA':
            original_image = original_image.convert('RGBA')
        
        new_image.paste(original_image, (0, 0))
    else:
        if product_id == 31981:
            original_image = original_image.convert('RGB')
            new_image = Image.new('RGB', (original_width, total_new_height), (255, 255, 255))
            new_image.paste(original_image, (0, 0))
        else:
            background_color = (255, 255, 255) if original_image.mode == 'RGB' else 255
            new_image = Image.new(original_image.mode, (original_width, total_new_height), background_color)
            new_image.paste(original_image, (0, 0))

    qr_x = (original_width - qr_size) // 2
    qr_y = original_height + (margin_height - padded_qr_height) // 2
    
    if new_image.mode == 'RGBA':
        new_image.paste(padded_qr_image, (qr_x, qr_y), padded_qr_image)
    else:
        rgb_qr = Image.new('RGB', padded_qr_image.size, (255, 255, 255))
        rgb_qr.paste(padded_qr_image, (0, 0), padded_qr_image)
        new_image.paste(rgb_qr, (qr_x, qr_y))

    # Paste text under QR code
    current_y = qr_y + padded_qr_height + 10
    if text_img:
        text_x = (original_width - text_img.width) // 2
        text_y = current_y
        new_image.paste(text_img, (text_x, text_y), text_img)
        current_y = text_y + text_img_height + logo_padding

    # Paste logo under text
    if logo_img and dropshipping != 1:
        logo_x = (original_width - logo_img.width) // 2
        logo_y = current_y
        new_image.paste(logo_img, (logo_x, logo_y), logo_img)

    img_io = BytesIO()
    new_image.save(img_io, format=image_format, dpi=(dpi_value, dpi_value))
    img_io.seek(0)
    return img_io

def create_image_grid_zipping(image_bytes, new_width_inch, new_height_inch, num_images=30, limitwidth=22.5):
    margin_inch = 0.25
    output_width_inch = limitwidth

    image_width_px = inches_to_pixels(new_width_inch)
    image_height_px = inches_to_pixels(new_height_inch)
    margin_px = inches_to_pixels(margin_inch)
    output_width_px = inches_to_pixels(output_width_inch)
    tempo = 0

    if image_height_px < image_width_px:
        tempo = image_height_px
        image_height_px = image_width_px
        image_width_px = tempo

    images_per_row = max((output_width_px + margin_px) // (image_width_px + margin_px), 1)
    images_per_row = min(images_per_row, num_images)
    actual_output_width_px = images_per_row * image_width_px + (images_per_row - 1) * margin_px
    output_width_px = min(output_width_px, actual_output_width_px)

    num_rows = math.ceil(num_images / images_per_row)
    total_height_px = num_rows * image_height_px + (num_rows - 1) * margin_px

    output_image = Image.new('RGBA', (output_width_px, total_height_px), (255, 255, 255, 0))

    original_image = Image.open(BytesIO(image_bytes)).convert("RGBA")
    if tempo > 0:
        original_image = original_image.rotate(90, expand=True)
    
    original_image = original_image.resize((image_width_px, image_height_px))

    for row in range(num_rows):
        images_in_this_row = images_per_row if (row + 1) * images_per_row <= num_images else num_images % images_per_row or images_per_row

        for col in range(images_in_this_row):
            idx = row * images_per_row + col
            if idx >= num_images:
                break

            x = col * (image_width_px + margin_px)  
            y = row * (image_height_px + margin_px)  

            output_image.paste(original_image, (x, y), original_image)

    return output_image, num_rows, image_height_px, margin_px
def split_image_by_max_height(image, num_rows, image_height_px, margin_px, max_height_inch):
    max_height_px = inches_to_pixels(max_height_inch)
    parts = []
    current_y = 0
    start_row = 0

    while start_row < num_rows:
        rows_height = 0
        end_row = start_row
        
        while end_row < num_rows:
            next_row_height = image_height_px
            if end_row > start_row:  
                next_row_height += margin_px  
            
            if rows_height + next_row_height > max_height_px and end_row > start_row:
                break
            
            rows_height += next_row_height
            end_row += 1
        
        if end_row == start_row:
            end_row = start_row + 1
            rows_height = image_height_px
        
        part_height = (end_row - start_row) * image_height_px + max(0, (end_row - start_row - 1)) * margin_px
        
        part_img = image.crop((0, current_y, image.width, current_y + part_height))
        parts.append(part_img)
        
        current_y += part_height
        if end_row < num_rows: 
            current_y += margin_px
        
        start_row = end_row

    return parts
# ==============================
# S3 Upload Function
# ==============================
def upload_to_s3(file_bytes, s3_key, s3_bucket, content_type,
                 aws_access_key=None, aws_secret_key=None, aws_region="us-east-1"):
    """Upload file bytes to S3 and return the URL."""
    try:
        session = boto3.session.Session(
            aws_access_key_id=aws_access_key or os.getenv("AWS_ACCESS_KEY_ID"),
            aws_secret_access_key=aws_secret_key or os.getenv("AWS_SECRET_ACCESS_KEY"),
            region_name=aws_region or os.getenv("AWS_DEFAULT_REGION", "us-east-1"),
        )
        s3_client = session.client("s3")

        s3_client.put_object(
            Bucket=s3_bucket,
            Key=s3_key,
            Body=file_bytes,
            ContentType=content_type,
        )

        s3_url = f"https://{s3_bucket}.s3.{aws_region}.amazonaws.com/{s3_key}"
        print(f"[DEBUG] Uploaded to S3: {s3_url}")
        return s3_url
    except Exception as e:
        print(f"[ERROR] Failed to upload to S3: {e}")
        raise


# ==============================
# CLI Worker Function (Rewritten Flask Logic)
# ==============================
def process_file(image_url, width_inch, height_inch, quantity, limitwidth, dropshipping, order_id, product_id, s3_folder, s3_bucket, aws_access_key=None, aws_secret_key=None, aws_region="us-east-1"):    
    print(f"[DEBUG] Starting process_file with parameters:")
    print(f"[DEBUG] - image_url: {image_url}")
    print(f"[DEBUG] - width_inch: {width_inch}, height_inch: {height_inch}")
    print(f"[DEBUG] - quantity: {quantity}, limitwidth: {limitwidth}")
    print(f"[DEBUG] - order_id: {order_id}, product_id: {product_id}")
    print(f"[DEBUG] - s3_bucket: {s3_bucket}, s3_folder: {s3_folder}")
    print(f"[DEBUG] - aws_region: {aws_region}")
    
    excluded = [31624,31618,12596,12569,9942,9945,12221,31981,42963]
    exclude_qr_code = [175033, 31624, 31618, 12596, 12569, 54551,167282]
    splitheight = 400
    if int(product_id) == 31981:
        splitheight = 200
    
    print(f"[DEBUG] Configuration - excluded products: {excluded}")
    print(f"[DEBUG] Configuration - exclude_qr_code products: {exclude_qr_code}")
    print(f"[DEBUG] Configuration - splitheight: {splitheight}")

    if not image_url:
        print("[ERROR] Missing required parameter: image_url")
        raise ValueError("Missing required parameter: image_url")
    if not order_id:
        print("[ERROR] Missing required parameter: order_id")
        raise ValueError("Missing required parameter: order_id")

    # Download file
    print(f"[DEBUG] Downloading file from: {image_url}")
    response = requests.get(image_url, stream=True)
    print(f"[DEBUG] Download response status: {response.status_code}")
    
    if response.status_code != 200:
        print(f"[ERROR] Failed to download file: {image_url}, status: {response.status_code}")
        raise ValueError(f"Failed to download file: {image_url}")

    file_bytes = response.content
    content_type = response.headers.get('Content-Type', '').lower()
    file_extension = content_type.split('/')[-1].split(';')[0]
    
    print(f"[DEBUG] File downloaded - size: {len(file_bytes)} bytes")
    print(f"[DEBUG] Content-Type: {content_type}")
    print(f"[DEBUG] File extension: {file_extension}")

    # Convert inch to pixels
    if width_inch and height_inch:
        try:
            width = int(float(width_inch) * 300)
            height = int(float(height_inch) * 300)
            print(f"[DEBUG] Converted dimensions - width: {width}px, height: {height}px")
        except ValueError as e:
            print(f"[WARNING] Failed to convert dimensions: {e}")
            width_inch, height_inch = None, None
            width, height = None, None
    else:
        width, height = None, None
        print("[DEBUG] No dimensions provided, using original size")

    if quantity:
        try:
            quantity = int(quantity)
            print(f"[DEBUG] Quantity converted to: {quantity}")
        except ValueError as e:
            print(f"[WARNING] Failed to convert quantity: {e}")
            quantity = None
    if limitwidth:
        try:
            limitwidth = float(limitwidth)
            print(f"[DEBUG] Limitwidth converted to: {limitwidth}")
        except ValueError as e:
            print(f"[WARNING] Failed to convert limitwidth: {e}")
            limitwidth = None

    # =============================
    # Main Branches
    # =============================
    print(f"[DEBUG] Determining processing branch...")
    print(f"[DEBUG] - Has dimensions: {width_inch and height_inch}")
    print(f"[DEBUG] - Is image: {'image' in content_type}")
    print(f"[DEBUG] - Is PDF: {'pdf' in content_type}")

    # ---- Images with width & height ----
    if width_inch and height_inch and 'image' in content_type:
        print("[DEBUG] Branch: Images with width & height")
        image = Image.open(io.BytesIO(file_bytes))
        print(f"[DEBUG] Original image - format: {image.format}, size: {image.size}, mode: {image.mode}")
        
        jpeg_format = False
        if image.format in ['JPEG', 'JPG', 'MPO']:
            print("[DEBUG] Converting JPEG to PNG for transparency support")
            jpeg_format = True
            img_io = io.BytesIO()
            image = image.convert("RGBA")
            image.save(img_io, format='PNG', dpi=(300, 300))
            img_io.seek(0)
            image = Image.open(img_io)

        print(f"[DEBUG] Resizing image from {image.size} to {width}x{height}")
        resized_image = resize_image(image, width, height)
        img_io = io.BytesIO()
        resized_image.save(img_io, format=image.format, dpi=(300, 300))
        img_io.seek(0)
        final_image_bytes = img_io.read()
        print(f"[DEBUG] Resized image saved, size: {len(final_image_bytes)} bytes")

        # --- Quantity → Grid ---
        if quantity:
            print(f"[DEBUG] Creating grid with {quantity} images")
            grid_image, num_rows, row_height, margin_px = create_image_grid_zipping(
                final_image_bytes, float(width_inch), float(height_inch), quantity, limitwidth
            )
            print(f"[DEBUG] Grid created - size: {grid_image.size}, rows: {num_rows}")
            
            if inches_to_pixels(splitheight) < grid_image.height:
                print(f"[DEBUG] Grid too tall ({grid_image.height}px > {inches_to_pixels(splitheight)}px), splitting")
                parts = split_image_by_max_height(grid_image, num_rows, row_height, margin_px, splitheight)
                print(f"[DEBUG] Split into {len(parts)} parts")
                
                zip_io = io.BytesIO()
                with zipfile.ZipFile(zip_io, 'w', zipfile.ZIP_DEFLATED) as zipf:
                    for i, part in enumerate(parts, 1):
                    
                        temp_io = io.BytesIO()
                        if int(product_id) == 31981:
                            qr_content = f"{order_id}_{i}.jpg"
                            print(f"[DEBUG] Processing part {i}/{len(parts)} with QR: {qr_content}")
                            if part.mode == "RGBA":
                                background = Image.new("RGB", part.size, (255, 255, 255))  # white background
                                background.paste(part, mask=part.split()[3])  # 3 is the alpha channel
                                part = background
                            else:
                                part = part.convert("RGB")
                            part.save(temp_io, format='JPEG', dpi=(300, 300))
                            part_with_qr_io = add_qr_code_to_image_test(temp_io.getvalue(), qr_content, 'JPEG', 31981, dropshipping=dropshipping)
                            part_with_qr_io.seek(0)
                            zipf.writestr(f"{order_id}_{i}.jpg", part_with_qr_io.read())
                        else:
                            qr_content = f"{order_id}_{i}.{image.format.lower()}"
                            print(f"[DEBUG] Processing part {i}/{len(parts)} with QR: {qr_content}")
                            part.save(temp_io, format=image.format, dpi=(300, 300))
                            part_with_qr_io = add_qr_code_to_image_test(temp_io.getvalue(), qr_content, image.format, dropshipping=dropshipping)
                            part_with_qr_io.seek(0)
                            zipf.writestr(f"{order_id}_{i}.{image.format.lower()}", part_with_qr_io.read())
                        
                zip_io.seek(0)
                print(f"[DEBUG] Uploading ZIP file to S3: processed/{order_id}.zip")
                orderId, itemId = order_id.split("_")
                upload_to_s3(zip_io, f"processed/{orderId}/{itemId}/{order_id}.zip", s3_bucket, "application/zip", aws_access_key, aws_secret_key, aws_region)
                print("[DEBUG] ZIP upload completed successfully")
                return

            img_io = io.BytesIO()
            grid_image.save(img_io, format=image.format, dpi=(300, 300))
            img_io.seek(0)
            final_image_bytes = img_io.read()
            
            print(f"[DEBUG] Grid image saved, final size: {len(final_image_bytes)} bytes")

        qr_content = f"{order_id}.{image.format.lower()}"
        print(f"[DEBUG] QR content: {qr_content}")
        print(f"[DEBUG] Product ID check: {product_id} (type: {type(product_id)})")
        
        if int(product_id) == 31981:
            print("[DEBUG] Special product 31981 - converting to PDF")
            if int(product_id) not in exclude_qr_code and not jpeg_format:
                print("[DEBUG] Adding QR code to image")
                final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, image.format, 31981, dropshipping=dropshipping)
            else:
                print("[DEBUG] Skipping QR code (excluded or JPEG format)")
                final_img_io = io.BytesIO(final_image_bytes)
            image = Image.open(final_img_io).convert('RGB')
            pdf_io = io.BytesIO()
            image.save(pdf_io, format='JPEG', dpi=(300, 300))
            pdf_io.seek(0)
            print(f"[DEBUG] Uploading PDF to S3: processed/{order_id}.jpg")
            orderId, itemId = order_id.split("_")
            upload_to_s3(pdf_io, f"processed/{orderId}/{itemId}/{order_id}.jpg", s3_bucket, "image/jpeg", aws_access_key, aws_secret_key, aws_region)
            print("[DEBUG] PDF upload completed successfully")
            return
        print(f"[DEBUG] Image format {image.format.lower()}")
        jpeg_format = True if image.format.lower() in ['jpeg', 'jpg', 'mpo'] else False
        if int(product_id) not in exclude_qr_code and not jpeg_format:
            print("[DEBUG] Adding QR code to final image")
            final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, image.format, dropshipping=dropshipping)
        else:
            print("[DEBUG] Skipping QR code (product excluded or JPEG format)")
            final_img_io = io.BytesIO(final_image_bytes)
        orderId, itemId = order_id.split("_")
        upload_filename = f"processed/{orderId}/{itemId}/{order_id}.{'jpg' if jpeg_format else image.format.lower()}"
        print(f"[DEBUG] Uploading image to S3: {upload_filename}")
        
        s3_url = upload_to_s3(final_img_io, upload_filename, s3_bucket, f"image/{image.format.lower()}", aws_access_key, aws_secret_key, aws_region)
        print("[DEBUG] Image upload completed successfully")
        print(f"[RESULT] S3 URL: {s3_url}")
        return

    # ---- PDFs with width & height ----
    elif width_inch and height_inch and 'pdf' in content_type:
        print("[DEBUG] Branch: PDFs with width & height")
        print(f"[DEBUG] Resizing PDF to {width_inch}\" x {height_inch}\"")
        png_images = resize_pdf(file_bytes, float(width_inch), float(height_inch))
        
        if not png_images:
            print("[ERROR] No images found in the PDF")
            raise ValueError("No images found in the PDF")
        
        print(f"[DEBUG] PDF converted to {len(png_images)} PNG images")
        final_image_bytes = png_images[0]

        if quantity:
            print(f"[DEBUG] Creating grid with {quantity} images")

            image = Image.open(io.BytesIO(png_images[0]))
            special_products = [32319, 176573, 24473, 12221, 9945, 31941, 59296, 157565,
                                59684, 59446, 170738, 158772, 170749, 13624, 7477]
            print(f"[DEBUG] Special products list: {special_products}")
            
            if int(product_id) in special_products and quantity and quantity > 1:
                print(f"[DEBUG] Special product {product_id} with quantity {quantity} - creating individual files")
                zip_io = io.BytesIO()
                with zipfile.ZipFile(zip_io, 'w', zipfile.ZIP_DEFLATED) as zipf:
                    for i in range(1, quantity + 1):
                        if int(product_id) in [9945, 31941]:
                            filename = f"{order_id}_{i}.pdf"
                        else:
                            filename = f"{order_id}_{i}.png"
                        
                        print(f"[DEBUG] Creating individual file {i}/{quantity}: {filename}")
                        part_with_qr_io = add_qr_code_to_image_test(final_image_bytes, filename, "PNG", int(product_id), dropshipping=dropshipping)
                        
                        if int(product_id) in [9945, 31941]:
                            part_with_qr_io.seek(0)
                            img = Image.open(part_with_qr_io).convert('RGB')
                            output_io = io.BytesIO()
                            img.save(output_io, format='PDF', resolution=300.0)
                            output_io.seek(0)
                            zipf.writestr(filename, output_io.read())
                        else:
                            part_with_qr_io.seek(0)
                            zipf.writestr(filename, part_with_qr_io.read())

                zip_io.seek(0)
                print(f"[DEBUG] Uploading special product ZIP to S3: processed/{order_id}.zip")
                orderId, itemId = order_id.split("_")
                upload_to_s3(zip_io, f"processed/{orderId}/{itemId}/{order_id}.zip", s3_bucket, "application/zip", aws_access_key, aws_secret_key, aws_region)
                print("[DEBUG] Special product ZIP upload completed successfully")
                return
                zip_io.seek(0)
                print(f"[DEBUG] Uploading special product ZIP to S3: processed/{order_id}.zip")
                orderId, itemId = order_id.split("_")
                upload_to_s3(zip_io, f"processed/{orderId}/{itemId}/{order_id}.zip", s3_bucket, "application/zip", aws_access_key, aws_secret_key, aws_region)
                print("[DEBUG] Special product ZIP upload completed successfully")
                return


            grid_image, num_rows, row_height, margin_px = create_image_grid_zipping(
                final_image_bytes, float(width_inch), float(height_inch), quantity, limitwidth
            )
            print(f"[DEBUG] Grid created - size: {grid_image.size}, rows: {num_rows}")
            
            if inches_to_pixels(splitheight) < grid_image.height:
                print(f"[DEBUG] Grid too tall ({grid_image.height}px > {inches_to_pixels(splitheight)}px), splitting")
                parts = split_image_by_max_height(grid_image, num_rows, row_height, margin_px, splitheight)
                print(f"[DEBUG] Split into {len(parts)} parts")
                
                zip_io = io.BytesIO()
                with zipfile.ZipFile(zip_io, 'w', zipfile.ZIP_DEFLATED) as zipf:
                    for i, part in enumerate(parts, 1):
                        # Determine file format based on product_id
                        if int(product_id) == 31981:
                            qr_content = f"{order_id}_{i}.pdf"
                        else:
                            qr_content = f"{order_id}_{i}.{image.format.lower()}"
                        
                        print(f"[DEBUG] Processing part {i}/{len(parts)} with QR: {qr_content}")
                        
                        temp_io = io.BytesIO()
                        part.save(temp_io, format=image.format, dpi=(300, 300))
                        part_with_qr_io = add_qr_code_to_image_test(temp_io.getvalue(), qr_content, image.format, product_id, dropshipping=dropshipping)
                        
                        # Convert to PDF if product_id is 31981
                        if int(product_id) == 31981:
                            part_with_qr_io.seek(0)
                            img = Image.open(part_with_qr_io).convert('RGB')
                            pdf_io = io.BytesIO()
                            img.save(pdf_io, format='PDF', resolution=300.0)
                            pdf_io.seek(0)
                            zipf.writestr(f"{order_id}_{i}.pdf", pdf_io.read())
                        else:
                            part_with_qr_io.seek(0)
                            zipf.writestr(f"{order_id}_{i}.{image.format.lower()}", part_with_qr_io.read())
                        
                zip_io.seek(0)
                print(f"[DEBUG] Uploading split ZIP to S3: processed/{order_id}.zip")
                orderId, itemId = order_id.split("_")
                upload_to_s3(zip_io, f"processed/{orderId}/{itemId}/{order_id}.zip", s3_bucket, "application/zip", aws_access_key, aws_secret_key, aws_region)
                print("[DEBUG] Split ZIP upload completed successfully")
                return

            img_io = io.BytesIO()
            grid_image.save(img_io, format=image.format, dpi=(300, 300))
            img_io.seek(0)
            final_image_bytes = img_io.read()
            print(f"[DEBUG] Grid image saved, final size: {len(final_image_bytes)} bytes")

        qr_content = f"{order_id}.png"
        print(f"[DEBUG] QR content: {qr_content}")
        
        if int(product_id) == 31981:
            print("[DEBUG] Special product 31981 - converting to PDF")
            if int(product_id) not in exclude_qr_code:
                print("[DEBUG] Adding QR code to image")
                final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, "PNG", 31981, dropshipping=dropshipping)
            else:
                print("[DEBUG] Skipping QR code (product excluded)")
                final_img_io = io.BytesIO(final_image_bytes)
            image = Image.open(final_img_io).convert('RGB')
            pdf_io = io.BytesIO()
            image.save(pdf_io, format='PDF', resolution=300.0)
            pdf_io.seek(0)
            orderId, itemId = order_id.split("_")
            upload_to_s3(pdf_io, f"processed/{orderId}/{itemId}/{order_id}.pdf", s3_bucket, "application/pdf", aws_access_key, aws_secret_key, aws_region)
            print("[DEBUG] PDF upload completed successfully")
            return

        if int(product_id) not in exclude_qr_code:
            print("[DEBUG] Adding QR code to final image")
            final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, "PNG", dropshipping=dropshipping)
        else:
            print("[DEBUG] Skipping QR code (product excluded)")
            final_img_io = io.BytesIO(final_image_bytes)
        
        print(f"[DEBUG] Uploading PNG to S3: processed/{order_id}.png")
        orderId, itemId = order_id.split("_")
        upload_to_s3(final_img_io, f"processed/{orderId}/{itemId}/{order_id}.png", s3_bucket, "image/png", aws_access_key, aws_secret_key, aws_region)
        print("[DEBUG] PNG upload completed successfully")
        return

    # ---- Everything else (images or PDFs without resize) ----
    else:
        print("[DEBUG] Branch: Everything else (no resize)")
        
        if 'image' in content_type:
            print("[DEBUG] Processing image without resize")
            image = Image.open(io.BytesIO(file_bytes))
            print(f"[DEBUG] Original image - format: {image.format}, size: {image.size}, mode: {image.mode}")
            original_format_store = image.format
            # FIX: Convert palette mode to RGBA
            if image.mode == 'P':
                print("[DEBUG] Converting palette mode (P) to RGBA")
                image = image.convert('RGBA')
                print(f"[DEBUG] After conversion - mode: {image.mode}")
                # Restore format info after conversion
                image.format = original_format_store
            dpinf = False
            dpi_info = image.info.get("dpi")
            dpi_value = 300
            print("[DEBUG] Using original DPI info from image", dpi_info)

            special_products = [32319, 176573, 24473, 12221, 9945, 59296, 157565,
                                59684, 59446, 170738, 158772, 170749, 13624, 7477]
            if int(product_id) in special_products:
                if dpi_info and dpi_info[0]:
                    
                    dpi_value = round_half_up(dpi_info[0])               
                dpinf = True
            # JPEG → PNG for transparency & QR
            jpeg_format = False
            if image.format in ['JPEG', 'JPG']:
                print("[DEBUG] Converting JPEG to PNG for transparency support")
                jpeg_format = True
                img_io = io.BytesIO()
                image = image.convert("RGBA")
                image.save(img_io, format='PNG', dpi=(dpi_value, dpi_value))
                img_io.seek(0)
                image = Image.open(img_io)

            img_io = io.BytesIO()
            image.save(img_io, format=image.format, dpi=(dpi_value, dpi_value))
            img_io.seek(0)
            final_image_bytes = img_io.read()
            print(f"[DEBUG] Image processed, size: {len(final_image_bytes)} bytes")
            
            
            print(f"[DEBUG] Special products list: {special_products}")
            
            if int(product_id) in special_products and quantity and quantity > 1:
                print(f"[DEBUG] Special product {product_id} with quantity {quantity} - creating individual files")
                zip_io = io.BytesIO()
                with zipfile.ZipFile(zip_io, 'w', zipfile.ZIP_DEFLATED) as zipf:
                    for i in range(1, quantity + 1):
                        if int(product_id) == 31981:
                            filename = f"{order_id}_{i}.jpg"
                            print(f"[DEBUG] Creating individual file {i}/{quantity}: {filename}")
                            part_with_qr_io = add_qr_code_to_image_test(final_image_bytes, filename, "JPG", int(product_id), dpinfo=True, dropshipping=dropshipping)
                            part_with_qr_io.seek(0)

                            img = Image.open(part_with_qr_io)
                            if img.mode in ("RGBA", "LA"):  
                                background = Image.new("RGB", img.size, (255, 255, 255))  # white background
                                background.paste(img, mask=img.split()[-1])  # use alpha channel as mask
                                rgb_io = io.BytesIO()
                                background.save(rgb_io, format="JPEG")
                                rgb_io.seek(0)
                                zipf.writestr(filename, rgb_io.read())
                            else:
                                zipf.writestr(filename, part_with_qr_io.read())
                        else:
                            filename = f"{order_id}_{i}.png"
                            print(f"[DEBUG] Creating individual file {i}/{quantity}: {filename}")
                            part_with_qr_io = add_qr_code_to_image_test(final_image_bytes, filename, "PNG", int(product_id), dpinfo=dpinf, dropshipping=dropshipping)
                            part_with_qr_io.seek(0)
                            zipf.writestr(filename, part_with_qr_io.read())

                        
                zip_io.seek(0)
                print(f"[DEBUG] Uploading special product ZIP to S3: processed/{order_id}.zip")
                orderId, itemId = order_id.split("_")

                upload_to_s3(zip_io, f"processed/{orderId}/{itemId}/{order_id}.zip", s3_bucket, "application/zip", aws_access_key, aws_secret_key, aws_region)

                print("[DEBUG] Special product ZIP upload completed successfully")
                return

            qr_content = f"{order_id}.{image.format.lower()}"
            print(f"[DEBUG] QR content: {qr_content}")

            if int(product_id) == 31981:
                print("[DEBUG] Special product 31981 - converting to PDF")
                if int(product_id) not in exclude_qr_code and not jpeg_format:
                    print("[DEBUG] Adding QR code to image")
                    final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, image.format, 31981, dropshipping=dropshipping)
                else:
                    print("[DEBUG] Skipping QR code (excluded or JPEG format)")
                    final_img_io = io.BytesIO(final_image_bytes)
                image = Image.open(final_img_io).convert('RGB')
                pdf_io = io.BytesIO()
                image.save(pdf_io, format='JPEG', resolution=300.0)
                pdf_io.seek(0)
                print(f"[DEBUG] Uploading PDF to S3: processed/{order_id}.pdf")
                orderId, itemId = order_id.split("_")
                upload_to_s3(pdf_io, f"processed/{orderId}/{itemId}/{order_id}.pdf", s3_bucket, "application/pdf", aws_access_key, aws_secret_key, aws_region)
                print("[DEBUG] PDF upload completed successfully")
                return

            # Default image case
            if int(product_id) not in exclude_qr_code and not jpeg_format:
                print("[DEBUG] Adding QR code to final image")
                final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, image.format, int(product_id), dpinfo=dpinf, dropshipping=dropshipping)
            else:
                print("[DEBUG] Skipping QR code (product excluded or JPEG format)")
                final_img_io = io.BytesIO(final_image_bytes)
            orderId, itemId = order_id.split("_")
            upload_filename = f"processed/{orderId}/{itemId}/{order_id}.{image.format.lower()}"
            print(f"[DEBUG] Uploading image to S3: {upload_filename}")

            upload_to_s3(final_img_io, upload_filename, s3_bucket, f"image/{image.format.lower()}", aws_access_key, aws_secret_key, aws_region)
            print("[DEBUG] Image upload completed successfully")
            return

        elif 'pdf' in content_type:
            print("[DEBUG] Processing PDF without resize")
            special_products = [32319, 176573, 24473, 12221, 9945, 59296, 157565,
                                59684, 59446, 170738, 158772, 170749, 13624, 7477]
           
            if int(product_id) in special_products and quantity and quantity > 1:
                    zip_io = BytesIO()
                    pdf_document = fitz.open(stream=file_bytes, filetype="pdf")
                    page = pdf_document.load_page(0)  # first page
                    pix = page.get_pixmap(matrix=fitz.Matrix(300/72, 300/72), alpha=True)
                    final_image_bytes = pix.tobytes("png")  # transparent PNG bytes
                    
                    with zipfile.ZipFile(zip_io, 'w', zipfile.ZIP_DEFLATED) as zipf:
                        for i in range(1, quantity + 1):
                            filename = f"{order_id}_{i}.png"
                            qr_content = filename  
                            part_with_qr_io = add_qr_code_to_image_test(final_image_bytes, qr_content, "PNG", int(product_id), dropshipping=dropshipping)
                            part_with_qr_io.seek(0)  # Make sure we're at the beginning
                            image_bytes = part_with_qr_io.getvalue()  # Get all bytes from BytesIO
                            zipf.writestr(filename, image_bytes)
                            # zipf.writestr(filename, part_with_qr_io.read())
                    zip_io.seek(0)
                    orderId, itemId = order_id.split("_")
                    upload_to_s3(zip_io, f"processed/{orderId}/{itemId}/{order_id}.zip", s3_bucket, "application/zip", aws_access_key, aws_secret_key, aws_region)
                    print("[DEBUG] PDF upload completed successfully to zip")
                    return
            pdf_document = fitz.open(stream=file_bytes, filetype="pdf")
            page = pdf_document.load_page(0)  # first page
            pix = page.get_pixmap(matrix=fitz.Matrix(300/72, 300/72), alpha=True)
                
            img_bytes = pix.tobytes("png")  # transparent PNG bytes
            final_image_bytes = img_bytes
                
            print(f"[DEBUG] PDF converted to PNG, size: {len(final_image_bytes)} bytes")
            
          
            qr_content = f"{order_id}.png"
            print(f"[DEBUG] QR content: {qr_content}")

            if int(product_id) == 31981:
                print("[DEBUG] Special product 31981 - converting to PDF")
                if int(product_id) not in exclude_qr_code:
                    print("[DEBUG] Adding QR code to image")
                    final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, "PNG", 31981, dropshipping=dropshipping)
                else:
                    print("[DEBUG] Skipping QR code (product excluded)")
                    final_img_io = io.BytesIO(final_image_bytes)
                image = Image.open(final_img_io).convert('RGB')
                pdf_out = io.BytesIO()
                image.save(pdf_out, format='JPEG', resolution=300.0)
                pdf_out.seek(0)
                print(f"[DEBUG] Uploading PDF to S3: processed/{order_id}.pdf")
                orderId, itemId = order_id.split("_")
                upload_to_s3(pdf_out, f"processed/{orderId}/{itemId}/{order_id}.pdf", s3_bucket, "application/pdf", aws_access_key, aws_secret_key, aws_region)
                print("[DEBUG] PDF upload completed successfully")
                return

            if int(product_id) not in exclude_qr_code:
                print("[DEBUG] Adding QR code to final image")
                final_img_io = add_qr_code_to_image_test(final_image_bytes, qr_content, "PNG", int(product_id), dropshipping=dropshipping)
            else:
                print("[DEBUG] Skipping QR code (product excluded)")
                final_img_io = io.BytesIO(final_image_bytes)
            
            print(f"[DEBUG] Uploading PNG to S3: processed/{order_id}.png")
            orderId, itemId = order_id.split("_")
            upload_to_s3(final_img_io, f"processed/{orderId}/{itemId}/{order_id}.png", s3_bucket, "image/png", aws_access_key, aws_secret_key, aws_region)
            print("[DEBUG] PNG upload completed successfully")
            return

        else:
            print(f"[ERROR] Unsupported file type: {content_type}")
            raise ValueError("Unsupported file type")
def check_dpi(image_url):
    try:
        response = requests.get(image_url, stream=True)
        print(f"[DEBUG] Download response status: {response.status_code}")
        
        if response.status_code != 200:
            return 0

        file_bytes = response.content
        image = Image.open(io.BytesIO(file_bytes))
        dpi_info = image.info.get("dpi")
        if dpi_info:
            return 0
        return -1
    except Exception as e:
        print(f"[ERROR] Exception in check_dpi: {e}")
        return 0

def should_process(db_config, order_id, item_id, image_url=None, product_id = None, width = None, height = None, quantity = None, limitwidth = None):
    """
    Decide whether to process a file based on BPyN0vqr_processing_table state.
    Returns:
      (True, record_id)  → proceed with processing
      (False, record_id) → skip processing
    """
    try:
        conn = mysql.connector.connect(**db_config)
        cursor = conn.cursor(dictionary=True)

        cursor.execute("""
            SELECT id, status, retry_count, image_url
            FROM BPyN0vqr_processing_table
            WHERE order_id = %s AND item_id = %s
        """, (order_id, item_id))
        row = cursor.fetchone()
        dpi_validation = 0
        if int(product_id) in [32319, 176573, 24473, 12221, 9945, 59296, 157565, 59684, 59446, 170738, 158772, 170749, 13624, 7477]:
            if image_url:
                dpi_validation = check_dpi(image_url)
        
        if not row:
            # Insert new record
            cursor.execute("""
                INSERT INTO BPyN0vqr_processing_table
                (order_id, item_id, image_url, product_id, width, height, quantity, limitwidth, status, started_at, retry_count, dpi_valid)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """, (order_id, item_id, image_url, product_id, width, height, quantity, limitwidth, "processing", datetime.now(), 0, dpi_validation))

            conn.commit()
            record_id = cursor.lastrowid
            cursor.close()
            conn.close()
            return True, record_id

        # Case: already exists
        if row["status"] in ("completed", "error"):
            cursor.close()
            conn.close()
            return False, row["id"]

        if row["status"] == "processing":
            if row["retry_count"] >= 3:
                cursor.execute("""
                    UPDATE BPyN0vqr_processing_table
                    SET status = %s,
                        completed_at = %s,
                        error_message = %s
                    WHERE id = %s
                """, ("error", datetime.now(), "Exceeded max retries", row["id"]))
                conn.commit()
                cursor.close()
                conn.close()
                return False, row["id"]

            # Retry allowed → increment retry_count
            new_retry = row["retry_count"] + 1
            cursor.execute("""
                UPDATE BPyN0vqr_processing_table
                SET retry_count = %s,
                    started_at = %s,
                    dpi_valid = %s
                WHERE id = %s
            """, (new_retry, datetime.now(), dpi_validation, row["id"]))
            conn.commit()
            cursor.close()
            conn.close()
            return True, row["id"]

    except mysql.connector.Error as err:
        print(f"Database error: {err}")
        return False, None



def check_s3_file_exists(url):
    """Check if an S3 file exists by sending a HEAD request."""
    try:
        response = requests.head(url)
        return response.status_code == 200
    except requests.RequestException:
        return False


def find_existing_file(base_path, formats=None):
    """Try multiple formats to see if a processed file exists in S3."""
    if formats is None:
        formats = ["png", "jpg", "jpeg", "pdf", "zip"]

    for fmt in formats:
        file_url = f"{base_path}.{fmt}"
        if check_s3_file_exists(file_url):
            return {"url": file_url, "format": fmt}
    return None

def update_status_post_process(db_config, order_id, item_id, s3_base_url, s3_folder="processed", product_id=0):
    """
    After attempting processing, check if the file exists on S3.
    Update status in the database accordingly.
    """
    conn = mysql.connector.connect(**db_config)
    cursor = conn.cursor(dictionary=True)

    base_path = f"{s3_base_url}/{s3_folder}/{order_id}/{item_id}/{order_id}_{item_id}"
    found_file = find_existing_file(base_path)

    cursor.execute("""
        SELECT id, status, retry_count
        FROM BPyN0vqr_processing_table
        WHERE order_id = %s AND item_id = %s
    """, (order_id, item_id))
    row = cursor.fetchone()

    if not row:
        cursor.close()
        conn.close()
        return  # safety net

    if found_file:
        # ✅ Mark as completed
        if int(product_id) in [32317, 32319, 32500, 28377]:
            # For hot peel products, set lambda_call to 0
            cursor.execute("""
                UPDATE BPyN0vqr_processing_table
                SET status = %s,
                    completed_at = %s,
                    lambda_call = 1,
                    error_message = NULL
                WHERE id = %s
            """, ("completed", datetime.now(), row["id"]))
        else:
            cursor.execute("""
                UPDATE BPyN0vqr_processing_table
                SET status = %s,
                    completed_at = %s,
                    error_message = NULL
                WHERE id = %s
            """, ("completed", datetime.now(), row["id"]))
    else:
        # 🚫 No file found
        if row["retry_count"] >= 3:
            cursor.execute("""
                UPDATE BPyN0vqr_processing_table
                SET status = %s,
                    completed_at = %s,
                    error_message = %s
                WHERE id = %s
            """, ("error", datetime.now(), "No file found after retries", row["id"]))
        else:
            cursor.execute("""
                UPDATE BPyN0vqr_processing_table
                SET status = %s
                WHERE id = %s
            """, ("processing", row["id"]))

    conn.commit()
    cursor.close()
    conn.close()
def check_and_create_hot_peel_file(db_config, order_id, s3_bucket, aws_access_key=None, aws_secret_key=None, aws_region="us-east-1"):
    """
    Check if all items for specific products in an order are completed with lambda_call=0,
    then create and upload a peels.txt file listing the filenames.
    
    Args:
        db_config: Database configuration dictionary
        order_id: The order ID to check
        s3_bucket: S3 bucket name
        aws_access_key: AWS access key (optional if using env vars)
        aws_secret_key: AWS secret key (optional if using env vars)
        aws_region: AWS region
    """
    import io
    
    HOT_PEEL_PRODUCTS = [32317, 32319, 32500, 28377]
    
    try:
        # Connect to database
        connection = mysql.connector.connect(**db_config)
        cursor = connection.cursor(dictionary=True)
        
        # Check if there are any items with hot peel products for this order
        check_query = """
            SELECT COUNT(*) as count 
            FROM BPyN0vqr_processing_table 
            WHERE order_id = %s AND product_id IN (%s, %s, %s, %s)
        """
        cursor.execute(check_query, (order_id, *HOT_PEEL_PRODUCTS))
        result = cursor.fetchone()
        
        if result['count'] == 0:
            print(f"[INFO] No hot peel products found for order {order_id}")
            cursor.close()
            connection.close()
            return
        
        # Check if all hot peel items are completed with status 'completed' and lambda_call = 0
        status_query = """
            SELECT item_id, status, lambda_call
            FROM BPyN0vqr_processing_table 
            WHERE order_id = %s AND product_id IN (%s, %s, %s, %s)
        """
        cursor.execute(status_query, (order_id, *HOT_PEEL_PRODUCTS))
        items = cursor.fetchall()
        
        # Check if all items are completed and lambda_call is 0
        all_completed = all(
            item['status'] == 'completed' and item['lambda_call'] == 1 
            for item in items
        )
        
        if not all_completed:
            print(f"[INFO] Not all hot peel items completed for order {order_id} or lambda_call != 0")
            cursor.close()
            connection.close()
            return
        
        print(f"[INFO] All hot peel items completed for order {order_id}. Creating peels.txt file...")
        
        # Create the file content with filenames (orderid_itemid format)
        file_content = ""
        for item in items:
            filename = f"{order_id}_{item['item_id']}"
            file_content += f"{filename}\n"
        
        # Upload to S3
        s3_key = f"processed/{order_id}/hot_peel/peels.txt"
        
        # Initialize S3 client
        session = boto3.Session(
            aws_access_key_id=aws_access_key or os.environ.get('AWS_ACCESS_KEY_ID'),
            aws_secret_access_key=aws_secret_key or os.environ.get('AWS_SECRET_ACCESS_KEY'),
            region_name=aws_region
        )
        s3_client = session.client('s3')
        
        # Upload the file
        s3_client.put_object(
            Bucket=s3_bucket,
            Key=s3_key,
            Body=file_content.encode('utf-8'),
            ContentType='text/plain'
        )
        
        print(f"[SUCCESS] Hot peel file uploaded to s3://{s3_bucket}/{s3_key}")
        print(f"[INFO] File contains {len(items)} filename(s)")
        
       
        
    except mysql.connector.Error as db_error:
        print(f"[ERROR] Database error in check_and_create_hot_peel_file: {db_error}")
        if connection:
            connection.rollback()
    except Exception as e:
        print(f"[ERROR] Error in check_and_create_hot_peel_file: {type(e).__name__}: {str(e)}")
        import traceback
        traceback.print_exc()
    finally:
        if 'cursor' in locals() and cursor:
            cursor.close()
        if 'connection' in locals() and connection:
            connection.close()
def main():
    print("[DEBUG] Starting main function")
    parser = argparse.ArgumentParser(description="Process and upload images to S3")
    parser.add_argument("--image-url", required=True, help="URL of the image to process")
    parser.add_argument("--width", type=float, help="Target width in inches")
    parser.add_argument("--height", type=float, help="Target height in inches")
    parser.add_argument("--quantity", type=int, help="Number of images in grid")
    parser.add_argument("--limitwidth", type=float, help="Limit width for grid")
    parser.add_argument("--dropshipping", type=int, help="dropshipping flag", default=0)
    parser.add_argument("--order-id", required=True, help="Order ID for the file")
    parser.add_argument("--product-id", type=int, help="Product ID")
    parser.add_argument("--s3-bucket", required=True, help="S3 bucket name")
    parser.add_argument("--s3-folder", default="processed", help="S3 folder to upload to")
    parser.add_argument("--aws-access-key", help="AWS access key (or set AWS_ACCESS_KEY_ID env var)")
    parser.add_argument("--aws-secret-key", help="AWS secret key (or set AWS_SECRET_ACCESS_KEY env var)")
    parser.add_argument("--aws-region", default="us-east-1", help="AWS region")
    parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose logging")
    
    print("[DEBUG] Parsing command line arguments")
    args = parser.parse_args()
    
    print("[DEBUG] Command line arguments parsed:")
    print(f"[DEBUG] - image_url: {args.image_url}")
    print(f"[DEBUG] - width: {args.width}, height: {args.height}")
    print(f"[DEBUG] - quantity: {args.quantity}, limitwidth: {args.limitwidth}")
    print(f"[DEBUG] - order_id: {args.order_id}, product_id: {args.product_id}")
    print(f"[DEBUG] - s3_bucket: {args.s3_bucket}, s3_folder: {args.s3_folder}")
    print(f"[DEBUG] - aws_region: {args.aws_region}")
    print(f"[DEBUG] - verbose: {args.verbose}")
    orderId, ItemId = args.order_id.split("_")
    
    try:

        print("[DEBUG] Calling process_file function")

        should_run, record_id = should_process(db_config, order_id=orderId, item_id=ItemId, image_url= args.image_url, product_id=args.product_id, width=args.width, height=args.height, quantity=args.quantity, limitwidth=args.limitwidth)

        if should_run:
            print("➡️ Proceed with processing...")
            process_file(
            image_url=args.image_url,
            width_inch=args.width,
            height_inch=args.height,
            quantity=args.quantity,
            limitwidth=args.limitwidth,
            dropshipping=args.dropshipping,
            order_id=args.order_id,
            product_id=args.product_id,
            s3_folder=args.s3_folder,
            s3_bucket=args.s3_bucket,
            aws_access_key=args.aws_access_key,
            aws_secret_key=args.aws_secret_key,
            aws_region=args.aws_region

        )
            print("[DEBUG] process_file completed successfully")
        else:
            print("⏭ Skipping processing.")
        
        
    except Exception as e:
        print(f"[ERROR] Exception occurred in main: {type(e).__name__}: {str(e)}")
        print("[ERROR] Full traceback:")
        import traceback
        traceback.print_exc()
        # sys.exit(1)
    
    print("[DEBUG] Main function completed successfully")
    update_status_post_process(
        db_config,
        order_id=orderId,
        item_id=ItemId,
        s3_base_url=f"https://{args.s3_bucket}.s3.us-east-1.amazonaws.com",
        product_id=args.product_id
    )

    check_and_create_hot_peel_file(
        db_config=db_config,
        order_id=orderId,
        s3_bucket=args.s3_bucket,
        aws_access_key=args.aws_access_key,
        aws_secret_key=args.aws_secret_key,
        aws_region=args.aws_region
    )

if __name__ == "__main__":
    import time
    starttime = time.time()
    main()
    endtime = time.time()
    duration = endtime - starttime
    print(f"[DEBUG] Total execution time: {duration:.2f} seconds")