"""熔断门封装: 后端故障必须报错而非放行(降级方向铁律,与 QuotaGate 同构)。"""

from __future__ import annotations

from typing import TYPE_CHECKING

from polygateway.errors import GovernanceBackendError, SourceNotConfiguredError

if TYPE_CHECKING:
    from polygateway.ports import GateDecision, GateUpdate, ProviderGate
    from polygateway.types import SourceConfig


class BreakerGate:
    """RetryMW 面向熔断后端的唯一入口;包装一切后端异常。"""

    def __init__(self, gate: ProviderGate, *, scope: str) -> None:
        self._gate = gate
        # 后端故障即 scope 级不可用,异常须携 scope 供调用方定位(issue #7 §3.3)
        self._scope = scope

    async def try_enter(self, source: SourceConfig, owner: str) -> GateDecision:
        try:
            return await self._gate.try_enter(source.name, owner)
        except (GovernanceBackendError, SourceNotConfiguredError):
            raise
        except Exception as exc:
            raise GovernanceBackendError(
                f"熔断后端故障(try_enter): {exc}", scope=self._scope
            ) from exc

    async def record_success(
        self, entry: GateDecision, *, count_attempt: bool = True
    ) -> GateUpdate:
        try:
            return await self._gate.record_success(entry, count_attempt=count_attempt)
        except (GovernanceBackendError, SourceNotConfiguredError):
            raise
        except Exception as exc:
            raise GovernanceBackendError(
                f"熔断后端故障(record_success): {exc}", scope=self._scope
            ) from exc

    async def record_failure(
        self, entry: GateDecision, reason: str, force_open: bool
    ) -> GateUpdate:
        try:
            return await self._gate.record_failure(entry, reason, force_open)
        except (GovernanceBackendError, SourceNotConfiguredError):
            raise
        except Exception as exc:
            raise GovernanceBackendError(
                f"熔断后端故障(record_failure): {exc}", scope=self._scope
            ) from exc

    async def release_probe(self, entry: GateDecision) -> GateUpdate:
        try:
            return await self._gate.release_probe(entry)
        except (GovernanceBackendError, SourceNotConfiguredError):
            raise
        except Exception as exc:
            raise GovernanceBackendError(
                f"熔断后端故障(release_probe): {exc}", scope=self._scope
            ) from exc

    async def retry_after_s(self, sources: tuple[str, ...]) -> float:
        try:
            return await self._gate.retry_after_s(sources)
        except (GovernanceBackendError, SourceNotConfiguredError):
            raise
        except Exception as exc:
            raise GovernanceBackendError(
                f"熔断后端故障(retry_after_s): {exc}", scope=self._scope
            ) from exc
