"""
Blender 5.1 script: render preview frames of matador animations to PNG.
Run:  blender --background matador_v02.blend --python render_anim_preview.py

Outputs to Blender/preview/ directory:
  walk_frame_00.png .. walk_frame_09.png
  idle_frame_00.png

Use this to visually verify bone orientations BEFORE exporting to Godot.
"""
import bpy
import os
import math

# ── Configuration ─────────────────────────────────────────────────────────────
PREVIEW_DIR = os.path.join(os.path.dirname(bpy.data.filepath), "preview")
RENDER_RES_X = 512
RENDER_RES_Y = 512
WALK_FRAMES = 10      # number of evenly-spaced frames to render from walk cycle
CAMERA_DISTANCE = 5.0
CAMERA_HEIGHT = 1.0
CAMERA_ANGLES = [0, 90]  # degrees — front and side views

os.makedirs(PREVIEW_DIR, exist_ok=True)

# ── Find armature ─────────────────────────────────────────────────────────────
arm_obj = next((o for o in bpy.data.objects if o.type == 'ARMATURE'), None)
if arm_obj is None:
    raise RuntimeError("No armature found in scene")

# ── Setup render settings ─────────────────────────────────────────────────────
scene = bpy.context.scene
scene.render.resolution_x = RENDER_RES_X
scene.render.resolution_y = RENDER_RES_Y
scene.render.resolution_percentage = 100
scene.render.film_transparent = True
scene.render.image_settings.file_format = 'PNG'
scene.render.image_settings.color_mode = 'RGBA'
scene.render.engine = 'BLENDER_EEVEE'

# ── Create or reuse camera ────────────────────────────────────────────────────
cam_data = bpy.data.cameras.get("PreviewCam") or bpy.data.cameras.new("PreviewCam")
cam_data.lens = 50
cam_obj = bpy.data.objects.get("PreviewCamObj")
if cam_obj is None:
    cam_obj = bpy.data.objects.new("PreviewCamObj", cam_data)
    scene.collection.objects.link(cam_obj)
scene.camera = cam_obj

# ── Create or reuse key light ─────────────────────────────────────────────────
light_data = bpy.data.lights.get("PreviewLight") or bpy.data.lights.new("PreviewLight", type='SUN')
light_data.energy = 3.0
light_obj = bpy.data.objects.get("PreviewLightObj")
if light_obj is None:
    light_obj = bpy.data.objects.new("PreviewLightObj", light_data)
    scene.collection.objects.link(light_obj)
light_obj.rotation_euler = (math.radians(45), math.radians(30), 0)

# ── Create or reuse fill light ────────────────────────────────────────────────
fill_data = bpy.data.lights.get("PreviewFill") or bpy.data.lights.new("PreviewFill", type='SUN')
fill_data.energy = 1.0
fill_obj = bpy.data.objects.get("PreviewFillObj")
if fill_obj is None:
    fill_obj = bpy.data.objects.new("PreviewFillObj", fill_data)
    scene.collection.objects.link(fill_obj)
fill_obj.rotation_euler = (math.radians(60), math.radians(-45), 0)

# ── Ensure armature is visible ────────────────────────────────────────────────
arm_obj.hide_render = False
arm_obj.hide_viewport = False
for child in arm_obj.children:
    child.hide_render = False
    child.hide_viewport = False


def position_camera(angle_deg: float) -> None:
    """Place camera at given horizontal angle around the armature center."""
    rad = math.radians(angle_deg)
    cam_obj.location = (
        math.sin(rad) * CAMERA_DISTANCE,
        CAMERA_HEIGHT,
        math.cos(rad) * CAMERA_DISTANCE,
    )
    # Point camera at armature center (roughly hip height)
    target = arm_obj.location.copy()
    target.y = 0.9
    direction = target - cam_obj.location
    rot_quat = direction.to_track_quat('-Z', 'Y')
    cam_obj.rotation_euler = rot_quat.to_euler()


def render_action(action_name: str, frame_count: int) -> None:
    """Render frame_count evenly-spaced frames of the named action."""
    action = bpy.data.actions.get(action_name)
    if action is None:
        print(f"WARNING: Action '{action_name}' not found, skipping")
        return

    # Assign action
    if arm_obj.animation_data is None:
        arm_obj.animation_data_create()
    arm_obj.animation_data.action = action

    frame_start = int(action.frame_range[0])
    frame_end = int(action.frame_range[1])
    total_frames = max(frame_end - frame_start, 1)

    for angle_deg in CAMERA_ANGLES:
        position_camera(angle_deg)
        angle_label = f"{angle_deg:03d}deg"

        for i in range(frame_count):
            t = i / max(frame_count - 1, 1) if frame_count > 1 else 0
            frame = frame_start + int(t * total_frames)
            scene.frame_set(frame)

            filename = f"{action_name}_{angle_label}_frame_{i:02d}.png"
            filepath = os.path.join(PREVIEW_DIR, filename)
            scene.render.filepath = filepath
            bpy.ops.render.render(write_still=True)
            print(f"  Rendered: {filename}")


# ── Render all animations ─────────────────────────────────────────────────────
print("=" * 60)
print("RENDERING ANIMATION PREVIEWS")
print("=" * 60)

render_action("walk", WALK_FRAMES)
render_action("idle", 1)

# ── Cleanup preview objects (optional — keep them for re-runs) ────────────────
print("=" * 60)
print(f"Preview images saved to: {PREVIEW_DIR}")
print(f"Total actions rendered: {len([a for a in ['walk', 'idle'] if bpy.data.actions.get(a)])}")
print("=" * 60)
