import subprocess, os, json, re, tempfile, shutil
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("YouTubeProcessor")


def _run(cmd, **kwargs):
    return subprocess.run(cmd, capture_output=True, text=True, **kwargs)


@mcp.tool()
def download_video(url: str, output_dir: str = "~/Downloads") -> str:
    """Download YouTube video at 480p quality. Returns path to downloaded file."""
    output_dir = os.path.expanduser(output_dir)
    os.makedirs(output_dir, exist_ok=True)

    tmpl = os.path.join(output_dir, "%(title)s.%(ext)s")
    result = _run([
        "yt-dlp", "-f", "best[height<=480][ext=mp4]/best[height<=480]",
        "--merge-output-format", "mp4",
        "--no-write-subs", "--no-embed-subs",
        "--print", "after_move:filepath",
        "-o", tmpl,
        url
    ])
    if result.returncode != 0:
        return json.dumps({"error": result.stderr.strip()})
    path = result.stdout.strip().split("\n")[0]
    if not os.path.exists(path):
        return json.dumps({"error": f"yt-dlp completed but output file not found: {path}"})
    return json.dumps({"path": path, "title": os.path.basename(path)})


@mcp.tool()
def extract_subs(url: str, output_dir: str = "~/Downloads") -> str:
    """Extract subtitles from YouTube video. Tries Russian first, then English. Returns subtitle info with content."""
    output_dir = os.path.expanduser(output_dir)
    os.makedirs(output_dir, exist_ok=True)

    def try_subs(lang, auto=False):
        flags = ["yt-dlp", "--skip-download", "--convert-subs", "srt", "--sub-format", "srt"]
        flags += ["--write-auto-subs" if auto else "--write-subs"]
        flags += ["--sub-langs", lang]
        flags += ["-o", os.path.join(output_dir, "%(title)s.%(ext)s"), url]
        result = _run(flags)
        if result.returncode != 0:
            return None
        for f in os.listdir(output_dir):
            if f.endswith(f".{lang}.srt"):
                path = os.path.join(output_dir, f)
                with open(path, encoding="utf-8", errors="replace") as fh:
                    content = fh.read()
                return {"path": path, "lang": lang, "content": content}
        return None

    for lang in ("ru", "en"):
        for auto in (False, True):
            found = try_subs(lang, auto)
            if found:
                needs = lang != "ru"
                return json.dumps({
                    "path": found["path"], "lang": found["lang"],
                    "needs_translation": needs, "content": found["content"]
                })
    return json.dumps({
        "error": "No subtitles found in Russian or English",
        "lang": None, "path": None, "content": None,
        "needs_translation": False
    })


@mcp.tool()
def save_subs(filepath: str, content: str) -> str:
    """Save subtitle content to a .srt file. Returns the path."""
    filepath = os.path.expanduser(filepath)
    os.makedirs(os.path.dirname(filepath), exist_ok=True)
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(content)
    return json.dumps({"path": filepath})


@mcp.tool()
def burn_subs(video_path: str, subs_path: str, output_path: str = "") -> str:
    """Burn subtitles into video using ffmpeg. Returns path to output file."""
    video_path = os.path.expanduser(video_path)
    subs_path = os.path.expanduser(subs_path)
    if not output_path:
        base, ext = os.path.splitext(video_path)
        output_path = base + "_subbed" + ext
    output_path = os.path.expanduser(output_path)

    tmp_subs = ""
    try:
        if not os.access(subs_path, os.R_OK):
            return json.dumps({"error": f"Subtitle file not readable: {subs_path}"})

        # copy subs to a temp path with safe chars (no commas, brackets etc)
        tmp_subs = os.path.join(
            tempfile.mkdtemp(), "subs.srt"
        )
        shutil.copy2(subs_path, tmp_subs)

        result = _run([
            "ffmpeg", "-y",
            "-i", video_path,
            "-vf", f"subtitles={tmp_subs}",
            "-c:v", "libx264", "-crf", "23", "-preset", "fast",
            "-c:a", "aac", "-b:a", "128k",
            output_path
        ])
        if result.returncode != 0:
            return json.dumps({"error": result.stderr.strip()})
        if not os.path.exists(output_path):
            return json.dumps({"error": "ffmpeg completed but output file not found"})
        return json.dumps({"path": output_path})
    finally:
        if tmp_subs:
            shutil.rmtree(os.path.dirname(tmp_subs), ignore_errors=True)


if __name__ == "__main__":
    mcp.run(transport="stdio")
