import os
import subprocess

from .db import get_compile_job, get_track_file_path, get_track_by_id, update_compile_job

VIDEO_DATA_DIR = os.getenv("VIDEO_DATA_DIR", "/app/data/videos")


def _build_concat_cmd(file_paths: list[str], crossfade_sec: float, output_path: str) -> list:
    """FFmpeg command: N audio files → single audio with acrossfade."""
    n = len(file_paths)
    if n == 1:
        # Single track: just copy
        return ["ffmpeg", "-y", "-i", file_paths[0], "-c:a", "libmp3lame", "-q:a", "2", output_path]

    cmd = []
    for fp in file_paths:
        cmd += ["-i", fp]

    # Build acrossfade filter chain
    filter_parts = []
    prev = "0"
    for i in range(1, n):
        out_label = f"a{i:02d}"
        filter_parts.append(f"[{prev}][{i}]acrossfade=d={crossfade_sec}:c1=tri:c2=tri[{out_label}]")
        prev = out_label

    filter_str = ";".join(filter_parts)

    return (
        ["ffmpeg", "-y"]
        + cmd
        + ["-filter_complex", filter_str, "-map", f"[{prev}]", "-c:a", "libmp3lame", "-q:a", "2", output_path]
    )


def _make_gradient_bg(width: int, height: int, output_path: str) -> None:
    """Simple dark gradient background image via FFmpeg."""
    subprocess.run(
        [
            "ffmpeg", "-y",
            "-f", "lavfi",
            "-i", f"color=c=0x111827:size={width}x{height}:rate=1",
            "-frames:v", "1",
            output_path,
        ],
        check=True, capture_output=True,
    )


def _get_audio_duration(path: str) -> float:
    """Return duration in seconds via ffprobe."""
    try:
        result = subprocess.run(
            ["ffprobe", "-v", "error", "-show_entries", "format=duration",
             "-of", "default=noprint_wrappers=1:nokey=1", path],
            capture_output=True, text=True, check=True,
        )
        return float(result.stdout.strip())
    except Exception:
        return 0.0


def run_compile(job_id: int) -> None:
    """Main compile worker — called as BackgroundTask."""
    job = get_compile_job(job_id)
    if not job:
        return

    update_compile_job(job_id, status="rendering")

    try:
        track_ids = job["track_ids"]
        if not track_ids:
            raise ValueError("트랙이 선택되지 않았습니다")

        # Resolve file paths
        file_paths = []
        for tid in track_ids:
            fp = get_track_file_path(tid)
            if not fp or not os.path.exists(fp):
                raise ValueError(f"트랙 파일 없음 (id={tid})")
            file_paths.append(fp)

        out_dir = os.path.join(VIDEO_DATA_DIR, f"compile_{job_id}")
        os.makedirs(out_dir, exist_ok=True)

        # Step 1: concat audio
        audio_path = os.path.join(out_dir, "audio.mp3")
        concat_cmd = _build_concat_cmd(file_paths, job["crossfade_sec"], audio_path)
        subprocess.run(concat_cmd, check=True, capture_output=True)

        duration = _get_audio_duration(audio_path)

        # Step 2: background image
        bg_path = os.path.join(out_dir, "bg.jpg")
        _make_gradient_bg(1920, 1080, bg_path)

        # Step 3: audio + bg → MP4
        output_path = os.path.join(out_dir, "output.mp4")
        subprocess.run(
            [
                "ffmpeg", "-y",
                "-loop", "1", "-i", bg_path,
                "-i", audio_path,
                "-c:v", "libx264", "-tune", "stillimage", "-preset", "fast",
                "-c:a", "aac", "-b:a", "192k",
                "-pix_fmt", "yuv420p",
                "-shortest",
                output_path,
            ],
            check=True, capture_output=True,
        )

        update_compile_job(job_id, status="done", output_path=output_path, duration_sec=duration)

    except subprocess.CalledProcessError as e:
        err = (e.stderr or b"").decode()[-300:]
        update_compile_job(job_id, status="failed", error=err)
    except Exception as e:
        update_compile_job(job_id, status="failed", error=str(e))
