from silencewarp import (
    calculate_noise_threshold_ebur128,
    detect_silence,
    create_ffmpeg_speedup_filter,
    get_frame_rate,
    merge_chunks,
    split_video,
    process_video_silence_speedup,
)
from typing import List, Tuple

import subprocess
import argparse
import os
from pathlib import Path
import logging

logging.basicConfig(level=logging.INFO)


class FFmpegError(Exception):
    """Custom exception for FFmpeg related errors."""

    pass


def _run_ffmpeg_command(command: List[str]) -> Tuple[str, str]:
    """
    Executes an FFmpeg command and returns the output and error.

    Args:
        command: The FFmpeg command as a list of strings.

    Returns:
        A tuple containing stdout and stderr as strings.

    Raises:
        FFmpegError: If the FFmpeg command fails (non-zero return code).
    """
    logging.debug(f"Executing FFmpeg command: {' '.join(command)}")
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output_bytes, error_bytes = process.communicate()
    output_text = output_bytes.decode("utf-8").strip()
    error_text = error_bytes.decode("utf-8").strip()

    if process.returncode != 0:
        logging.error(f"FFmpeg command failed with return code {process.returncode}")
        logging.error(f"Command: {' '.join(command)}")
        logging.error(f"Error output:\n{error_text}")
        # raise FFmpegError(f"FFmpeg command failed: {error_text}")

    return output_text, error_text


if __name__ == "__main__":
    argparse.PARSER = argparse.ArgumentParser(description="SilenceWarp")
    argparse.PARSER.add_argument(
        "input",
        help="Input video file",
        type=str,
    )
    argparse.PARSER.add_argument(
        "output",
        help="Output video file",
        type=str,
    )

    args = argparse.PARSER.parse_args()

    if args.input == args.output:
        raise ValueError("Input and output files must be different")

    # Get file path
    input_file = Path(args.input)
    output_file = Path(args.output)
    print(f"in: {input_file.absolute()}")

    chunk_files = split_video(input_file, chunk_duration=120, temp_dir="./temp")

    chunk_file = Path("./temp/video_chunks/chunk009.mp4")

    for chunk_file in chunk_files:
        noise = calculate_noise_threshold_ebur128(chunk_file)

        silences = detect_silence(chunk_file, noise_threshold=noise)

        fps = get_frame_rate(input_file)

        filter = create_ffmpeg_speedup_filter(silences, fps=fps, speed_factor=10)

        ffmpeg_command = [
            "ffmpeg",
            "-y",
            "-i",
            str(chunk_file),
            "-filter_complex",
            filter,
            "-map",
            "[outv]",
            "-map",
            "[outa]",
            f"./temp/sped_up/{chunk_file.name}",
        ]

        try:
            _run_ffmpeg_command(ffmpeg_command)
        except FFmpegError as e:
            logging.error(f"Error processing chunk {chunk_file}: {e}")
