import logging
import gradio as gr
from yt_dlp import YoutubeDL
import os
from dotenv import load_dotenv
from pathlib import Path
import tempfile
import shutil
from pathlib import Path

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        #logging.FileHandler('youtube_downloader.log'),
        logging.StreamHandler()
    ]
)

# Create logger instance
logger = logging.getLogger('youtube_downloader')

def cookies_to_env(cookie_file_path: str) -> str:
    """Convert cookie file content to environment variable format"""
    try:
        with open(cookie_file_path, 'r') as f:
            lines = f.readlines()
            
        # Keep header comments
        header = [line.strip() for line in lines if line.startswith('#')]
        # Get cookie content (non-comment lines)
        cookies = [line.strip() for line in lines if line.strip() and not line.startswith('#')]
        
        # Join with escaped newlines
        content = '\\n'.join(header + [''] + cookies)  # Empty line after headers
        
        # Create env file content
        return f'FIREFOX_COOKIES="{content}"'
    
    except Exception as e:
        raise ValueError(f"Error converting cookie file: {str(e)}")

def env_to_cookies(env_content: str, output_file: str) -> None:
    """Convert environment variable content back to cookie file"""
    try:
        # Extract content from env format
        if '="' not in env_content:
            raise ValueError("Invalid env content format")
            
        content = env_content.split('="', 1)[1].strip('"')
        
        # Replace escaped newlines with actual newlines
        cookie_content = content.replace('\\n', '\n')
        
        # Write to cookie file
        with open(output_file, 'w') as f:
            f.write(cookie_content)
            
    except Exception as e:
        raise ValueError(f"Error converting to cookie file: {str(e)}")

def save_to_env_file(env_content: str, env_file: str = '.env') -> None:
    """Save environment variable content to .env file"""
    try:
        with open(env_file, 'w') as f:
            f.write(env_content)
        #print(f"Successfully saved to {env_file}")
    except Exception as e:
        raise ValueError(f"Error saving to env file: {str(e)}")

def env_to_cookies_from_env(output_file: str) -> None:
    """Convert environment variable from .env file to cookie file"""
    try:
        load_dotenv()  # Load from .env file
        env_content = os.getenv('FIREFOX_COOKIES', "")
        #print(f"Printing env content: \n{env_content}")
        if not env_content:
            raise ValueError("FIREFOX_COOKIES not found in .env file")
            
        env_to_cookies(f'FIREFOX_COOKIES="{env_content}"', output_file)
    except Exception as e:
        raise ValueError(f"Error converting to cookie file: {str(e)}")

def get_cookies():
    """Get cookies from environment variable"""
    load_dotenv()
    cookie_content = os.getenv('FIREFOX_COOKIES', "")
    #print(cookie_content)
    if not cookie_content:
        raise ValueError("FIREFOX_COOKIES environment variable not set")
    return cookie_content

def create_temp_cookie_file():
    """Create temporary cookie file from environment variable"""
    temp_cookie = tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.txt')
    try:
        cookie_content = get_cookies()
        # Replace escaped newlines with actual newlines
        cookie_content = cookie_content.replace('\\n', '\n')
        temp_cookie.write()
        temp_cookie.flush()
        return Path(temp_cookie.name)
    finally:
        temp_cookie.close()

def download_for_browser(url, mode='audio', quality='high'):
    if not url:
        return None, "Please enter a valid URL"
    logger.info(f"Downloading {url} in {mode} mode with {quality} quality")
        
    # Create temporary directory that persists until file is served
    temp_dir = Path(tempfile.mkdtemp())
    
    try:
        # Configure download options
        opts = {
            'format': 'bestaudio/best' if mode == 'audio' else 'bestvideo+bestaudio/best',
            'outtmpl': str(temp_dir / '%(title)s.%(ext)s'),
            'restrictfilenames': True,
            'windowsfilenames': True,
            'quiet': True,
            'no_warnings': True
        }
        
        # Add format-specific options
        if mode == 'audio':
            opts.update({
                'postprocessors': [{
                    'key': 'FFmpegExtractAudio',
                    'preferredcodec': 'mp3',
                    'preferredquality': '320' if quality == 'high' else '192',
                }],
                'prefer_ffmpeg': True,
                'keepvideo': False
            })
        else:
            opts.update({
                'format': 'bestvideo+bestaudio/best' if quality == 'high' else 'best[height<=720]',
                'merge_output_format': 'mp4'
            })

        load_dotenv()
        USE_FIREFOX_COOKIES = os.getenv("USE_FIREFOX_COOKIES", "False")
        if USE_FIREFOX_COOKIES == "True":
            # Convert cookie file to env and save locally
            #cookie_file = "cookies.firefox-private.txt"
            #env_content = cookies_to_env(cookie_file)
            #save_to_env_file(env_content)

            # Convert back to cookie file using .env
            cookiefile = "firefox-cookies.txt"
            env_to_cookies_from_env("firefox-cookies.txt")

                    # Add cookies
            logger.info(f"Using Firefox cookies: {USE_FIREFOX_COOKIES}")
            opts["cookiefile"] =  "firefox-cookies.txt" #create_temp_cookie_file() 
        else:
            opts["no_cookies"] = True # Forces yt-dlp to access YouTube without any authentication

        # Download file
        logger.info(f"Downloading {url} with options: {opts}")
        with YoutubeDL(opts) as ydl:
            info = ydl.extract_info(url, download=True)
            
        # Find downloaded file
        files = list(temp_dir.glob('*'))
        if not files:
            return None, "Download failed - no files found"
            
        download_file = files[0]
        if not download_file.exists():
            return None, f"File not found after download: {download_file.name}"
            
        # Return file while it exists in temp directory
        logger.info(f"Downloaded file: {download_file.name}")
        return str(download_file), f"Successfully converted: {download_file.name}"
        
    except Exception as e:
        if temp_dir.exists():
            shutil.rmtree(temp_dir)
        # Return raw error message without formatting
        error_msg = str(e)
        if "ERROR: [youtube]" in error_msg:
            # Extract everything after "ERROR: [youtube]"
            error_msg = error_msg.split("ERROR: [youtube]")[1].strip()
        logger.error(f"Download error: {error_msg}")
        return None, error_msg

def create_browser_ui():
    
    with gr.Blocks(title="YouTube Downloader", theme=gr.themes.Soft()) as demo:

        gr.Markdown("""## <span style='display: flex; align-items: center; gap: 10px;'><img src='https://cdn-icons-png.flaticon.com/512/1384/1384060.png' width='25'/> <img src='https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Youtube_Music_icon.svg/2048px-Youtube_Music_icon.svg.png' width='25'/>YouTube Downloader</span>""")
        
        with gr.Row():
            with gr.Column(scale=1):
                url_input = gr.Textbox(
                label="YouTube URL",
                placeholder="https://youtube.com/watch?v=...",
                scale=1
                )

                mode_input = gr.Radio(
                    choices=["audio", "video"],
                    value="audio",
                    label="Format"
                )
                quality_input = gr.Radio(
                    choices=["high", "medium"],
                    value="high",
                    label="Quality"
                )
        
                download_button = gr.Button("Convert", variant="primary")

        with gr.Column(scale=1):
            status_text = gr.Textbox(label="Converting Status", interactive=False)
            output_file = gr.File(label="Download to your device ...")
            gr.Markdown("""### ⓘ Note:
                        The downloader currently works only when running locally.<br> 
                        To run it in HF deployed space, cookies are required to access YouTube.<br>
                        For more details, visit [README](https://huggingface.co/spaces/prasanthntu/youtube-downloader/blob/main/README.md)""", label="Note", show_label=True, container=True)

        download_button.click(
            fn=download_for_browser,
            inputs=[url_input, mode_input, quality_input],
            outputs=[output_file, status_text]
        )

    return demo

demo = create_browser_ui()
demo.launch(
    share=False,
    debug=True,
    show_error=True
    )