"""
Audio processing module for downloading YouTube audio using PyAV.
No external ffmpeg installation required - PyAV includes FFmpeg bindings.
"""

import subprocess
import tempfile
import os
import av


def split_audio_into_chunks(input_path, chunk_duration_seconds=600):
    """
    Splits audio file into chunks of specified duration using PyAV.
    Default is 600 seconds (10 minutes).
    
    Args:
        input_path (str): Path to input audio file
        chunk_duration_seconds (int): Duration of each chunk in seconds (default: 600 = 10 minutes)
        
    Returns:
        list: List of paths to chunk files
    """
    try:
        print(f"Splitting audio into {chunk_duration_seconds // 60}-minute chunks...")
        
        # Open input container
        input_container = av.open(input_path)
        audio_stream = input_container.streams.audio[0]
        
        # Get audio duration
        duration = float(input_container.duration) / av.time_base if input_container.duration else 0
        print(f"Total audio duration: {duration / 60:.1f} minutes")
        
        chunk_paths = []
        chunk_index = 0
        start_time = 0
        
        temp_dir = tempfile.gettempdir()
        
        while start_time < duration:
            end_time = min(start_time + chunk_duration_seconds, duration)
            chunk_path = os.path.join(temp_dir, f"audio_chunk_{chunk_index}.mp3")
            
            print(f"Creating chunk {chunk_index + 1}: {start_time / 60:.1f}-{end_time / 60:.1f} minutes")
            
            # Seek to start time
            input_container.seek(int(start_time * av.time_base))
            
            # Create output container for this chunk
            output_container = av.open(chunk_path, 'w')
            output_stream = output_container.add_stream('mp3', rate=44100)
            
            # Process frames for this chunk
            for frame in input_container.decode(audio_stream):
                if frame.time is None:
                    continue
                    
                frame_time = float(frame.time)
                
                if frame_time < start_time:
                    continue
                if frame_time >= end_time:
                    break
                
                frame.pts = None
                for packet in output_stream.encode(frame):
                    output_container.mux(packet)
            
            # Flush remaining packets
            for packet in output_stream.encode():
                output_container.mux(packet)
            
            output_container.close()
            chunk_paths.append(chunk_path)
            
            chunk_index += 1
            start_time = end_time
            
            # Reopen container for next iteration
            if start_time < duration:
                input_container.close()
                input_container = av.open(input_path)
                audio_stream = input_container.streams.audio[0]
        
        input_container.close()
        print(f"Created {len(chunk_paths)} audio chunks")
        return chunk_paths
        
    except Exception as e:
        raise RuntimeError(f"Error splitting audio with PyAV: {e}")


def convert_to_mp3_with_pyav(input_path, output_path):
    """
    Converts audio file to MP3 using PyAV.
    
    Args:
        input_path (str): Path to input audio file
        output_path (str): Path to output MP3 file
    """
    try:
        # Open input container
        input_container = av.open(input_path)
        
        # Open output container for MP3
        output_container = av.open(output_path, 'w')
        
        # Get the first audio stream
        input_stream = input_container.streams.audio[0]
        
        # Create output audio stream with MP3 codec
        output_stream = output_container.add_stream('mp3', rate=44100)
        
        # Process audio frames
        for frame in input_container.decode(input_stream):
            # Resample if necessary
            frame.pts = None
            for packet in output_stream.encode(frame):
                output_container.mux(packet)
        
        # Flush remaining packets
        for packet in output_stream.encode():
            output_container.mux(packet)
        
        # Close containers
        input_container.close()
        output_container.close()
        
        print(f"Audio converted to MP3: {output_path}")
    except Exception as e:
        raise RuntimeError(f"Error converting audio with PyAV: {e}")


def download_youtube_audio(video_url, output_path=None):
    """
    Downloads audio from a YouTube video and converts to MP3 using PyAV.
    No external ffmpeg installation required.
    
    Args:
        video_url (str): YouTube video URL
        output_path (str, optional): Path to save the audio file. 
                                     If None, uses a temporary file.
        
    Returns:
        str: Path to the downloaded audio file
    """
    print(f"Starting audio download from: {video_url}")
    
    if output_path is None:
        # Create a temporary file for the audio
        temp_dir = tempfile.gettempdir()
        output_path = os.path.join(temp_dir, "youtube_audio.mp3")
    
    print(f"Target output path: {output_path}")
    
    # Download audio without conversion first (yt-dlp will get best available format)
    temp_download = os.path.join(tempfile.gettempdir(), "youtube_audio_raw")
    
    command = [
        "yt-dlp",
        "-f", "bestaudio",
        "--no-playlist",
        "-o", temp_download,
        video_url
    ]
    
    print(f"Running command: {' '.join(command)}")
    
    try:
        print("Downloading audio from YouTube...")
        result = subprocess.run(command, check=True, capture_output=True, text=True)
        print("Download completed!")
        
        # Find the actual downloaded file (yt-dlp adds extension)
        downloaded_file = None
        for ext in ['.m4a', '.webm', '.opus', '.mp4', '.mp3', '.ogg']:
            candidate = temp_download + ext
            if os.path.exists(candidate):
                downloaded_file = candidate
                print(f"Found downloaded file: {downloaded_file}")
                break
        
        if not downloaded_file:
            # Try without extension
            if os.path.exists(temp_download):
                downloaded_file = temp_download
                print(f"Found downloaded file (no ext): {downloaded_file}")
            else:
                raise FileNotFoundError("Could not find downloaded audio file")
        
        print(f"Downloaded: {downloaded_file}")
        
        # Convert to MP3 using PyAV if not already MP3
        if not downloaded_file.endswith('.mp3'):
            print("Converting audio to MP3 using PyAV...")
            convert_to_mp3_with_pyav(downloaded_file, output_path)
            # Clean up the temporary download
            os.remove(downloaded_file)
            print("Conversion complete, temporary file removed")
        else:
            # Just rename if already MP3
            print("Already in MP3 format, renaming...")
            os.rename(downloaded_file, output_path)
        
        print(f"Audio ready at: {output_path}")
        return output_path
        
    except subprocess.CalledProcessError as e:
        print(f"Error downloading audio: {e.stderr}")
        raise
    except Exception as e:
        print(f"Exception occurred: {type(e).__name__}: {e}")
        # Clean up on error
        if 'downloaded_file' in locals() and downloaded_file and os.path.exists(downloaded_file):
            os.remove(downloaded_file)
        raise
