import streamlit as st
import os
import PyPDF2
import tempfile
import shutil
from pathlib import Path
import math
import time

def split_pdf_fast(input_file, target_size_mb=100):
    """Split a PDF file into multiple files of approximately target_size_mb each, using a faster approach"""
    # Get the total size of the input file in MB
    total_size_mb = os.path.getsize(input_file) / (1024 * 1024)
    
    if total_size_mb <= target_size_mb:
        st.info(f"File is already smaller than {target_size_mb}MB. No need to split.")
        return []
    
    original_filename = os.path.basename(input_file)
    filename_without_ext = os.path.splitext(original_filename)[0]
    
    # Create a temporary directory to store output files
    with tempfile.TemporaryDirectory() as temp_dir:
        # Open the PDF file
        with open(input_file, 'rb') as file:
            pdf_reader = PyPDF2.PdfReader(file)
            total_pages = len(pdf_reader.pages)
            
            # Calculate number of chunks needed
            num_chunks = math.ceil(total_size_mb / target_size_mb)
            
            # Calculate approximately how many pages per chunk (evenly distributed)
            pages_per_chunk = math.ceil(total_pages / num_chunks)
            
            output_files = []
            
            # Process chunks
            for chunk_number in range(1, num_chunks + 1):
                start_page = (chunk_number - 1) * pages_per_chunk
                end_page = min(chunk_number * pages_per_chunk, total_pages)
                
                if start_page >= total_pages:
                    break
                
                # Create a new PDF writer for this chunk
                pdf_writer = PyPDF2.PdfWriter()
                
                # Add pages to this chunk
                for page_num in range(start_page, end_page):
                    pdf_writer.add_page(pdf_reader.pages[page_num])
                
                # Generate output file name
                output_file = os.path.join(temp_dir, f"{filename_without_ext}({chunk_number}).pdf")
                
                # Write the PDF to the output file
                with open(output_file, 'wb') as output:
                    pdf_writer.write(output)
                
                # Calculate the actual size of the output file
                actual_size_mb = os.path.getsize(output_file) / (1024 * 1024)
                
                # Add the output file to the list
                output_files.append({
                    'path': output_file,
                    'filename': f"{filename_without_ext}({chunk_number}).pdf",
                    'size_mb': actual_size_mb,
                    'pages': end_page - start_page
                })
        
        # Copy files to a location outside the temporary directory
        permanent_files = []
        output_dir = os.path.dirname(input_file)
        
        for file_info in output_files:
            dest_path = os.path.join(output_dir, file_info['filename'])
            shutil.copy2(file_info['path'], dest_path)
            file_info['path'] = dest_path
            permanent_files.append(file_info)
        
        return permanent_files

def main():
    st.title("Large Pdf Splitter")
    st.write("Upload a large PDF file to split it into smaller chunks")
    
    max_chunk_size = st.slider("Maximum size per chunk (MB)", min_value=10, max_value=500, value=100, step=10)
    
   
    
    uploaded_file = st.file_uploader("Choose a PDF file", type="pdf")
    
    if uploaded_file is not None:
        # Create a temporary file to save the uploaded file
        with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
            with st.spinner("Processing uploaded file..."):
                tmp_file.write(uploaded_file.getvalue())
                tmp_file_path = tmp_file.name
        
        # Preserve the original filename
        original_filename = uploaded_file.name
        
        file_size_mb = os.path.getsize(tmp_file_path) / (1024 * 1024)
        
        st.write(f"Uploaded file: {original_filename}")
        st.write(f"File size: {file_size_mb:.2f} MB")
        
        if st.button("Split File"):
            if file_size_mb <= max_chunk_size:
                st.warning(f"The file is already smaller than {max_chunk_size}MB. No need to split.")
            else:
                start_time = time.time()
                with st.spinner(f"Splitting {original_filename} into chunks..."):
                    output_files = split_pdf_fast(tmp_file_path, max_chunk_size)
                end_time = time.time()
                
                if output_files:
                    processing_time = end_time - start_time
                    st.success(f"Successfully split into {len(output_files)} files in {processing_time:.2f} seconds!")
                    
                    # Show file size distribution
                    st.write("### Generated Files:")
                    for file_info in output_files:
                        col1, col2 = st.columns([3, 1])
                        with col1:
                            st.write(f"**{file_info['filename']}** ({file_info['size_mb']:.2f} MB, {file_info['pages']} pages)")
                        with col2:
                            with open(file_info['path'], 'rb') as f:
                                st.download_button(
                                    label=f"Download",
                                    data=f.read(),
                                    file_name=file_info['filename'],
                                    mime="application/pdf"
                                )
                else:
                    st.error("Error splitting the file.")
        
        # Clean up the temporary file after processing
        os.unlink(tmp_file_path)

if __name__ == "__main__":
    main()     in this it is not making pdfs of 100mb tmpui2brstt(1).pdf (48.31 MB, 325 pages)


tmpui2brstt(2).pdf (184.57 MB, 325 pages)


tmpui2brstt(3).pdf (38.57 MB, 323 pages)    i wanted pdf to be splitted into max 100mb and split into as minimum no of pdfs as possible like for 220 ..make 100 , 100, 20 mb three pdfs ...and also name them like uploaded_pdf_name (1) (2) (3) qnd so on