the bulk mode should also combind the segments that it creates like the single video thing. right now its not implementet right?:
# app.py

import os
import sys
import random
import threading
from pathlib import Path
from datetime import datetime
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox

# Import functions from existing scripts
from text_generation2 import generate_would_you_rather, summarize_text
from image_generation import ComfyUIGenerator
from voice_generation import generate_tts
from moviepy.editor import (
    AudioFileClip,
    concatenate_videoclips,
    VideoFileClip  # Ensure VideoFileClip is imported
)

# Import the video generator class
from video_generation4 import WouldYouRatherGenerator  # Ensure the file is named correctly

def debug_print(message, log_widget=None):
    print(f"[DEBUG] {message}")
    if log_widget:
        log_widget.configure(state='normal')
        log_widget.insert(tk.END, f"[DEBUG] {message}\n")
        log_widget.configure(state='disabled')
        log_widget.see(tk.END)

def parse_would_you_rather_text(file_path, log_widget=None):
    """
    Parses the 'would_you_rather.txt' file to extract choices and image descriptions.
    Designed to handle minor deviations in formatting.

    Expected block structure for each pair:
    1.
    CHOICE: First choice description
    IMAGE: First image description
    VERSUS
    CHOICE: Second choice description
    IMAGE: Second image description
    """
    pairs = []
    with open(file_path, 'r', encoding='utf-8') as f:
        lines = [line.strip() for line in f if line.strip()]  # Remove empty lines

    i = 0
    total_lines = len(lines)
    pair_number = 1
    while i < total_lines:
        line = lines[i]
        if line.endswith('.'):
            debug_print(f"Parsing pair {pair_number} starting at line {i+1}", log_widget)
            pair = {}
            j = i + 1  # Start parsing after the number line

            # Initialize flags to check if essential components are found
            choice1_found = False
            image1_found = False
            versus_found = False
            choice2_found = False
            image2_found = False

            while j < total_lines and not (lines[j].endswith('.') and lines[j].rstrip('.').isdigit()):
                current_line = lines[j].upper()
                if current_line.startswith('CHOICE:'):
                    if not choice1_found:
                        pair['option1'] = lines[j][len('CHOICE:'):].strip()
                        choice1_found = True
                        debug_print(f"Pair {pair_number} - Option 1: {pair['option1']}", log_widget)
                    elif not choice2_found:
                        pair['option2'] = lines[j][len('CHOICE:'):].strip()
                        choice2_found = True
                        debug_print(f"Pair {pair_number} - Option 2: {pair['option2']}", log_widget)
                elif current_line.startswith('IMAGE:'):
                    if choice1_found and not image1_found:
                        pair['image1_desc'] = lines[j][len('IMAGE:'):].strip()
                        image1_found = True
                        debug_print(f"Pair {pair_number} - Image 1: {pair['image1_desc']}", log_widget)
                    elif choice2_found and not image2_found:
                        pair['image2_desc'] = lines[j][len('IMAGE:'):].strip()
                        image2_found = True
                        debug_print(f"Pair {pair_number} - Image 2: {pair['image2_desc']}", log_widget)
                elif current_line == 'VERSUS':
                    versus_found = True
                    debug_print(f"Pair {pair_number} - Versus found", log_widget)
                else:
                    debug_print(f"Pair {pair_number} - Unrecognized line: '{lines[j]}'", log_widget)
                j += 1

            # Validate if all components are found
            if choice1_found and image1_found and versus_found and choice2_found and image2_found:
                pairs.append(pair)
                debug_print(f"Successfully parsed pair {pair_number}", log_widget)
                pair_number += 1
            else:
                missing = []
                if not choice1_found:
                    missing.append("Option 1 Choice")
                if not image1_found:
                    missing.append("Option 1 Image")
                if not versus_found:
                    missing.append("'VERSUS'")
                if not choice2_found:
                    missing.append("Option 2 Choice")
                if not image2_found:
                    missing.append("Option 2 Image")
                debug_print(f"Pair {pair_number} incomplete. Missing: {', '.join(missing)}. Skipping this pair.", log_widget)
            i = j  # Move to the next pair
        else:
            debug_print(f"Unexpected line format at line {i+1}: '{line}'. Skipping.", log_widget)
            i += 1
    return pairs

def run_generation(mode, mode_prompt, number_of_pairs, log_widget=None):
    """
    Runs the entire generation process.

    Args:
        mode (str): Selected mode.
        mode_prompt (str): Custom prompt based on mode.
        number_of_pairs (int): Number of pairs to generate.
        log_widget (ScrolledText): GUI widget to display logs.
    """
    try:
        debug_print("Starting Would You Rather Generator Process", log_widget)

        # Step 1: Generate 'Would You Rather' text
        debug_print("Generating Would You Rather pairs...", log_widget)
        generated_text = generate_would_you_rather(mode_prompt, number_of_pairs)
        if not generated_text:
            debug_print("Failed to generate Would You Rather pairs.", log_widget)
            messagebox.showerror("Error", "Failed to generate Would You Rather pairs.")
            return

        # Define the project output directories
        project_output_dir = Path('generated_assets')
        images_dir = project_output_dir / 'images'
        audio_dir = project_output_dir / 'audio'
        videos_dir = project_output_dir / 'videos'
        final_video_dir = project_output_dir / 'final_video'
        sounds_dir = project_output_dir / 'sounds'  # Directory for sound effects

        # Ensure directories exist
        images_dir.mkdir(parents=True, exist_ok=True)
        audio_dir.mkdir(parents=True, exist_ok=True)
        videos_dir.mkdir(parents=True, exist_ok=True)
        final_video_dir.mkdir(parents=True, exist_ok=True)
        sounds_dir.mkdir(parents=True, exist_ok=True)

        # Save generated text to file
        wr_file = project_output_dir / 'would_you_rather.txt'
        with open(wr_file, 'w', encoding='utf-8') as f:
            f.write(generated_text)
        debug_print(f"Generated text saved to {wr_file.resolve()}", log_widget)

        # Paths to sound effects
        clock_sound_path = sounds_dir / 'clock.mp3'
        bling_sound_path = sounds_dir / 'bling.mp3'

        # Verify that sound effects exist
        if not clock_sound_path.exists():
            debug_print(f"Error: '{clock_sound_path}' does not exist. Please ensure the file is present.", log_widget)
            messagebox.showerror("Error", f"'{clock_sound_path}' does not exist. Please ensure the file is present.")
            return
        if not bling_sound_path.exists():
            debug_print(f"Error: '{bling_sound_path}' does not exist. Please ensure the file is present.", log_widget)
            messagebox.showerror("Error", f"'{bling_sound_path}' does not exist. Please ensure the file is present.")
            return

        # Step 2: Parse the generated text
        pairs = parse_would_you_rather_text(wr_file, log_widget)
        debug_print(f"Parsed {len(pairs)} Would You Rather pairs.", log_widget)

        if not pairs:
            debug_print("No valid pairs found. Exiting.", log_widget)
            messagebox.showerror("Error", "No valid pairs found.")
            return

        # Initialize image generator
        image_generator = ComfyUIGenerator()

        # Initialize list to hold all generated assets
        asset_list = []

        # Step 3: Generate images and audio for each pair
        for idx, pair in enumerate(pairs, start=1):
            debug_print(f"Processing pair {idx}: {pair['option1']} vs {pair['option2']}", log_widget)

            # Generate images for Option 1
            debug_print(f"Generating image for Option 1: {pair['image1_desc']}", log_widget)
            image1_paths = image_generator.generate_image(
                workflow_path="workflow.json",
                prompt_text=pair['image1_desc'],
                seed=random.randint(100000000, 999999999),  # Generate a unique seed
                node_id='CLIPTextEncode',
                index=0,
                output_dir=images_dir
            )
            if not image1_paths:
                debug_print(f"Failed to generate image for Option 1: {pair['option1']}", log_widget)
                continue
            # Assuming one image per prompt
            img1_filename = Path(image1_paths[0]).name
            img1_path = images_dir / img1_filename
            debug_print(f"Image for Option 1 saved as {img1_path}", log_widget)

            # Generate images for Option 2
            debug_print(f"Generating image for Option 2: {pair['image2_desc']}", log_widget)
            image2_paths = image_generator.generate_image(
                workflow_path="workflow.json",
                prompt_text=pair['image2_desc'],
                seed=random.randint(100000000, 999999999),  # Generate a unique seed
                node_id='CLIPTextEncode',
                index=0,
                output_dir=images_dir
            )
            if not image2_paths:
                debug_print(f"Failed to generate image for Option 2: {pair['option2']}", log_widget)
                continue
            # Assuming one image per prompt
            img2_filename = Path(image2_paths[0]).name
            img2_path = images_dir / img2_filename
            debug_print(f"Image for Option 2 saved as {img2_path}", log_widget)

            # Generate summaries for both options
            summary1 = summarize_text(pair['option1'])
            summary2 = summarize_text(pair['option2'])
            debug_print(f"Summary for Option 1: {summary1}", log_widget)
            debug_print(f"Summary for Option 2: {summary2}", log_widget)

            # Generate TTS audio for Option 1 with summary
            audio1_text = pair['option1']
            debug_print(f"Generating audio for Option 1: {audio1_text}", log_widget)
            audio1_path = generate_tts(text=audio1_text, output_dir=str(audio_dir))
            if not audio1_path:
                debug_print(f"Failed to generate audio for Option 1: {audio1_text}", log_widget)
                continue
            debug_print(f"Audio for Option 1 saved as {audio1_path}", log_widget)

            # Generate TTS audio for Option 2 with summary
            audio2_text = "or " + pair['option2']
            debug_print(f"Generating audio for Option 2: {audio2_text}", log_widget)
            audio2_path = generate_tts(text=audio2_text, output_dir=str(audio_dir))
            if not audio2_path:
                debug_print(f"Failed to generate audio for Option 2: {audio2_text}", log_widget)
                continue
            debug_print(f"Audio for Option 2 saved as {audio2_path}", log_widget)

            # Append to asset list
            asset = {
                'option1_text': summary1,   # Use summary for text in video
                'option2_text': summary2,
                'image1_path': str(img1_path.resolve()),
                'image2_path': str(img2_path.resolve()),
                'audio1_path': audio1_path,
                'audio2_path': audio2_path
            }
            asset_list.append(asset)

        if not asset_list:
            debug_print("No assets were generated. Exiting.", log_widget)
            messagebox.showerror("Error", "No assets were generated.")
            return

        # Initialize the video generator
        video_generator = WouldYouRatherGenerator()

        for idx, asset in enumerate(asset_list, start=1):
            # Define timings (customize as needed)
            initial_pause = 0  # No initial pause since audio1 starts immediately
            timer_delay = 1     # 1 second after audio1 for starting audio2
            countdown_wait = 1  # 1 second after audio2 before countdown

            # Load audio clips to determine durations
            debug_print(f"Loading audio files for pair {idx}", log_widget)
            try:
                audio1_clip = AudioFileClip(asset['audio1_path'])
                audio2_clip = AudioFileClip(asset['audio2_path'])
            except Exception as e:
                debug_print(f"Error loading audio files for pair {idx}: {str(e)}", log_widget)
                continue

            # Calculate timings based on audio lengths
            audio1_duration = audio1_clip.duration
            audio2_duration = audio2_clip.duration

            # Define countdown_seconds based on the actual requirement (fixed to 3 seconds)
            countdown_seconds = 3

            # Generate random percentages
            percent1_num = random.randint(0, 100)
            percent2_num = 100 - percent1_num

            # Turn the percentage int into a string and add % sign
            percent1 = f"{percent1_num}%"
            percent2 = f"{percent2_num}%"

            # Generate unique output filename
            output_filename = videos_dir / f"would_you_rather_pair_{idx}.mp4"

            # Paths to sound effects (already verified existence in app.py)
            clock_sound_path = Path('generated_assets/sounds/clock.mp3').resolve()
            bling_sound_path = Path('generated_assets/sounds/bling.mp3').resolve()

            debug_print(f"Generating video for pair {idx}: {asset['option1_text']} vs {asset['option2_text']}", log_widget)
            video_generator.generate_video(
                option1_text=asset['option1_text'],
                option2_text=asset['option2_text'],
                image1_path=asset['image1_path'],
                image2_path=asset['image2_path'],
                audio1_path=asset['audio1_path'],
                audio2_path=asset['audio2_path'],
                percent1=percent1,
                percent2=percent2,
                initial_pause=initial_pause,
                timer_delay=timer_delay,
                countdown_wait=countdown_wait,
                countdown_seconds=countdown_seconds,
                output_filename=str(output_filename),
                clock_sound_path=str(clock_sound_path),  # Pass clock sound path
                bling_sound_path=str(bling_sound_path)   # Pass bling sound path
            )
            debug_print(f"Video for pair {idx} generated successfully: {output_filename}", log_widget)

            # Close audio clips to release resources
            audio1_clip.close()
            audio2_clip.close()

        debug_print("All individual videos have been generated successfully.", log_widget)

        # Step 5: Combine all individual videos into a final video
        debug_print("Combining all individual videos into a final video...", log_widget)

        try:
            video_files = sorted(videos_dir.glob("would_you_rather_pair_*.mp4"))
            if not video_files:
                debug_print("No video files found to combine.", log_widget)
                messagebox.showerror("Error", "No video files found to combine.")
                return

            video_clips = [VideoFileClip(str(video)) for video in video_files]
            final_video = concatenate_videoclips(video_clips, method="compose")

            # Define the final output path
            final_output_path = final_video_dir / "would_you_rather_final.mp4"

            # Write the final video file
            final_video.write_videofile(
                str(final_output_path),
                fps=30,
                codec="libx264",
                audio_codec="aac",
                threads=4,
                preset="medium",
                remove_temp=True,
                logger=None  # Suppress MoviePy logs if desired
            )
            debug_print(f"Final combined video saved as: {final_output_path}", log_widget)

            # Close video clips to release resources
            for clip in video_clips:
                clip.close()
            final_video.close()

        except Exception as e:
            debug_print(f"Failed to combine videos: {str(e)}", log_widget)
            messagebox.showerror("Error", f"Failed to combine videos: {str(e)}")
            return

        debug_print("All videos have been combined into the final video successfully.", log_widget)
        messagebox.showinfo("Success", "Video generation completed successfully!")

    except Exception as e:
        debug_print(f"Error: {str(e)}", log_widget)
        messagebox.showerror("Error", f"An error occurred while generating the video: {str(e)}")

def run_bulk_generation(mode, mode_prompt, number_of_pairs, number_of_videos, log_widget=None):
    """
    Runs the bulk generation process.

    Args:
        mode (str): Selected mode.
        mode_prompt (str): Custom prompt based on mode.
        number_of_pairs (int): Number of pairs per video.
        number_of_videos (int): Number of videos to generate.
        log_widget (ScrolledText): GUI widget to display logs.
    """
    try:
        debug_print("Starting Bulk Video Generation Process", log_widget)
        project_output_dir = Path('generated_assets')
        videos_dir = project_output_dir / 'videos_bulk'
        videos_dir.mkdir(parents=True, exist_ok=True)

        # Define the project output directories
        images_dir = project_output_dir / 'images_bulk'
        audio_dir = project_output_dir / 'audio_bulk'
        final_video_dir = project_output_dir / 'final_video_bulk'
        sounds_dir = project_output_dir / 'sounds'  # Directory for sound effects

        # Ensure directories exist
        images_dir.mkdir(parents=True, exist_ok=True)
        audio_dir.mkdir(parents=True, exist_ok=True)
        final_video_dir.mkdir(parents=True, exist_ok=True)
        sounds_dir.mkdir(parents=True, exist_ok=True)

        # Paths to sound effects
        clock_sound_path = sounds_dir / 'clock.mp3'
        bling_sound_path = sounds_dir / 'bling.mp3'

        # Verify that sound effects exist
        if not clock_sound_path.exists():
            debug_print(f"Error: '{clock_sound_path}' does not exist. Please ensure the file is present.", log_widget)
            messagebox.showerror("Error", f"'{clock_sound_path}' does not exist. Please ensure the file is present.")
            return
        if not bling_sound_path.exists():
            debug_print(f"Error: '{bling_sound_path}' does not exist. Please ensure the file is present.", log_widget)
            messagebox.showerror("Error", f"'{bling_sound_path}' does not exist. Please ensure the file is present.")
            return

        # Initialize image generator
        image_generator = ComfyUIGenerator()

        # Initialize the video generator
        video_generator = WouldYouRatherGenerator()

        for vid in range(1, number_of_videos + 1):
            debug_print(f"Generating video {vid}/{number_of_videos}", log_widget)

            # Step 1: Generate 'Would You Rather' text
            debug_print(f"Generating Would You Rather pairs for video {vid}...", log_widget)
            generated_text = generate_would_you_rather(mode_prompt, number_of_pairs)
            if not generated_text:
                debug_print(f"Failed to generate Would You Rather pairs for video {vid}. Skipping.", log_widget)
                continue

            # Save generated text to file
            wr_file = project_output_dir / f'would_you_rather_{vid}.txt'
            with open(wr_file, 'w', encoding='utf-8') as f:
                f.write(generated_text)
            debug_print(f"Generated text saved to {wr_file.resolve()}", log_widget)

            # Step 2: Parse the generated text
            pairs = parse_would_you_rather_text(wr_file, log_widget)
            debug_print(f"Parsed {len(pairs)} Would You Rather pairs for video {vid}.", log_widget)

            if not pairs:
                debug_print(f"No valid pairs found for video {vid}. Skipping.", log_widget)
                continue

            # Initialize list to hold all generated assets for this video
            asset_list = []

            # Step 3: Generate images and audio for each pair
            for idx, pair in enumerate(pairs, start=1):
                debug_print(f"Processing pair {idx}: {pair['option1']} vs {pair['option2']}", log_widget)

                # Generate images for Option 1
                debug_print(f"Generating image for Option 1: {pair['image1_desc']}", log_widget)
                image1_paths = image_generator.generate_image(
                    workflow_path="workflow.json",
                    prompt_text=pair['image1_desc'],
                    seed=random.randint(100000000, 999999999),  # Generate a unique seed
                    node_id='CLIPTextEncode',
                    index=0,
                    output_dir=images_dir
                )
                if not image1_paths:
                    debug_print(f"Failed to generate image for Option 1: {pair['option1']}. Skipping pair.", log_widget)
                    continue
                # Assuming one image per prompt
                img1_filename = Path(image1_paths[0]).name
                img1_path = images_dir / img1_filename
                debug_print(f"Image for Option 1 saved as {img1_path}", log_widget)

                # Generate images for Option 2
                debug_print(f"Generating image for Option 2: {pair['image2_desc']}", log_widget)
                image2_paths = image_generator.generate_image(
                    workflow_path="workflow.json",
                    prompt_text=pair['image2_desc'],
                    seed=random.randint(100000000, 999999999),  # Generate a unique seed
                    node_id='CLIPTextEncode',
                    index=0,
                    output_dir=images_dir
                )
                if not image2_paths:
                    debug_print(f"Failed to generate image for Option 2: {pair['option2']}. Skipping pair.", log_widget)
                    continue
                # Assuming one image per prompt
                img2_filename = Path(image2_paths[0]).name
                img2_path = images_dir / img2_filename
                debug_print(f"Image for Option 2 saved as {img2_path}", log_widget)

                # Generate summaries for both options
                summary1 = summarize_text(pair['option1'])
                summary2 = summarize_text(pair['option2'])
                debug_print(f"Summary for Option 1: {summary1}", log_widget)
                debug_print(f"Summary for Option 2: {summary2}", log_widget)

                # Generate TTS audio for Option 1 with summary
                audio1_text = pair['option1']
                debug_print(f"Generating audio for Option 1: {audio1_text}", log_widget)
                audio1_path = generate_tts(text=audio1_text, output_dir=str(audio_dir))
                if not audio1_path:
                    debug_print(f"Failed to generate audio for Option 1: {audio1_text}. Skipping pair.", log_widget)
                    continue
                debug_print(f"Audio for Option 1 saved as {audio1_path}", log_widget)

                # Generate TTS audio for Option 2 with summary
                audio2_text = "or " + pair['option2']
                debug_print(f"Generating audio for Option 2: {audio2_text}", log_widget)
                audio2_path = generate_tts(text=audio2_text, output_dir=str(audio_dir))
                if not audio2_path:
                    debug_print(f"Failed to generate audio for Option 2: {audio2_text}. Skipping pair.", log_widget)
                    continue
                debug_print(f"Audio for Option 2 saved as {audio2_path}", log_widget)

                # Append to asset list
                asset = {
                    'option1_text': summary1,   # Use summary for text in video
                    'option2_text': summary2,
                    'image1_path': str(img1_path.resolve()),
                    'image2_path': str(img2_path.resolve()),
                    'audio1_path': audio1_path,
                    'audio2_path': audio2_path
                }
                asset_list.append(asset)

            if not asset_list:
                debug_print(f"No assets were generated for video {vid}. Skipping.", log_widget)
                continue

            # Step 4: Assemble all assets into individual videos
            debug_print(f"Assembling individual videos for bulk video {vid}...", log_widget)

            for idx, asset in enumerate(asset_list, start=1):
                # Define timings (customize as needed)
                initial_pause = 0  # No initial pause since audio1 starts immediately
                timer_delay = 1     # 1 second after audio1 for starting audio2
                countdown_wait = 1  # 1 second after audio2 before countdown

                # Load audio clips to determine durations
                debug_print(f"Loading audio files for pair {idx} in video {vid}", log_widget)
                try:
                    audio1_clip = AudioFileClip(asset['audio1_path'])
                    audio2_clip = AudioFileClip(asset['audio2_path'])
                except Exception as e:
                    debug_print(f"Error loading audio files for pair {idx} in video {vid}: {str(e)}", log_widget)
                    continue

                # Calculate timings based on audio lengths
                audio1_duration = audio1_clip.duration
                audio2_duration = audio2_clip.duration

                # Define countdown_seconds based on the actual requirement (fixed to 3 seconds)
                countdown_seconds = 3

                # Generate random percentages
                percent1_num = random.randint(0, 100)
                percent2_num = 100 - percent1_num

                # Turn the percentage int into a string and add % sign
                percent1 = f"{percent1_num}%"
                percent2 = f"{percent2_num}%"

                # Generate timestamped output filename
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                output_filename = videos_dir / f"would_you_rather_{timestamp}_pair_{idx}.mp4"

                # Paths to sound effects (already verified existence in bulk generation)
                clock_sound_path = Path('generated_assets/sounds/clock.mp3').resolve()
                bling_sound_path = Path('generated_assets/sounds/bling.mp3').resolve()

                debug_print(f"Generating video {idx} for bulk video {vid}: {asset['option1_text']} vs {asset['option2_text']}", log_widget)
                video_generator.generate_video(
                    option1_text=asset['option1_text'],
                    option2_text=asset['option2_text'],
                    image1_path=asset['image1_path'],
                    image2_path=asset['image2_path'],
                    audio1_path=asset['audio1_path'],
                    audio2_path=asset['audio2_path'],
                    percent1=percent1,
                    percent2=percent2,
                    initial_pause=initial_pause,
                    timer_delay=timer_delay,
                    countdown_wait=countdown_wait,
                    countdown_seconds=countdown_seconds,
                    output_filename=str(output_filename),
                    clock_sound_path=str(clock_sound_path),  # Pass clock sound path
                    bling_sound_path=str(bling_sound_path)   # Pass bling sound path
                )
                debug_print(f"Video {idx} for bulk video {vid} generated successfully: {output_filename}", log_widget)

                # Close audio clips to release resources
                audio1_clip.close()
                audio2_clip.close()

            debug_print(f"Bulk video {vid} generated successfully.", log_widget)

        debug_print("All bulk videos have been generated successfully.", log_widget)
        messagebox.showinfo("Success", f"{number_of_videos} Videos generated successfully!")

    except Exception as e:
        debug_print(f"Error generating bulk videos: {str(e)}", log_widget)

def start_generation(mode, mode_prompt, number_of_pairs, log_widget):
    """
    Starts the single generation process in a separate thread to keep the GUI responsive.
    """
    generation_thread = threading.Thread(target=run_generation, args=(mode, mode_prompt, number_of_pairs, log_widget))
    generation_thread.start()

def start_bulk_generation(mode, mode_prompt, number_of_pairs, number_of_videos, log_widget):
    """
    Starts the bulk generation process in a separate thread to keep the GUI responsive.
    """
    bulk_thread = threading.Thread(target=run_bulk_generation, args=(mode, mode_prompt, number_of_pairs, number_of_videos, log_widget))
    bulk_thread.start()

def create_gui():
    """
    Creates the Tkinter GUI with Single and Bulk generation tabs.
    """
    root = tk.Tk()
    root.title("Would You Rather Video Generator")
    root.geometry("900x700")
    root.resizable(False, False)

    # Create main frame
    main_frame = ttk.Frame(root, padding="10")
    main_frame.pack(fill=tk.BOTH, expand=True)

    # Create Notebook (Tabbed Interface)
    notebook = ttk.Notebook(main_frame)
    notebook.pack(fill=tk.BOTH, expand=True)

    # ======================= Single Generation Tab =======================
    single_tab = ttk.Frame(notebook)
    notebook.add(single_tab, text="Single Generation")

    # Mode selection
    single_mode_label = ttk.Label(single_tab, text="Select Mode:")
    single_mode_label.grid(column=0, row=0, sticky=tk.W, pady=5, padx=5)

    mode_options = ["Random", "Food", "Ability", "Travel", "Technology"]
    single_mode_var = tk.StringVar(value=mode_options[0])

    single_mode_dropdown = ttk.Combobox(single_tab, textvariable=single_mode_var, values=mode_options, state="readonly")
    single_mode_dropdown.grid(column=1, row=0, sticky=tk.W, pady=5, padx=5)

    # Prompt customization
    single_prompt_label = ttk.Label(single_tab, text="Customize Prompt:")
    single_prompt_label.grid(column=0, row=1, sticky=tk.NW, pady=5, padx=5)

    single_prompt_text = tk.Text(single_tab, width=60, height=5)
    single_prompt_text.grid(column=1, row=1, sticky=tk.W, pady=5, padx=5)
    single_prompt_text.insert(tk.END, "Be super creative in the Would you rather choices.")

    # Number of pairs
    single_number_label = ttk.Label(single_tab, text="Number of Pairs:")
    single_number_label.grid(column=0, row=2, sticky=tk.W, pady=5, padx=5)

    single_number_var = tk.IntVar(value=4)
    single_number_spinbox = ttk.Spinbox(single_tab, from_=1, to=20, textvariable=single_number_var, width=5)
    single_number_spinbox.grid(column=1, row=2, sticky=tk.W, pady=5, padx=5)

    # Start button
    single_start_button = ttk.Button(single_tab, text="Generate Video", command=lambda: start_generation(
        single_mode_var.get(),
        single_prompt_text.get("1.0", tk.END).strip(),
        single_number_var.get(),
        single_log_widget
    ))
    single_start_button.grid(column=1, row=3, sticky=tk.W, pady=10, padx=5)

    # Log area
    single_log_label = ttk.Label(single_tab, text="Logs:")
    single_log_label.grid(column=0, row=4, sticky=tk.W, pady=5, padx=5)

    single_log_widget = scrolledtext.ScrolledText(single_tab, width=95, height=15, state='disabled')
    single_log_widget.grid(column=0, row=5, columnspan=3, pady=5, padx=5)

    # Bind mode selection to update prompt (if needed)
    def single_update_prompt(event):
        selected_mode = single_mode_var.get()
        default_prompts = {
            "Random": "Be super creative in the Would you rather choices.",
            "Food": "Focus on unique and interesting food-related choices.",
            "Ability": "Emphasize on extraordinary and fun ability choices.",
            "Travel": "Create travel-themed choices with exciting destinations.",
            "Technology": "Incorporate tech-centric and futuristic choices."
        }
        single_prompt_text.delete("1.0", tk.END)
        single_prompt_text.insert(tk.END, default_prompts.get(selected_mode, "Be super creative in the Would you rather choices."))

    single_mode_dropdown.bind("<<ComboboxSelected>>", single_update_prompt)

    # ======================= Bulk Generation Tab =======================
    bulk_tab = ttk.Frame(notebook)
    notebook.add(bulk_tab, text="Bulk Generation")

    # Mode selection
    bulk_mode_label = ttk.Label(bulk_tab, text="Select Mode:")
    bulk_mode_label.grid(column=0, row=0, sticky=tk.W, pady=5, padx=5)

    bulk_mode_var = tk.StringVar(value=mode_options[0])

    bulk_mode_dropdown = ttk.Combobox(bulk_tab, textvariable=bulk_mode_var, values=mode_options, state="readonly")
    bulk_mode_dropdown.grid(column=1, row=0, sticky=tk.W, pady=5, padx=5)

    # Prompt customization
    bulk_prompt_label = ttk.Label(bulk_tab, text="Customize Prompt:")
    bulk_prompt_label.grid(column=0, row=1, sticky=tk.NW, pady=5, padx=5)

    bulk_prompt_text = tk.Text(bulk_tab, width=60, height=5)
    bulk_prompt_text.grid(column=1, row=1, sticky=tk.W, pady=5, padx=5)
    bulk_prompt_text.insert(tk.END, "Be super creative in the Would you rather choices.")

    # Number of pairs per video
    bulk_number_label = ttk.Label(bulk_tab, text="Number of Pairs per Video:")
    bulk_number_label.grid(column=0, row=2, sticky=tk.W, pady=5, padx=5)

    bulk_number_var = tk.IntVar(value=4)
    bulk_number_spinbox = ttk.Spinbox(bulk_tab, from_=1, to=20, textvariable=bulk_number_var, width=5)
    bulk_number_spinbox.grid(column=1, row=2, sticky=tk.W, pady=5, padx=5)

    # Number of videos
    bulk_videos_label = ttk.Label(bulk_tab, text="Number of Videos:")
    bulk_videos_label.grid(column=0, row=3, sticky=tk.W, pady=5, padx=5)

    bulk_videos_var = tk.IntVar(value=1)
    bulk_videos_spinbox = ttk.Spinbox(bulk_tab, from_=1, to=100, textvariable=bulk_videos_var, width=5)
    bulk_videos_spinbox.grid(column=1, row=3, sticky=tk.W, pady=5, padx=5)

    # Start Bulk button
    bulk_start_button = ttk.Button(bulk_tab, text="Generate Bulk Videos", command=lambda: start_bulk_generation(
        bulk_mode_var.get(),
        bulk_prompt_text.get("1.0", tk.END).strip(),
        bulk_number_var.get(),
        bulk_videos_var.get(),
        bulk_log_widget
    ))
    bulk_start_button.grid(column=1, row=4, sticky=tk.W, pady=10, padx=5)

    # Log area
    bulk_log_label = ttk.Label(bulk_tab, text="Logs:")
    bulk_log_label.grid(column=0, row=5, sticky=tk.W, pady=5, padx=5)

    bulk_log_widget = scrolledtext.ScrolledText(bulk_tab, width=95, height=25, state='disabled')
    bulk_log_widget.grid(column=0, row=6, columnspan=3, pady=5, padx=5)

    # Bind mode selection to update prompt (if needed)
    def bulk_update_prompt(event):
        selected_mode = bulk_mode_var.get()
        default_prompts = {
            "Random": "Be super creative in the Would you rather choices.",
            "Food": "Focus on unique and interesting food-related choices.",
            "Ability": "Emphasize on extraordinary and fun ability choices.",
            "Travel": "Create travel-themed choices with exciting destinations.",
            "Technology": "Incorporate tech-centric and futuristic choices."
        }
        bulk_prompt_text.delete("1.0", tk.END)
        bulk_prompt_text.insert(tk.END, default_prompts.get(selected_mode, "Be super creative in the Would you rather choices."))

    bulk_mode_dropdown.bind("<<ComboboxSelected>>", bulk_update_prompt)

    root.mainloop()

if __name__ == "__main__":
    create_gui()