"""横長の動画から指定した区間を切り抜き、縦型（9:16）の字幕付きショート動画を作る。

使い方:
    .venv\\Scripts\\python make_short.py 元動画.mp4 字幕.srt --start 20.2 --end 41.6 --title "集中力が続かない人へ" --out short.mp4

・字幕（.srt）は元動画の時刻のままでよい（切り抜く区間に合わせて自動でずらす）
・背景は元動画をぼかして縦いっぱいに敷き、中央に元動画をそのまま置く
・上部にタイトル、下部に大きめの字幕を入れる
"""

import argparse
import re
import shutil
import subprocess
import tempfile
from pathlib import Path

import imageio_ffmpeg
from PIL import Image, ImageDraw, ImageFont

W, H = 1080, 1920
FONT = "C:/Windows/Fonts/YuGothB.ttc"


def to_sec(t: str) -> float:
    h, m, s = t.replace(",", ".").split(":")
    return int(h) * 3600 + int(m) * 60 + float(s)


def to_ts(x: float) -> str:
    x = max(0.0, x)
    h, r = divmod(x, 3600)
    m, s = divmod(r, 60)
    return f"{int(h):02}:{int(m):02}:{s:06.3f}".replace(".", ",")


def shift_srt(src: str, start: float, end: float) -> str:
    """区間内の字幕だけを残し、時刻を切り抜き後の0秒起点にずらす"""
    blocks, out = re.split(r"\n\s*\n", Path(src).read_text(encoding="utf-8-sig").strip()), []
    for b in blocks:
        lines = b.strip().splitlines()
        if len(lines) < 3:
            continue
        a, z = [to_sec(t.strip()) for t in lines[1].split("-->")]
        if z <= start or a >= end:
            continue
        out.append(f"{len(out) + 1}\n{to_ts(max(a, start) - start)} --> {to_ts(min(z, end) - start)}\n" + "\n".join(lines[2:]))
    return "\n\n".join(out) + "\n"


def title_png(text: str, path: Path) -> None:
    img = Image.new("RGBA", (W, H), (0, 0, 0, 0))
    d = ImageDraw.Draw(img)
    f = ImageFont.truetype(FONT, 76)
    box = d.multiline_textbbox((0, 0), text, font=f, spacing=14, align="center")
    tw, th = box[2] - box[0], box[3] - box[1]
    x, y = (W - tw) // 2, 250
    d.rounded_rectangle([x - 40, y - 30, x + tw + 40, y + th + 44], radius=24, fill=(217, 119, 6, 235))
    d.multiline_text((x, y), text, font=f, fill="white", spacing=14, align="center")
    img.save(path)


def main() -> None:
    ap = argparse.ArgumentParser()
    ap.add_argument("video")
    ap.add_argument("srt")
    ap.add_argument("--start", type=float, required=True)
    ap.add_argument("--end", type=float, required=True)
    ap.add_argument("--title", default="")
    ap.add_argument("--out", required=True)
    a = ap.parse_args()
    ff = imageio_ffmpeg.get_ffmpeg_exe()
    out = Path(a.out).resolve()
    with tempfile.TemporaryDirectory() as tmp:
        tmp = Path(tmp)
        shutil.copy(a.video, tmp / "in.mp4")
        (tmp / "subs.srt").write_text(shift_srt(a.srt, a.start, a.end), encoding="utf-8")
        title_png(a.title.replace("\\n", "\n"), tmp / "title.png")
        style = ("FontName=Yu Gothic UI,FontSize=17,Bold=1,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,"
                 "BorderStyle=1,Outline=3,Shadow=0,Alignment=2,MarginV=36")
        graph = (
            "[0:v]split[a][b];"
            f"[a]scale={W}:{H}:force_original_aspect_ratio=increase,crop={W}:{H},boxblur=30:2,eq=brightness=-0.15[bg];"
            f"[b]scale={W}:-2[fg];"
            "[bg][fg]overlay=(W-w)/2:(H-h)/2[v1];"
            "[v1][1:v]overlay=0:0[v2];"
            "[v2]subtitles=subs.srt:charenc=UTF-8:original_size=1080x1920:force_style='" + style + "'[v]"
        )
        subprocess.run([ff, "-y", "-ss", str(a.start), "-to", str(a.end), "-i", "in.mp4", "-i", "title.png",
                        "-filter_complex", graph, "-map", "[v]", "-map", "0:a", "-r", "30",
                        "-c:v", "libx264", "-pix_fmt", "yuv420p", "-c:a", "aac", str(out)],
                       cwd=tmp, check=True, capture_output=True)
    print(f"作成しました: {out}")


if __name__ == "__main__":
    main()
