"""
Minimal safety utilities for new commands.

Provides a SafetyContext that can be used to emit AgenticResult payloads and
enforce apply/force policies for remote mutations. This is intentionally light
touch for initial rollout (PR2a).
"""

from __future__ import annotations

import uuid
from dataclasses import dataclass
from typing import Any, Dict, List, Optional

import click

from g_gremlin.contracts import AgenticResult, AgenticWarning, BatchOutcome, DeltaSummary


DEFAULT_MIN_CONFIDENCE = 0.85


@dataclass
class SafetyContext:
    command: str
    remote_mutation: bool = False
    min_confidence_to_apply: float = DEFAULT_MIN_CONFIDENCE
    correlation_id: str = ""

    def __post_init__(self) -> None:
        if not self.correlation_id:
            try:
                ctx = click.get_current_context(silent=True)
                if ctx and ctx.obj and ctx.obj.get("correlation_id"):
                    self.correlation_id = str(ctx.obj.get("correlation_id"))
                else:
                    self.correlation_id = str(uuid.uuid4())
            except Exception:
                self.correlation_id = str(uuid.uuid4())

    def enforce_apply(self, apply: bool, force: bool = False) -> None:
        """
        Enforce that remote mutations require --apply unless force overrides.
        Non-remote commands are unaffected.
        """
        if not self.remote_mutation:
            return
        if not apply and not force:
            raise click.ClickException(
                "This command performs remote mutations. Re-run with --apply to execute."
            )

    def enforce_confidence(self, confidence: Optional[float], apply: bool, force: bool = False) -> None:
        """Block low-confidence mutations unless --force."""
        if not self.remote_mutation or not apply:
            return
        if confidence is None:
            return
        if confidence < self.min_confidence_to_apply and not force:
            raise click.ClickException(
                f"Confidence {confidence:.2f} below minimum {self.min_confidence_to_apply:.2f}. "
                "Re-run with --force to proceed."
            )

    def build_result(
        self,
        status: str,
        dry_run: bool,
        result: Dict[str, Any],
        *,
        confidence_score: float = 1.0,
        confidence_blocked: bool = False,
        warnings: Optional[List[AgenticWarning]] = None,
        delta_summary: Optional[DeltaSummary] = None,
        batch_outcome: Optional[BatchOutcome] = None,
        provenance: Optional[Dict[str, Any]] = None,
        error: Optional[str] = None,
    ) -> AgenticResult:
        agentic = AgenticResult(
            command=self.command,
            status=status,
            dry_run=dry_run,
            confidence_score=confidence_score,
            confidence_blocked=confidence_blocked,
            warnings=warnings or [],
            delta_summary=delta_summary,
            batch_outcome=batch_outcome,
            provenance=provenance,
            result=result,
            error=error,
            correlation_id=self.correlation_id,
        )
        try:
            ctx = click.get_current_context(silent=True)
            if ctx is not None:
                ctx.ensure_object(dict)
                command_path = ctx.command_path or ""
                if command_path == "root":
                    callback = getattr(getattr(ctx, "command", None), "callback", None)
                    callback_name = getattr(callback, "__name__", "")
                    if callback_name:
                        command_path = callback_name.lstrip("_")
                if command_path:
                    ctx.obj.setdefault("command_path", command_path)
                ctx.obj["last_agentic_result"] = agentic.to_dict()
        except Exception:
            pass
        return agentic
