import subprocess
import os
import argparse
import urllib.request
import re
import shutil

def download_hls(url, output_file, max_retries=3):
    """Baixa e converte um stream HLS diretamente para MP4"""
    command = [
        'ffmpeg',
        '-i', url,
        '-c:v', 'libx264',
        '-crf', '23',
        '-preset', 'fast',
        '-c:a', 'aac',
        '-b:a', '192k',
        '-c:s', 'mov_text',
        '-map', '0',
        '-metadata:s:s:0', 'language=por',
        '-f', 'mp4',
        output_file
    ]
    
    for attempt in range(max_retries):
        try:
            print(f"Processando stream HLS (tentativa {attempt + 1}): {url}")
            subprocess.run(command, check=True)
            print(f"Conversão concluída: {output_file}")
            return True
        except subprocess.CalledProcessError as e:
            print(f"Erro na tentativa {attempt + 1}: {e}")
            if attempt == max_retries - 1:
                print(f"Falha ao processar após {max_retries} tentativas: {url}")
                return False

def is_hls_url(url):
    """Verifica se a URL parece ser um stream HLS"""
    return url.endswith('.m3u8') or 'm3u8' in url.lower()

def is_url(path):
    """Verifica se o caminho é uma URL"""
    return path.startswith(('http://', 'https://', 'ftp://'))

def process_file_list(file_path, crf=23, preset='fast', audio_bitrate='192k'):
    """
    Processa a lista de arquivos no formato CAMINHO/URL NOMEDESAIDA
    """
    with open(file_path, 'r') as f:
        lines = [line.strip().split() for line in f if line.strip()]
    
    for items in lines:
        if len(items) < 2:
            print(f"Linha inválida: {' '.join(items)}")
            continue
            
        source = items[0]
        output_name = items[1]
        
        # Garante que a extensão do output seja .mp4
        if not output_name.lower().endswith('.mp4'):
            output_name += '.mp4'
        
        if is_url(source):
            # Processa como URL
            if is_hls_url(source):
                # Processa como stream HLS
                if not download_hls(source, output_name):
                    print(f"Falha ao processar stream HLS: {source}")
            else:
                # Processa como arquivo remoto normal
                temp_file = 'temp_' + os.path.basename(source.split('?')[0])  # Remove query params
                
                # 1. Baixa o arquivo
                try:
                    print(f"Baixando: {source} -> {temp_file}")
                    urllib.request.urlretrieve(source, temp_file)
                    print(f"Download concluído: {temp_file}")
                except Exception as e:
                    print(f"Erro ao baixar {source}: {e}")
                    continue
                
                # 2. Converte o arquivo
                if convert_to_mp4(temp_file, output_name, crf, preset, audio_bitrate):
                    # 3. Remove o arquivo temporário se a conversão foi bem-sucedida
                    try:
                        os.remove(temp_file)
                        print(f"Arquivo temporário removido: {temp_file}")
                    except Exception as e:
                        print(f"Erro ao remover arquivo temporário {temp_file}: {e}")
        else:
            # Processa como arquivo local
            if not os.path.exists(source):
                print(f"Arquivo local não encontrado: {source}")
                continue
                
            # Verifica se já é MP4 (e tem as configurações desejadas)
            if source.lower().endswith('.mp4'):
                print(f"O arquivo {source} já é MP4. Verificando configurações...")
                if needs_reencoding(source, crf, preset, audio_bitrate):
                    # Se precisa reencodar, faz uma conversão
                    temp_output = 'temp_' + output_name
                    if convert_to_mp4(source, temp_output, crf, preset, audio_bitrate):
                        # Substitui o arquivo original pelo novo
                        try:
                            os.remove(source)
                            shutil.move(temp_output, output_name)
                            print(f"Arquivo reencodado e substituído: {output_name}")
                        except Exception as e:
                            print(f"Erro ao substituir arquivo: {e}")
                else:
                    # Se não precisa reencodar, apenas copia/renomeia
                    try:
                        shutil.copy2(source, output_name)
                        print(f"Arquivo MP4 copiado para: {output_name}")
                    except Exception as e:
                        print(f"Erro ao copiar arquivo: {e}")
            else:
                # Converte arquivo local para MP4
                if convert_to_mp4(source, output_name, crf, preset, audio_bitrate):
                    print(f"Conversão de arquivo local concluída: {output_name}")

def needs_reencoding(file_path, target_crf, target_preset, target_audio_bitrate):
    """
    Verifica se um arquivo MP4 precisa ser reencodado com as configurações desejadas.
    """
    try:
        # Obtém informações do arquivo usando ffprobe
        probe_command = [
            'ffprobe',
            '-v', 'error',
            '-select_streams', 'v:0',
            '-show_entries', 'stream=codec_name,width,height',
            '-of', 'default=noprint_wrappers=1:nokey=1',
            file_path
        ]
        
        result = subprocess.run(probe_command, capture_output=True, text=True)
        if result.returncode != 0:
            print(f"Não foi possível analisar o arquivo {file_path}")
            return True
            
        # Verifica se o codec de vídeo é h264
        if 'h264' not in result.stdout:
            return True
            
        # Aqui você poderia adicionar mais verificações se necessário
            
    except Exception as e:
        print(f"Erro ao verificar arquivo {file_path}: {e}")
        return True
        
    return False

def convert_to_mp4(input_file, output_file, crf=23, preset='fast', audio_bitrate='192k'):
    """
    Converte um arquivo de vídeo para MP4 usando as configurações especificadas.
    """
    command = [
        'ffmpeg',
        '-i', input_file,
        '-c:v', 'libx264',
        '-crf', str(crf),
        '-preset', preset,
        '-c:a', 'aac',
        '-b:a', audio_bitrate,
        '-c:s', 'mov_text',
        '-map', '0',
        '-metadata:s:s:0', 'language=por',
        output_file
    ]
    
    try:
        print(f"Convertendo: {input_file} -> {output_file}")
        subprocess.run(command, check=True)
        print(f"Conversão concluída: {output_file}")
        return True
    except subprocess.CalledProcessError as e:
        print(f"Erro ao converter {input_file}: {e}")
        return False
    except Exception as e:
        print(f"Erro inesperado ao processar {input_file}: {e}")
        return False

def main():
    parser = argparse.ArgumentParser(description='Converte vídeos para MP4 (arquivos locais ou URLs)')
    parser.add_argument('--input', default='lista.txt', help='Arquivo com lista de vídeos (padrão: lista.txt)')
    parser.add_argument('--crf', type=int, default=23, help='Qualidade do vídeo (padrão: 23)')
    parser.add_argument('--preset', default='fast', help='Preset de codificação (padrão: fast)')
    parser.add_argument('--audio', default='192k', help='Taxa de bits do áudio (padrão: 192k)')
    
    args = parser.parse_args()
    
    if not os.path.exists(args.input):
        print(f"Arquivo {args.input} não encontrado!")
        return
    
    print(f"Processando lista de vídeos de {args.input}...")
    process_file_list(args.input, args.crf, args.preset, args.audio)
    print("Processamento concluído!")

if __name__ == '__main__':
    main()