import os
import shutil
import subprocess
import logging
from django.conf import settings
from .models import Movie, Episode

logger = logging.getLogger(__name__)

def transcode_video(content_type, content_id):
    """
    Performs video transcoding to HLS format.
    If ffmpeg is available, it generates an M3U8 playlist and segments.
    """
    model = Movie if content_type == 'movie' else Episode
    try:
        obj = model.objects.get(id=content_id)
    except model.DoesNotExist:
        logger.error(f"Content {content_type} with id {content_id} not found for transcoding")
        return

    if not obj.video_file:
        logger.error(f"No video file found for {content_type} {content_id}")
        obj.transcoding_status = 'failed'
        obj.save()
        return

    obj.transcoding_status = 'processing'
    obj.save()

    work_dir = None
    try:
        input_path = obj.video_file.path
        if not os.path.exists(input_path):
            logger.error(f"Video source file missing for {content_type} {content_id}: {input_path}")
            obj.transcoding_status = 'failed'
            obj.save()
            return
        
        # Define HLS output paths
        hls_dir = os.path.join(settings.MEDIA_ROOT, 'videos/hls', f"{content_type}_{content_id}")
        work_dir = f"{hls_dir}.tmp-{os.getpid()}"
        if os.path.exists(work_dir):
            shutil.rmtree(work_dir)
        os.makedirs(work_dir, exist_ok=True)
        playlist_name = "playlist.m3u8"
        hls_output_path = os.path.join(work_dir, playlist_name)
        segment_output_path = os.path.join(work_dir, 'segment_%05d.ts')

        # Check for ffmpeg
        try:
            ffmpeg_available = subprocess.run(
                ['ffmpeg', '-version'],
                capture_output=True,
                timeout=10,
            ).returncode == 0
        except (FileNotFoundError, subprocess.TimeoutExpired):
            ffmpeg_available = False

        if ffmpeg_available:
            logger.info(f"Starting HLS transcoding for {content_type} {content_id}")
            cmd = [
                'ffmpeg', '-y', '-i', input_path,
                '-c:v', 'libx264', '-preset', 'veryfast', '-crf', '23',
                '-profile:v', 'baseline', '-level', '3.0',
                '-vf', 'scale=w=min(1280\\,iw):h=-2',
                '-c:a', 'aac', '-b:a', '128k', '-ac', '2',
                '-start_number', '0',
                '-hls_time', '6', '-hls_playlist_type', 'vod',
                '-hls_flags', 'independent_segments',
                '-hls_segment_filename', segment_output_path,
                '-hls_list_size', '0',
                '-f', 'hls', hls_output_path
            ]
            result = subprocess.run(cmd, check=True, capture_output=True, text=True)
            if result.stderr:
                logger.debug(result.stderr[-4000:])

            if not os.path.exists(hls_output_path):
                raise RuntimeError("ffmpeg completed without creating an HLS playlist")

            if os.path.exists(hls_dir):
                shutil.rmtree(hls_dir)
            os.replace(work_dir, hls_dir)
            work_dir = None
            
            relative_playlist_path = f"videos/hls/{content_type}_{content_id}/{playlist_name}"
            obj.hls_playlist.name = relative_playlist_path
            obj.optimized_video = obj.video_file # Use original as optimized for now
            obj.transcoding_status = 'completed'
        else:
            logger.warning(f"ffmpeg not found. Skipping HLS generation for {content_type} {content_id}")
            # Fallback: Just mark as completed and use original
            obj.hls_playlist = ''
            obj.optimized_video = obj.video_file
            obj.transcoding_status = 'completed'
        
        obj.save()
        logger.info(f"Transcoding process finished for {content_type} {content_id}")

    except Exception as e:
        logger.exception(f"Transcoding failed for {content_type} {content_id}: {str(e)}")
        obj.transcoding_status = 'failed'
        obj.save()
    finally:
        if work_dir and os.path.exists(work_dir):
            shutil.rmtree(work_dir, ignore_errors=True)

def start_transcoding(content_type, content_id):
    """
    Triggers transcoding process asynchronously.
    """
    import threading
    thread = threading.Thread(target=transcode_video, args=(content_type, content_id), daemon=True)
    thread.start()
