"""최종 산출 — `render_args`, `wizard_outcome` 과 persistence 액션."""
from __future__ import annotations

from typing import Any
import json

from okstra_ctl.legacy_model_selection import serialize_host_session_context
from okstra_ctl.wizard_stage_intent import (
    WizardStageIntent,
    WizardStageIntentError,
    resolve_wizard_stage_intent,
)

from .state import (
    WizardError,
    WizardState,
    _load_role_profile_for_state,
    _role_selection_enabled,
)
from .roles import _host_session_context, _selectable_static_requirements


def _stage_intent(state: WizardState) -> WizardStageIntent:
    """This state's stage selection, resolved once for every consumer.

    `render_args` needs the single stage this run prepares; `wizard_outcome`
    needs the chain the skill drives. Deriving them separately would let the two
    disagree about which stage the run is for.
    """
    try:
        return resolve_wizard_stage_intent(
            task_type=state.task_type,
            selected_stage=state.selected_stage,
            selected_stages=state.selected_stages,
        )
    except WizardStageIntentError as exc:
        raise WizardError(str(exc)) from exc


def render_role_args(state: WizardState) -> list[str]:
    """Return ordered canonical role count/model CLI tokens."""
    role_argv: list[str] = []
    if _role_selection_enabled(state):
        profile = _load_role_profile_for_state(state)
        requirements = _selectable_static_requirements(state, profile)
        for requirement in profile.roles:
            if (
                requirement.dynamic
                or requirement.min_count == requirement.max_count
            ):
                continue
            if requirement.role not in state.role_counts:
                continue
            count = state.role_counts[requirement.role]
            if count <= 0:
                continue
            role_argv.extend([
                "--role-count",
                f"{requirement.role}={count}",
            ])
        ordered_roles = [requirement.role for requirement in requirements]
    else:
        ordered_roles = []
    for role in state.role_models:
        if role not in ordered_roles:
            ordered_roles.append(role)
    for role in ordered_roles:
        for model_ref in state.role_models.get(role, []):
            role_argv.extend(["--role-model", f"{role}={model_ref}"])
    return role_argv


def render_args(state: WizardState) -> dict[str, Any]:
    """Convert finalized state into ``okstra render-bundle`` argument map."""
    if state.aborted:
        raise WizardError(
            "wizard was aborted by the user — render-args is unavailable"
        )
    base_ref = (
        ""
        if state.reuse_worktree or state.task_type == "final-verification"
        else state.base_ref
    )
    stage_intent = _stage_intent(state)
    pr_template = (
        state.pr_template_path
        if state.task_type == "release-handoff"
        else ""
    )
    evidence_paths = [
        path
        for path in (state.feature_evidence_path, state.project_evidence_path)
        if path
    ]
    rendered: dict[str, Any] = {
        "project-root": state.project_root,
        "project-id": state.project_id,
        "task-group": state.task_group,
        "task-id": state.task_id,
        "task-type": state.task_type,
        "task-brief": (
            "" if state.task_type == "release-handoff" else state.brief_path
        ),
        "analysis-target": state.analysis_target,
        "evidence-inputs": ",".join(evidence_paths),
        "approved-plan": state.approved_plan_path,
        "stage": stage_intent.stage,
        "stages": state.handoff_stages,
        "base-ref": base_ref,
        "directive": state.directive,
        "related-tasks": state.related_tasks_raw,
        "clarification-response": state.clarification_response_path,
        "selected-direction": state.selected_direction_path,
        "reverify-scope": (
            state.reverify_scope
            if state.task_type == "implementation-planning" else ""
        ),
        "pr-template-path": pr_template,
        "fix-cycle": state.fix_cycle,
        "host-session-context-json": serialize_host_session_context(
            _host_session_context(state)
        ),
    }
    role_argv = render_role_args(state)
    rendered["role-count"] = [
        role_argv[index + 1]
        for index, token in enumerate(role_argv)
        if token == "--role-count"
    ]
    rendered["role-model"] = [
        role_argv[index + 1]
        for index, token in enumerate(role_argv)
        if token == "--role-model"
    ]
    if state.user_authorization:
        stages = _stage_intent(state).chain_stages.split(",") if _stage_intent(state).chain_stages else []
        if state.user_authorization.get("stageScope", []) != stages:
            raise WizardError("confirmed stage scope changed; obtain confirmation for the changed stages")
        if state.user_authorization.get("scope") != rendered:
            raise WizardError("confirmed scope changed; obtain confirmation for the changed inputs")
        rendered["user-authorization-json"] = json.dumps(state.user_authorization, ensure_ascii=False)
    return rendered
