"""Celery Canvas workflow builder.

Translates WorkflowDefinition config into a Celery Canvas (chain/group/chord).
"""
from __future__ import annotations
import logging
from celery import chain, group

logger = logging.getLogger(__name__)


def dispatch_workflow(
    workflow_type: str,
    order_line_id: str,
    params: dict | None = None,
) -> str:
    """Build and dispatch a Celery Canvas workflow. Returns the Celery task/group ID."""
    params = params or {}
    builders = {
        "still": _build_still,
        "turntable": _build_turntable,
        "multi_angle": _build_multi_angle,
        "still_with_exports": _build_still_with_exports,
    }
    builder = builders.get(workflow_type)
    if not builder:
        raise ValueError(f"Unknown workflow type: {workflow_type!r}")
    canvas = builder(order_line_id, params)
    result = canvas.apply_async()
    return str(result.id)


def _build_still(order_line_id: str, params: dict):
    """Still render: resolves STEP path from order_line DB record."""
    from app.domains.rendering.tasks import render_order_line_still_task
    return chain(
        render_order_line_still_task.si(order_line_id, **params)
    )


def _build_turntable(order_line_id: str, params: dict):
    """Turntable animation: requires step_path + output_dir in params."""
    from app.domains.rendering.tasks import render_turntable_task
    step_path = params.get("step_path")
    output_dir = params.get("output_dir")
    if not step_path or not output_dir:
        raise ValueError(
            "turntable workflow requires 'step_path' and 'output_dir' in params"
        )
    remaining = {k: v for k, v in params.items() if k not in ("step_path", "output_dir")}
    return chain(
        render_turntable_task.si(step_path, output_dir, **remaining)
    )


def _build_multi_angle(order_line_id: str, params: dict):
    """Multi-angle stills: renders the same order_line from multiple rotation_z angles."""
    from app.domains.rendering.tasks import render_order_line_still_task
    angles = params.pop("angles", [0, 45, 90])
    return group(
        render_order_line_still_task.si(order_line_id, rotation_z=float(angle), **params)
        for angle in angles
    )


def _build_still_with_exports(order_line_id: str, params: dict):
    """Still render + parallel GLB exports (geometry + production quality).

    Pipeline:
        render_order_line_still_task → group(
            export_gltf_for_order_line_task,
            export_blend_for_order_line_task,
        )
    """
    from app.domains.rendering.tasks import (
        render_order_line_still_task,
        export_gltf_for_order_line_task,
        export_blend_for_order_line_task,
    )
    return chain(
        render_order_line_still_task.si(order_line_id, **params),
        group(
            export_gltf_for_order_line_task.si(order_line_id),
            export_blend_for_order_line_task.si(order_line_id),
        ),
    )
