"""Pure RCA domain engine.

This module computes RCA attempt records without performing persistence I/O.
"""

from __future__ import annotations

from typing import Any

from .gates import evaluate_gate, normalize_gate_mode
from .rca_transitions import (
    allowed_actions_for_state,
    apply_stall_rule,
    build_transition_history,
    default_next_required,
    derive_attempt_progress,
    normalize_action,
    resolve_attempt_values,
    resolve_merged_evidence_refs,
    resolve_previous_values,
    resolve_target_state,
)


def build_rca_attempt_record(
    *,
    previous: dict[str, Any] | None,
    attempt_id: str,
    session_id: str,
    action: str,
    failure_signature: str,
    evidence_refs: list[str] | None = None,
    hypothesis: str | None = None,
    experiment_plan: str | None = None,
    proposed_change_summary: str | None = None,
    verification_result: dict[str, Any] | None = None,
    gate_mode: str | None = None,
    exploratory: bool = False,
    override_reason: str | None = None,
    stall_threshold: int = 3,
    exploration_budget: int = 2,
    now: str,
) -> dict[str, Any]:
    normalized_mode = normalize_gate_mode(gate_mode)
    normalized_action = normalize_action(action)
    (
        previous_state,
        previous_hypothesis,
        previous_plan,
        previous_refs,
        previous_verification,
        previous_change_summary,
    ) = resolve_previous_values(previous)

    merged_refs = resolve_merged_evidence_refs(previous_refs, evidence_refs)
    (
        hypothesis_value,
        plan_value,
        verification_value,
        proposed_change_value,
    ) = resolve_attempt_values(
        previous_hypothesis=previous_hypothesis,
        previous_plan=previous_plan,
        previous_change_summary=previous_change_summary,
        previous_verification=previous_verification,
        hypothesis=hypothesis,
        experiment_plan=experiment_plan,
        proposed_change_summary=proposed_change_summary,
        verification_result=verification_result,
    )
    same_signature, repeat_count, hypothesis_delta, plan_advanced, hypothesis_advanced = (
        derive_attempt_progress(
            previous=previous,
            failure_signature=failure_signature,
            previous_hypothesis=previous_hypothesis,
            hypothesis_value=hypothesis_value,
            previous_plan=previous_plan,
            plan_value=plan_value,
        )
    )

    # Evaluate the current attempt against the previously available budget,
    # then consume one unit if we repeated the same signature without advancing.
    budget_before_attempt = (
        int(previous.get("exploration_budget_remaining", exploration_budget))
        if previous
        else exploration_budget
    )
    if same_signature and not hypothesis_advanced:
        exploration_budget_remaining = max(budget_before_attempt - 1, 0)
    else:
        exploration_budget_remaining = exploration_budget

    if same_signature and not hypothesis_advanced:
        gate_budget_remaining = budget_before_attempt
    else:
        gate_budget_remaining = exploration_budget

    gate_payload = {
        "evidence_refs": merged_refs,
        "hypothesis": hypothesis_value,
        "experiment_plan": plan_value,
        "verification_result": verification_value,
        "exploratory": exploratory,
        "override_reason": override_reason or "",
        "hypothesis_advanced": hypothesis_advanced,
    }
    gate = evaluate_gate(
        mode=normalized_mode,
        current_state=previous_state,
        action=normalized_action,
        payload=gate_payload,
        repeated_signature_count=repeat_count,
        exploration_budget=exploration_budget,
        exploration_budget_remaining=gate_budget_remaining,
    )

    target_state = resolve_target_state(previous_state, normalized_action, gate.allowed)
    target_state, gate_warnings = apply_stall_rule(
        target_state=target_state,
        gate_warnings=list(gate.warnings),
        same_signature=same_signature,
        repeat_count=repeat_count,
        stall_threshold=stall_threshold,
        hypothesis_advanced=hypothesis_advanced,
        plan_advanced=plan_advanced,
        normalized_action=normalized_action,
    )
    transition_history = build_transition_history(
        previous=previous,
        now=now,
        normalized_action=normalized_action,
        previous_state=previous_state,
        target_state=target_state,
        gate_allowed=gate.allowed,
        gate_mode=gate.mode,
    )
    created_at = str(previous.get("created_at") or now) if previous else now
    next_required = (
        list(gate.next_required) if gate.next_required else default_next_required(target_state)
    )

    return {
        "attempt_id": attempt_id,
        "session_id": session_id,
        "state": target_state,
        "failure_signature": failure_signature,
        "repeat_count": repeat_count,
        "evidence_refs": merged_refs,
        "hypothesis": hypothesis_value or None,
        "hypothesis_delta": hypothesis_delta,
        "experiment_plan": plan_value or None,
        "proposed_change_summary": proposed_change_value or None,
        "verification_result": verification_value,
        "gate_feedback": gate.to_dict(),
        "gate_warnings": gate_warnings,
        "allowed_actions": allowed_actions_for_state(target_state),
        "next_required": next_required,
        "exploratory": exploratory,
        "exploration_budget_remaining": exploration_budget_remaining,
        "transition_history": transition_history,
        "created_at": created_at,
        "updated_at": now,
    }
