"""YouTube processing commands for the Trax CLI."""

import asyncio
import json
import click
from pathlib import Path
from rich.progress import Progress, TextColumn, BarColumn, TimeElapsedColumn

from ..utils import console, is_valid_youtube_url, display_text_metadata
from ..progress import CliProgressRenderer, make_download_callback
from ...services.youtube_service import YouTubeMetadataService
from ...services.media_service import create_media_service
from ...repositories.media_repository import create_media_repository


@click.command()
@click.argument('url')
@click.option('--download', is_flag=True, help='Download media after metadata extraction')
@click.option('--queue', is_flag=True, help='Add to batch queue for processing')
@click.option('--json', 'output_format', flag_value='json', default=True, help='Output as JSON')
@click.option('--txt', 'output_format', flag_value='txt', help='Output as plain text')
def youtube(url, download, queue, output_format):
    """Process a YouTube URL to extract metadata."""
    async def _youtube():
        try:
            # Validate URL
            if not is_valid_youtube_url(url):
                console.print("[red]Error: Invalid YouTube URL[/red]")
                return
            
            with Progress(
                TextColumn("[bold blue]{task.description}"),
                BarColumn(),
                TimeElapsedColumn(),
            ) as progress:
                task = progress.add_task("Extracting metadata...", total=100)
                
                # Extract metadata
                youtube_service = YouTubeMetadataService()
                await youtube_service.initialize()
                metadata = await youtube_service.extractor.extract_metadata(url)
                progress.update(task, completed=100)
                
                # Display metadata
                if output_format == 'json':
                    # Convert datetime objects to strings for JSON serialization
                    serialized_metadata = metadata.copy()
                    if 'metadata_extracted_at' in serialized_metadata:
                        serialized_metadata['metadata_extracted_at'] = serialized_metadata['metadata_extracted_at'].isoformat()
                    console.print(json.dumps(serialized_metadata, indent=2))
                else:
                    display_text_metadata(metadata)
                
                # Handle download if requested
                if download:
                    # Create media service
                    media_repo = create_media_repository()
                    media_service = create_media_service(media_repository=media_repo)

                    # Set output directory
                    from src.config import config
                    output_dir = config.DATA_DIR / "media" / "downloads"
                    output_dir.mkdir(parents=True, exist_ok=True)

                    # Use CLI progress renderer for download updates
                    with CliProgressRenderer(console) as renderer:
                        renderer.track_download("Downloading media...")
                        result = await media_service.download_media(
                            metadata['url'],
                            output_dir,
                            make_download_callback(renderer, "Downloading media...")
                        )

                    # MediaFileInfo object returned
                    console.print(f"[green]Downloaded to: {result.local_path}[/green]")
                    console.print(f"[green]File size: {result.file_size} bytes[/green]")
                    console.print(f"[green]File hash: {result.file_hash}[/green]")
                
                # Handle queue if requested
                if queue:
                    # Add to batch queue (implementation depends on batch service)
                    console.print("[green]Added to batch queue[/green]")
        
        except Exception as e:
            console.print(f"[red]Error: {str(e)}[/red]")
            raise click.Abort()
    
    asyncio.run(_youtube())


@click.command()
@click.argument('file', type=click.Path(exists=True))
@click.option('--download', is_flag=True, help='Download media after metadata extraction')
@click.option('--queue', is_flag=True, help='Add to batch queue for processing')
@click.option('--json', 'output_format', flag_value='json', default=True, help='Output as JSON')
@click.option('--txt', 'output_format', flag_value='txt', help='Output as plain text')
def batch_urls(file, download, queue, output_format):
    """Process multiple YouTube URLs from a file."""
    async def _batch_urls():
        try:
            file_path = Path(file)
            
            if not file_path.exists():
                console.print(f"[red]File not found: {file}[/red]")
                return
            
            # Read URLs from file
            with open(file_path, 'r') as f:
                urls = [line.strip() for line in f if line.strip()]
            
            if not urls:
                console.print(f"[red]No URLs found in file: {file}[/red]")
                return
            
            console.print(f"[bold blue]Batch URL Processing[/bold blue]")
            console.print(f"[cyan]File:[/cyan] {file}")
            console.print(f"[cyan]URLs found:[/cyan] {len(urls)}")
            console.print(f"[cyan]Download:[/cyan] {'Yes' if download else 'No'}")
            console.print(f"[cyan]Queue:[/cyan] {'Yes' if queue else 'No'}")
            
            # Validate URLs
            valid_urls = []
            invalid_urls = []
            
            for url in urls:
                if is_valid_youtube_url(url):
                    valid_urls.append(url)
                else:
                    invalid_urls.append(url)
            
            if invalid_urls:
                console.print(f"\n[yellow]Invalid URLs found:[/yellow]")
                for url in invalid_urls:
                    console.print(f"  • {url}")
            
            if not valid_urls:
                console.print(f"[red]No valid YouTube URLs found[/red]")
                return
            
            console.print(f"\n[cyan]Processing {len(valid_urls)} valid URLs...[/cyan]")
            
            # Process URLs
            youtube_service = YouTubeMetadataService()
            results = []
            
            with Progress(
                TextColumn("[bold blue]{task.description}"),
                BarColumn(),
                TimeElapsedColumn(),
            ) as progress:
                task = progress.add_task("Processing URLs...", total=len(valid_urls))
                
                for url in valid_urls:
                    try:
                        # Extract metadata
                        metadata = await youtube_service.extractor.extract_metadata(url)
                        results.append({
                            'url': url,
                            'success': True,
                            'metadata': metadata
                        })
                        
                        # Handle download if requested
                        if download:
                            download_task = progress.add_task(f"Downloading {metadata.get('title', 'Unknown')}...", total=100)
                            
                            # Create media service
                            media_repo = create_media_repository()
                            media_service = create_media_service(media_repository=media_repo)
                            
                            # Set output directory
                            from src.config import config
                            output_dir = config.DATA_DIR / "media" / "downloads"
                            output_dir.mkdir(parents=True, exist_ok=True)
                            
                            # Download media
                            result = await media_service.download_media(
                                metadata['url'],
                                output_dir,
                                lambda p: progress.update(download_task, completed=int(p.percentage))
                            )
                            
                            # MediaFileInfo object returned
                            results[-1]['download_path'] = result.local_path
                            results[-1]['file_size'] = result.file_size
                            results[-1]['file_hash'] = result.file_hash
                        
                        progress.update(task, advance=1)
                        
                    except Exception as e:
                        results.append({
                            'url': url,
                            'success': False,
                            'error': str(e)
                        })
                        progress.update(task, advance=1)
            
            # Display results
            successful = [r for r in results if r['success']]
            failed = [r for r in results if not r['success']]
            
            if output_format == 'json':
                # Convert datetime objects to strings for JSON serialization
                def serialize_results(results_list):
                    serialized = []
                    for result in results_list:
                        serialized_result = result.copy()
                        if 'metadata' in serialized_result and 'metadata_extracted_at' in serialized_result['metadata']:
                            serialized_result['metadata']['metadata_extracted_at'] = serialized_result['metadata']['metadata_extracted_at'].isoformat()
                        serialized.append(serialized_result)
                    return serialized
                
                output_data = {
                    'total_urls': len(urls),
                    'valid_urls': len(valid_urls),
                    'invalid_urls': len(invalid_urls),
                    'successful': len(successful),
                    'failed': len(failed),
                    'results': serialize_results(results)
                }
                console.print(json.dumps(output_data, indent=2))
            else:
                console.print(f"\n[bold]Batch URL Processing Summary[/bold]")
                console.print(f"[cyan]Total URLs:[/cyan] {len(urls)}")
                console.print(f"[cyan]Valid URLs:[/cyan] {len(valid_urls)}")
                console.print(f"[cyan]Invalid URLs:[/cyan] {len(invalid_urls)}")
                console.print(f"[green]Successful:[/green] {len(successful)}")
                console.print(f"[red]Failed:[/red] {len(failed)}")
                
                if successful:
                    console.print(f"\n[bold green]Successful Results:[/bold green]")
                    for result in successful:
                        metadata = result['metadata']
                        console.print(f"  • {metadata.get('title', 'Unknown')} - {metadata.get('channel', 'Unknown')}")
                        if 'download_path' in result:
                            console.print(f"    Downloaded to: {result['download_path']}")
                        elif 'download_error' in result:
                            console.print(f"    Download failed: {result['download_error']}")
                
                if failed:
                    console.print(f"\n[bold red]Failed Results:[/bold red]")
                    for result in failed:
                        console.print(f"  • {result['url']}: {result['error']}")
        
        except Exception as e:
            console.print(f"[red]Error: {str(e)}[/red]")
            raise click.Abort()
    
    asyncio.run(_batch_urls())
