import subprocess
import json
import os
from database import FFmpegProfile
from core.state import state

class FFmpegEngine:
    def __init__(self, profile_id=None):
        if profile_id:
            self.profile = FFmpegProfile.get_by_id(profile_id)
        else:
            self.profile = FFmpegProfile.get_or_none(FFmpegProfile.is_active == True)
            
        if not self.profile:
            state.log("⚠️ AVISO: Nenhum perfil FFmpeg ativo! Usando defaults.")

    def get_file_info(self, filepath):
        cmd = ['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_streams', '-show_format', filepath]
        try:
            output = subprocess.check_output(cmd).decode('utf-8')
            return json.loads(output)
        except Exception as e:
            state.log(f"Erro FFprobe: {e}")
            return None

    def get_duration(self, filepath):
        try: return float(self.get_file_info(filepath)['format']['duration'])
        except: return 0

    def build_command(self, input_file, output_file):
        if not self.profile: raise Exception("Perfil não configurado.")
        p = self.profile
        metadata = self.get_file_info(input_file)
        if not metadata: raise Exception("Arquivo inválido.")

        # Info de entrada
        video_stream = next((s for s in metadata['streams'] if s['codec_type'] == 'video'), None)
        input_codec = video_stream['codec_name'] if video_stream else 'unknown'
        
        cmd = ['ffmpeg', '-y'] 
        video_filters = []

        # --- LÓGICA MODULAR DE HARDWARE ---
        
        # 1. INTEL/AMD VAAPI
        if p.hardware_type == 'vaapi':
            # Setup do Device (Sempre necessário para VAAPI)
            cmd.extend(['-init_hw_device', 'vaapi=intel:/dev/dri/renderD128'])
            cmd.extend(['-filter_hw_device', 'intel'])
            
            # Verificação de Modo Híbrido (Intel 4th Gen / Compatibilidade)
            use_hw_decode = True
            
            if p.hybrid_decode:
                # Lista de codecs seguros para Haswell
                safe_codecs = ['h264', 'mpeg2video', 'vc1', 'mjpeg']
                if input_codec not in safe_codecs:
                    use_hw_decode = False
                    state.log(f"⚙️ Modo Híbrido Ativado: CPU decodificando {input_codec} -> GPU codificando.")
            
            # Aplica Input HW Accel se permitido
            if use_hw_decode:
                cmd.extend(['-hwaccel', 'vaapi'])
                cmd.extend(['-hwaccel_output_format', 'vaapi'])
                cmd.extend(['-hwaccel_device', 'intel'])
            else:
                # Se não usar HW decode, precisa subir pra GPU antes de encodar
                video_filters.append('format=nv12,hwupload')

        # 2. NVIDIA NVENC (Se suportado pelo container/host)
        elif p.hardware_type == 'nvenc':
            cmd.extend(['-hwaccel', 'cuda'])
            # Nvidia geralmente aguenta tudo, mas se precisar de resize, adiciona filtros aqui

        # 3. INTEL QSV (QuickSync Proprietário)
        elif p.hardware_type == 'qsv':
            cmd.extend(['-hwaccel', 'qsv', '-c:v', 'h264_qsv'])

        # --- INPUT ---
        cmd.extend(['-threads', '4', '-i', input_file])

        # --- VÍDEO OUTPUT ---
        cmd.extend(['-map', '0:v:0']) 

        if p.video_codec == 'copy':
            cmd.extend(['-c:v', 'copy'])
        else:
            # Aplica filtros acumulados
            if video_filters:
                cmd.extend(['-vf', ",".join(video_filters)])
            
            cmd.extend(['-c:v', p.video_codec])

            # Qualidade baseada no encoder
            if 'vaapi' in p.video_codec:
                cmd.extend(['-qp', str(p.crf)]) # Constant Quality para VAAPI
            elif 'nvenc' in p.video_codec:
                cmd.extend(['-cq', str(p.crf), '-preset', p.preset])
            else:
                # CPU / Libx264
                cmd.extend(['-crf', str(p.crf), '-preset', p.preset])

        # --- ÁUDIO (AAC Stereo Compatível) ---
        allowed_langs = [l.strip().lower() for l in (p.audio_langs or "").split(',')]
        audio_streams = [s for s in metadata['streams'] if s['codec_type'] == 'audio']
        
        acount = 0
        for s in audio_streams:
            lang = s.get('tags', {}).get('language', 'und').lower()
            if not allowed_langs or lang in allowed_langs or 'und' in allowed_langs:
                cmd.extend(['-map', f'0:{s["index"]}'])
                cmd.extend([f'-c:a:{acount}', 'aac', f'-b:a:{acount}', '192k', f'-ac:{acount}', '2'])
                acount += 1
        
        if acount == 0 and audio_streams:
            cmd.extend(['-map', '0:a:0', '-c:a', 'aac', '-b:a', '192k'])

        # --- LEGENDAS ---
        sub_allowed = [l.strip().lower() for l in (p.subtitle_langs or "").split(',')]
        sub_streams = [s for s in metadata['streams'] if s['codec_type'] == 'subtitle']
        
        scount = 0
        for s in sub_streams:
            lang = s.get('tags', {}).get('language', 'und').lower()
            if not sub_allowed or lang in sub_allowed or 'und' in sub_allowed:
                cmd.extend(['-map', f'0:{s["index"]}'])
                cmd.extend([f'-c:s:{scount}', 'copy'])
                scount += 1

        # Metadados
        clean_title = os.path.splitext(os.path.basename(output_file))[0]
        cmd.extend(['-metadata', f'title={clean_title}'])
        cmd.append(output_file)
        
        return cmd