import os
import subprocess
import argparse


def get_video_duration(input_file):
    """
    Get the duration of a video file using ffprobe.

    ffprobe is a command-line tool used to analyze multimedia streams. In this function:
    - `-v error`: Limits output to only errors.
    - `-select_streams v:0`: Selects the first video stream.
    - `-show_entries format=duration`: Outputs only the video duration.
    - `-of default=noprint_wrappers=1:nokey=1`: Formats the output to display only the duration value.
    """
    try:
        result = subprocess.run(
            [
                "ffprobe",
                "-v",
                "error",
                "-select_streams",
                "v:0",
                "-show_entries",
                "format=duration",
                "-of",
                "default=noprint_wrappers=1:nokey=1",
                input_file,
            ],
            capture_output=True,
            text=True,
            check=True,
        )
        return float(result.stdout.strip())
    except (subprocess.CalledProcessError, ValueError) as e:
        raise RuntimeError(f"Failed to get duration for {input_file}: {e}")


def process_folder(input_dir, output_dir, trim_start, trim_end, supported_formats):
    """Process each folder in the input directory and trim video files."""
    os.makedirs(output_dir, exist_ok=True)

    for folder in os.listdir(input_dir):
        folder_path = os.path.join(input_dir, folder)
        if not os.path.isdir(folder_path):
            continue

        for file in os.listdir(folder_path):
            if file.endswith(tuple(supported_formats)):
                input_file = os.path.join(folder_path, file)

                # Extract episode number or default to folder name
                # Expected folder naming convention: 'SeriesName #EpisodeNumber - Description'
                # If '#' is missing, the folder name will be used as the episode identifier
                if "#" in folder:
                    try:
                        episode = folder.split("#")[1].strip().split(" - ")[0]
                    except IndexError:
                        episode = folder.replace(" ", "_")
                else:
                    episode = folder.replace(" ", "_")

                output_ext = os.path.splitext(file)[1]
                output_file = os.path.join(output_dir, f"ep{episode}{output_ext}")

                try:
                    duration = get_video_duration(input_file)
                except RuntimeError as e:
                    print(e)
                    continue

                if trim_start >= duration:
                    print(
                        f"Skipping {input_file}: trim-start ({trim_start}s) is greater than or equal to video duration ({duration}s)."
                    )
                    continue
                if duration - trim_end <= trim_start:
                    print(
                        f"Skipping {input_file}: Invalid trim range (start: {trim_start}s, end: {trim_end}s, duration: {duration}s)."
                    )
                    continue

                end_time = duration - trim_end

                # FFmpeg command to trim the video
                ffmpeg_command = [
                    "ffmpeg",  # Command to run FFmpeg
                    "-i",
                    input_file,  # Input file path
                    "-ss",
                    f"{trim_start:.2f}",  # Start trimming from this timestamp (in seconds)
                    "-to",
                    f"{end_time:.2f}",  # End trimming at this timestamp (in seconds)
                    "-c",
                    "copy",  # Copy codec to avoid re-encoding
                    output_file,  # Output file path
                ]

                try:
                    subprocess.run(ffmpeg_command, check=True)
                    print(f"Trimmed and saved: {output_file}")
                except subprocess.CalledProcessError as e:
                    print(f"Failed to process {input_file}: {e}")


def main():
    """Main function to parse arguments and run the script."""
    parser = argparse.ArgumentParser(
        description="Trim video files in folders and save them with episode numbers."
    )
    parser.add_argument(
        "--input",
        type=str,
        default=".",
        help="Input directory containing folders with video files",
    )
    parser.add_argument(
        "--output",
        type=str,
        default="output",
        help="Output directory for trimmed videos",
    )
    parser.add_argument(
        "--trim-start",
        type=float,
        default=46.0,
        help="Number of seconds to trim from the start",
    )
    parser.add_argument(
        "--trim-end",
        type=float,
        default=16.0,
        help="Number of seconds to trim from the end",
    )
    parser.add_argument(
        "--formats",
        type=str,
        default=".mp4,.webm,.mkv",
        help="Comma-separated list of supported video formats eg, '.mp4,.webm,.mkv' ",
    )

    args = parser.parse_args()
    supported_formats = [fmt.strip() for fmt in args.formats.split(",")]
    process_folder(
        args.input, args.output, args.trim_start, args.trim_end, supported_formats
    )


if __name__ == "__main__":
    main()