# SPDX-FileCopyrightText: 2026 Les Fées Spéciales
#
# SPDX-License-Identifier: GPL-3.0-or-later

import bpy

import os
import platform
import subprocess
from pathlib import Path

from storyliner.api import shot as sl_shot
from storyliner.api import storyliner_props


def batch_render_playblasts(
    do_render,
    file_path,
    quality,
    resolution_percentage,
    studio,
    project,
    sequence,
    version,
    do_mark_images=True,
    video_codec="H264",
    safety_margins=False,
    concat_shots=True,
    concat_movie_path=None,
):

    sl_props = storyliner_props.get_storyliner(bpy.context.scene)
    shots = storyliner_props.get_shots_list(sl_props, ignore_disabled=True)
    if not shots:
        print("No Storyliner shots found.")
        return

    if not file_path:
        if bpy.context.blend_data.filepath:
            file_path = os.path.splitext(bpy.context.blend_data.filepath)[0]
        else:
            file_path = "Untitled"
        file_path = bpy.path.ensure_ext(file_path, ".mp4")

    file_path = Path(file_path)
    render_dir = file_path.parent
    output_name = file_path.name
    files_path = ""
    shots_list_path = (render_dir / "movies.list").as_posix()

    storyliner_props.set_edit_play_mode(storyliner_props, False)

    if hasattr(bpy.context.scene, "camera_overscan"):
        bpy.context.scene.camera_overscan.activate = safety_margins
    else:
        print("Camera Overscan add-on not found, margins can't be enabled and rendered.")
        return

    for shot in shots:
        if not shot.enabled:
            continue
        print(sequence, " - ", shot.name)

        if sl_shot.is_camera_valid(shot):
            storyliner_props.set_current_shot(sl_props, shot)

            bpy.context.scene.frame_start = sl_shot.get_start(shot)
            bpy.context.scene.frame_end = sl_shot.get_end(shot)

            shot_output_name = f"{sequence}_{shot.name}_{output_name}"
            shot_output_path = (render_dir / shot_output_name).as_posix()

            bpy.ops.lfs.playblast(
                do_render=do_render,
                filepath=shot_output_path,
                studio=studio,
                project=project,
                sequence=sequence,
                scene=shot.name,
                quality=quality,
                version=version,
                do_mark_images=do_mark_images,
                video_codec=video_codec,
                do_autoplay=False,
                resolution_percentage=resolution_percentage,
            )

            files_path += f"file '{shot_output_name}'\n"
            # Needed to avoid having an offset on first video frame.
            # https://ffmpeg.org/ffmpeg-formats.html#Syntax
            files_path += "inpoint 0\n"

    with open(shots_list_path, "w") as f:
        f.write(files_path)

    if concat_shots:
        frame_rate = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base
        ffmpeg_args = ["ffmpeg", "-y"]
        ffmpeg_args.extend(["-f", "concat"])
        ffmpeg_args.extend(["-safe", "0"])
        ffmpeg_args.extend(["-r", str(frame_rate)])
        ffmpeg_args.extend(["-i", shots_list_path])
        ffmpeg_args.extend(["-vcodec", "copy"])
        ffmpeg_args.extend(["-acodec", "copy"])
        ffmpeg_args.extend(["-r", str(frame_rate)])
        ffmpeg_args.extend([concat_movie_path])

        print("FFmpeg command:")
        print(" ".join(ffmpeg_args))

        try:
            proc = subprocess.run(
                ffmpeg_args, check=True, shell=platform.system() == "Windows"
            )
        except subprocess.CalledProcessError as e:
            print(e.returncode, e.cmd, e.stderr)
            raise e
