"""Compliance-enhanced kill switch with full audit trail."""

from __future__ import annotations

import logging
import time
from typing import Any

from horizon.compliance._access import AccessControl
from horizon.compliance._audit import AuditTrail
from horizon.compliance._types import AuditEventType

logger = logging.getLogger("horizon.compliance.kill_switch")


class ComplianceKillSwitch:
    """Emergency halt with RBAC enforcement and audit trail.

    Extends the engine's built-in kill switch with:
    - Role-based access control (requires RISK_MANAGER or higher)
    - Full audit trail with reason, actor, open positions at time of activation
    - Deactivation requires justification
    """

    def __init__(
        self,
        audit: AuditTrail,
        access: AccessControl,
    ) -> None:
        self._audit = audit
        self._access = access
        self._engine: Any = None
        self._active = False
        self._activated_by: str | None = None
        self._activated_at: float | None = None
        self._reason: str | None = None

    def bind_engine(self, engine: Any) -> None:
        """Bind to the trading engine."""
        self._engine = engine

    @property
    def is_active(self) -> bool:
        return self._active

    def activate(self, reason: str, actor: str) -> None:
        """Activate the kill switch.

        Cancels all orders, logs open positions, and prevents new orders.

        Args:
            reason: Why the kill switch was activated.
            actor: Identity of the person/system activating it.

        Raises:
            PermissionError: If actor lacks permission.
            RuntimeError: If no engine is bound.
        """
        self._access.require_permission(actor, "activate_kill_switch")

        if self._engine is None:
            raise RuntimeError("No engine bound to compliance kill switch")

        # Snapshot positions before killing
        try:
            positions = [
                {
                    "market_id": p.market_id,
                    "side": str(p.side),
                    "size": p.size,
                    "avg_entry_price": p.avg_entry_price,
                }
                for p in self._engine.positions()
            ]
        except Exception:
            positions = []

        # Activate engine kill switch
        self._engine.activate_kill_switch(reason)

        self._active = True
        self._activated_by = actor
        self._activated_at = time.time()
        self._reason = reason

        self._audit.record(
            AuditEventType.KILL_SWITCH_ACTIVATED, actor,
            {
                "reason": reason,
                "positions_at_activation": positions,
                "position_count": len(positions),
            },
        )

        logger.critical("KILL SWITCH activated by %s: %s", actor, reason)

    def deactivate(self, actor: str, justification: str) -> None:
        """Deactivate the kill switch.

        Args:
            actor: Identity of the person deactivating it.
            justification: Why it is safe to resume trading.

        Raises:
            PermissionError: If actor lacks permission.
        """
        self._access.require_permission(actor, "deactivate_kill_switch")

        if self._engine is not None:
            self._engine.deactivate_kill_switch()

        self._audit.record(
            AuditEventType.KILL_SWITCH_DEACTIVATED, actor,
            {
                "justification": justification,
                "was_active_for_secs": time.time() - self._activated_at if self._activated_at else 0,
                "originally_activated_by": self._activated_by,
                "original_reason": self._reason,
            },
        )

        self._active = False
        logger.info("Kill switch deactivated by %s: %s", actor, justification)

    def status(self) -> dict[str, Any]:
        """Return current kill switch status."""
        return {
            "active": self._active,
            "activated_by": self._activated_by,
            "activated_at": self._activated_at,
            "reason": self._reason,
        }
