"""MLT/melt backend — invoke melt for rendering MLT XML projects.

Shotcut and Kdenlive both use the MLT framework. The `melt` command-line
tool can render MLT XML projects to video files.

Requires: melt (system package)
    apt install melt
"""

import os
import shutil
import subprocess
import tempfile
from typing import Optional


def find_melt() -> str:
    """Find the melt executable. Raises RuntimeError if not found."""
    path = shutil.which("melt")
    if path:
        return path
    raise RuntimeError(
        "melt is not installed. Install it with:\n"
        "  apt install melt   # Debian/Ubuntu"
    )


def find_ffmpeg() -> str:
    """Find ffmpeg executable."""
    path = shutil.which("ffmpeg")
    if path:
        return path
    raise RuntimeError("ffmpeg is not installed. apt install ffmpeg")


def get_melt_version() -> str:
    """Get the installed melt version string."""
    melt = find_melt()
    result = subprocess.run(
        [melt, "--version"],
        capture_output=True, text=True, timeout=10,
    )
    # melt outputs version info differently
    output = result.stdout.strip() or result.stderr.strip()
    return output.split("\n")[0] if output else "unknown"


def render_mlt(
    mlt_path: str,
    output_path: str,
    vcodec: str = "libx264",
    acodec: str = "aac",
    overwrite: bool = False,
    timeout: int = 300,
    extra_args: Optional[list] = None,
) -> dict:
    """Render an MLT XML file to a video using melt.

    Args:
        mlt_path: Path to the .mlt XML file
        output_path: Output video file path
        vcodec: Video codec
        acodec: Audio codec
        overwrite: Allow overwriting existing files
        timeout: Maximum seconds
        extra_args: Additional melt arguments

    Returns:
        Dict with output path, file size, method
    """
    if not os.path.exists(mlt_path):
        raise FileNotFoundError(f"MLT file not found: {mlt_path}")

    if os.path.exists(output_path) and not overwrite:
        raise FileExistsError(f"Output file exists: {output_path}")

    melt = find_melt()
    os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)

    cmd = [
        melt, mlt_path,
        "-consumer", f"avformat:{output_path}",
        f"vcodec={vcodec}",
        f"acodec={acodec}",
    ]

    if extra_args:
        cmd.extend(extra_args)

    result = subprocess.run(
        cmd,
        capture_output=True, text=True,
        timeout=timeout,
    )

    if result.returncode != 0:
        raise RuntimeError(
            f"melt render failed (exit {result.returncode}):\n"
            f"  stderr: {result.stderr[-500:]}"
        )

    if not os.path.exists(output_path):
        raise RuntimeError(
            f"melt produced no output file.\n"
            f"  Expected: {output_path}\n"
            f"  stdout: {result.stdout[-500:]}"
        )

    return {
        "output": os.path.abspath(output_path),
        "format": os.path.splitext(output_path)[1].lstrip("."),
        "method": "melt",
        "file_size": os.path.getsize(output_path),
    }


def render_color_bars(
    output_path: str,
    duration: int = 3,
    width: int = 320,
    height: int = 240,
    fps: int = 25,
    vcodec: str = "libx264",
    acodec: str = "aac",
    overwrite: bool = False,
    timeout: int = 120,
) -> dict:
    """Render a color bars test video using melt's built-in producer.

    This doesn't require any input files — perfect for E2E testing.
    """
    if os.path.exists(output_path) and not overwrite:
        raise FileExistsError(f"Output file exists: {output_path}")

    melt = find_melt()
    os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)

    frames = duration * fps
    cmd = [
        melt,
        f"color:red", f"out={fps - 1}",
        f"color:green", f"out={fps - 1}",
        f"color:blue", f"out={fps - 1}",
        "-consumer", f"avformat:{output_path}",
        f"width={width}", f"height={height}",
        f"frame_rate_num={fps}",
        f"vcodec={vcodec}",
        f"acodec={acodec}",
        "ar=48000", "channels=2",
    ]

    result = subprocess.run(
        cmd,
        capture_output=True, text=True,
        timeout=timeout,
    )

    if result.returncode != 0:
        raise RuntimeError(
            f"melt render failed (exit {result.returncode}):\n"
            f"  stderr: {result.stderr[-500:]}"
        )

    if not os.path.exists(output_path):
        raise RuntimeError(f"melt produced no output: {output_path}")

    return {
        "output": os.path.abspath(output_path),
        "format": os.path.splitext(output_path)[1].lstrip("."),
        "method": "melt",
        "file_size": os.path.getsize(output_path),
        "duration_seconds": duration,
    }
