"""
CLI factory for creating DualSteeringSteeringObject from enriched pairs.

Bridges the argument parser to the Dual Steering training pipeline:
extract args -> compute concept directions per layer -> wrap in steering object.
"""

from __future__ import annotations

import torch

from wisent.core.steering_methods.steering_object import SteeringObjectMetadata
from .dual_steering_steering_object import DualSteeringSteeringObject


def _create_dual_steering_steering_object(
    metadata: SteeringObjectMetadata,
    layer_activations: dict,
    available_layers: list,
    args,
) -> DualSteeringSteeringObject:
    """Create Dual Steering object with per-layer concept directions."""

    num_steps = getattr(args, "dual_steering_num_steps", 3)
    alpha = getattr(args, "dual_steering_alpha", 5e-3)
    eta = getattr(args, "dual_steering_eta", 0.5)
    top_k = getattr(args, "dual_steering_top_k", 256)

    concept_dirs = {}

    for layer_str in available_layers:
        pos_list = layer_activations[layer_str]["positive"]
        neg_list = layer_activations[layer_str]["negative"]
        if not pos_list or not neg_list:
            continue

        pos = torch.stack(
            [t.detach().float().reshape(-1) for t in pos_list], dim=0
        )
        neg = torch.stack(
            [t.detach().float().reshape(-1) for t in neg_list], dim=0
        )

        direction = pos.mean(dim=0) - neg.mean(dim=0)
        layer_int = int(layer_str)
        concept_dirs[layer_int] = direction.detach()

        dir_norm = direction.norm().item()
        print(
            f"   Layer {layer_str}: n_pos={pos.shape[0]}, "
            f"n_neg={neg.shape[0]}, dir_norm={dir_norm:.4f}"
        )

    return DualSteeringSteeringObject(
        metadata=metadata,
        concept_directions=concept_dirs,
        num_steps=num_steps,
        alpha=alpha,
        eta=eta,
        top_k=top_k,
    )
