import os
import zipfile
import secrets
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import base64

def encrypt_file(input_path, output_path, password):
    key = password.encode('utf-8').ljust(32)[:32]
    iv = secrets.token_bytes(16)
    
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()
    
    padder = padding.PKCS7(128).padder()
    
    with open(input_path, 'rb') as f_in:
        with open(output_path, 'wb') as f_out:
            f_out.write(iv)
            
            while True:
                chunk = f_in.read(64 * 1024)
                if not chunk:
                    break
                padded_chunk = padder.update(chunk)
                f_out.write(encryptor.update(padded_chunk))
            
            final_padded = padder.finalize()
            f_out.write(encryptor.update(final_padded))
            f_out.write(encryptor.finalize())

def create_encrypted_zip(input_folder, output_zip, password):
    temp_zip = output_zip + '.tmp'
    
    with zipfile.ZipFile(temp_zip, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(input_folder):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, input_folder)
                zipf.write(file_path, arcname)
    
    encrypt_file(temp_zip, output_zip, password)
    os.remove(temp_zip)

def split_file(input_file, part_size_mb=50):
    part_size = part_size_mb * 1024 * 1024
    parts = []
    
    file_size = os.path.getsize(input_file)
    base_name = os.path.splitext(input_file)[0]
    
    with open(input_file, 'rb') as f:
        part_num = 1
        while True:
            chunk = f.read(part_size)
            if not chunk:
                break
            
            part_name = f"{base_name}.part{part_num:03d}"
            with open(part_name, 'wb') as part_file:
                part_file.write(chunk)
            
            parts.append(part_name)
            part_num += 1
    
    return parts

def prepare_product_files(input_folder, output_dir, product_id, password, part_size_mb=50):
    os.makedirs(output_dir, exist_ok=True)
    
    encrypted_zip = os.path.join(output_dir, f"product_{product_id}_encrypted.zip")
    create_encrypted_zip(input_folder, encrypted_zip, password)
    
    if os.path.getsize(encrypted_zip) > part_size_mb * 1024 * 1024:
        parts = split_file(encrypted_zip, part_size_mb)
        os.remove(encrypted_zip)
        return parts
    else:
        return [encrypted_zip]
