"""ffmpeg 미디어 변환 — 레터박스(9:16 검은 띠) 굽기.

핵심: 캡컷 scale/transform 의미 추측(함정)을 피하려 영상을 미리 정확한 캔버스
비율로 구워둔다. 결과 mp4 는 이미 9:16 → 캡컷에서 scale 1.0 으로 정확히 일치.
부수효과: AV1/webm → h264 재인코딩으로 캡컷 미리보기 문제도 해소.
"""
from __future__ import annotations

import os
import subprocess
from typing import Tuple


def make_frame(out_png: str, *, top_bar: int, bottom_top: int,
               band_color: Tuple[int, int, int] = (0, 0, 0),
               canvas: Tuple[int, int] = (1080, 1920)) -> str:
    """명시적 좌표로 프레임 생성: 상단 띠(0~top_bar) + 투명 가운데 + 하단 띠(bottom_top~H).

    하단 띠를 크게(bottom_top 낮게) 잡으면 영상이 위로 올라가고 하단에 댓글 캡쳐용
    빈 공간이 생긴다. 띠는 band_color 불투명, 가운데는 투명(영상이 비침).
    배경.png 흰밴드 자동감지(make_transparent_frame) 대신 이걸 쓰면 레이아웃을
    코드 상수로 정확히 통제할 수 있다.
    """
    from PIL import Image  # 지연 import

    W, H = canvas
    out = Image.new("RGBA", (W, H), (0, 0, 0, 0))
    band = (*band_color, 255)
    px = out.load()
    for y in range(H):
        if y < top_bar or y >= bottom_top:
            for x in range(W):
                px[x, y] = band
    out.save(out_png)
    return out_png


def extract_audio(src: str, out_path: str) -> str:
    """오디오만 압축 mp3로 추출 (Gemini 받아쓰기 전송용, mono 16k 48k)."""
    subprocess.run(
        ["ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-i", src,
         "-vn", "-ac", "1", "-ar", "16000", "-b:a", "48k", out_path],
        check=True, encoding="utf-8", errors="replace",
    )
    return out_path


def detect_white_band(template_png: str) -> Tuple[int, int]:
    """검정-흰색-검정 템플릿에서 흰 밴드(영상 영역) [top, bottom] 픽셀 반환."""
    from PIL import Image  # 지연 import

    im = Image.open(template_png).convert("RGB")
    W, H = im.size
    x = W // 2
    whites = [y for y in range(H)
              if min(im.getpixel((x, y))) > 200]
    if not whites:
        return 0, H
    return whites[0], whites[-1] + 1


def make_transparent_frame(template_png: str, out_png: str,
                           band_color: Tuple[int, int, int] = (0, 0, 0)) -> str:
    """검정-흰색-검정 배경 템플릿 → 상하 띠는 band_color 로, 가운데(흰색)는 투명으로.

    영상 위에 '프레임'으로 올려 상하 띠로 가리고 가운데는 영상이 비치게 한다.
    band_color=(0,0,0) 검은 띠(기본), (255,255,255) 흰 띠.
    흰색 밴드 경계를 자동 검출(중앙 컬럼 스캔).
    """
    from PIL import Image  # 지연 import

    im = Image.open(template_png).convert("RGB")
    W, H = im.size
    x = W // 2

    def is_white(y: int) -> bool:
        r, g, b = im.getpixel((x, y))
        return r > 200 and g > 200 and b > 200

    whites = [y for y in range(H) if is_white(y)]
    if whites:
        top, bot = whites[0], whites[-1] + 1   # 흰색 밴드 = 투명 처리 구간
    else:
        top, bot = 0, H

    r, g, b = band_color
    out = Image.new("RGBA", (W, H), (0, 0, 0, 0))
    px = out.load()
    for y in range(H):
        opaque = (y < top) or (y >= bot)
        if not opaque:
            continue
        for xx in range(W):
            px[xx, y] = (r, g, b, 255)
    out.save(out_png)
    return out_png


def make_solid(out_png: str, color: Tuple[int, int, int] = (255, 255, 255),
               canvas: Tuple[int, int] = (1080, 1920)) -> str:
    """단색 전체 캔버스 PNG 생성(흰 배경 레이어 등). 가운데 빈 곳까지 그 색으로."""
    from PIL import Image  # 지연 import
    W, H = canvas
    Image.new("RGB", (W, H), color).save(out_png)
    return out_png


# ── 템플릿 레이아웃 (1080×1920) ──
# 상단 제목 띠 | 영상(좌우 살짝 크롭, 크게) | 하단 채널 띠
TPL_W, TPL_H = 1080, 1920
TPL_TOP_BAR = 410          # 상단 검은 띠(제목)
TPL_VIDEO_H = 1000         # 영상 영역 높이 (410~1410)
# 하단 띠 = 1920 - 410 - 1000 = 510 (채널/출처)

TPL_VIDEO_TOP = TPL_TOP_BAR
TPL_VIDEO_BOTTOM = TPL_TOP_BAR + TPL_VIDEO_H


def to_template(
    src: str,
    out_path: str,
    *,
    crf: int = 20,
) -> str:
    """영상을 템플릿 비디오 영역(1080×1000, 좌우 cover 크롭)에 채우고 상하 검은 띠로
    1080×1920 합성. 영상 틀만 굽고(제목/자막/채널은 캡컷 텍스트로 별도), scale 함정 회피.
    """
    vf = (
        f"scale={TPL_W}:{TPL_VIDEO_H}:force_original_aspect_ratio=increase,"
        f"crop={TPL_W}:{TPL_VIDEO_H},"
        f"pad={TPL_W}:{TPL_H}:0:{TPL_VIDEO_TOP}:color=black,"
        f"setsar=1"
    )
    cmd = [
        "ffmpeg", "-y", "-hide_banner", "-loglevel", "error",
        "-i", src, "-vf", vf,
        "-c:v", "libx264", "-preset", "veryfast", "-crf", str(crf),
        "-pix_fmt", "yuv420p", "-c:a", "aac", "-ar", "44100",
        out_path,
    ]
    subprocess.run(cmd, check=True, encoding="utf-8", errors="replace")
    return out_path


def to_letterbox(
    src: str,
    out_path: str,
    *,
    canvas: Tuple[int, int] = (1080, 1920),
    crf: int = 20,
) -> str:
    """가로 영상을 canvas(기본 9:16) 가운데 두고 위아래 검은 띠로 채운 mp4 생성.

    scale=...:force_original_aspect_ratio=decrease 로 캔버스 안에 비율 유지하며 축소,
    pad 로 가운데 정렬 + 나머지 검정. 전체 클립을 그대로(타임라인 보존) 재인코딩.
    """
    cw, ch = canvas
    vf = (
        f"scale={cw}:{ch}:force_original_aspect_ratio=decrease,"
        f"pad={cw}:{ch}:(ow-iw)/2:(oh-ih)/2:color=black,"
        f"setsar=1"
    )
    cmd = [
        "ffmpeg", "-y", "-hide_banner", "-loglevel", "error",
        "-i", src, "-vf", vf,
        "-c:v", "libx264", "-preset", "veryfast", "-crf", str(crf),
        "-pix_fmt", "yuv420p", "-c:a", "aac", "-ar", "44100",
        out_path,
    ]
    subprocess.run(cmd, check=True, encoding="utf-8", errors="replace")
    return out_path
