"""绕过中央 AgentToolCall 的真实运行入口使用的独立事务商业桥。"""

from __future__ import annotations

import uuid
from collections.abc import Callable, Mapping
from dataclasses import dataclass
from datetime import UTC, datetime
from decimal import Decimal, InvalidOperation
from typing import Any, Literal

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models.commercial import CommercialEntitlement, TenantSubscription
from app.models.commercial_runtime import CommercialRuntimeReservation
from app.schemas.commercial import CommercialCostEventCreate, UsageMeterEventCreate
from app.services.commercial_access_policy import (
    CommercialConfigurationError,
    CommercialConflictError,
)
from app.services.commercial_metering import CommercialMeteringService
from app.services.commercial_runtime_costs import runtime_cost_config
from app.services.commercial_runtime_policy import preflight_quantity
from app.services.commercial_runtime_registry import (
    ConfiguredRuntimeMeter,
    matching_runtime_meters,
)
from app.services.commercial_runtime_reservations import (
    CommercialRuntimeReservationService,
)

DirectOperationOutcome = Literal[
    "succeeded",
    "empty",
    "provider_rejected",
    "postprocess_failed",
    "not_sent",
    "outcome_unknown",
]
DirectOperationStatus = Literal[
    "created",
    "replayed",
    "released",
    "skipped",
    "denied",
    "reconciliation_required",
]

_SUPPORTED_BASES = {
    "call",
    "bytes",
    "events",
    "input_tokens",
    "objects",
    "output_tokens",
    "pages",
    "total_tokens",
    "duration_ms",
}
_SOURCE_SYSTEM = "direct-runtime-metering"
_METER_VERSION = "direct-operation-v1"


@dataclass(frozen=True, slots=True)
class DirectOperationIdentity:
    tenant_id: str
    operation_key: str
    run_key: str
    tool_type: str
    tool_name: str
    started_at: datetime
    provider: str | None = None
    model_name: str | None = None

    def __post_init__(self) -> None:
        object.__setattr__(self, "tenant_id", _required(self.tenant_id, "tenant_id", 64))
        object.__setattr__(
            self,
            "operation_key",
            _required(self.operation_key, "operation_key", 500),
        )
        object.__setattr__(self, "run_key", _required(self.run_key, "run_key", 500))
        object.__setattr__(self, "tool_type", _required(self.tool_type, "tool_type", 30))
        object.__setattr__(self, "tool_name", _required(self.tool_name, "tool_name", 100))
        object.__setattr__(self, "started_at", _utc(self.started_at))
        object.__setattr__(self, "provider", _optional(self.provider, 80))
        object.__setattr__(self, "model_name", _optional(self.model_name, 160))

    @property
    def operation_call_id(self) -> str:
        return _stable_uuid(
            "direct-operation",
            self.tenant_id,
            self.operation_key,
            self.tool_type,
            self.tool_name,
        )

    @property
    def metering_run_id(self) -> str:
        return f"direct-{_stable_uuid('direct-run', self.tenant_id, self.run_key)}"


@dataclass(frozen=True, slots=True)
class DirectOperationPermit:
    enforced: bool
    allowed: bool
    reason_code: str
    reason: str
    operation_call_id: str
    reservation_id: str | None = None
    entitlement_id: str | None = None
    quantity_basis: str | None = None
    reserved_quantity: Decimal | None = None


@dataclass(frozen=True, slots=True)
class DirectOperationResult:
    status: DirectOperationStatus
    reason_code: str
    reason: str
    operation_call_id: str
    reservation_id: str | None = None
    quantity_basis: str | None = None
    quantity: Decimal | None = None
    usage_event_id: str | None = None
    cost_event_id: str | None = None
    requires_reconciliation: bool = False


class CommercialDirectOperationBridge:
    """每次 permit/completion 都使用自有 Session，不提交调用方业务事务。"""

    def __init__(
        self,
        session_factory: Callable[[], Session],
        *,
        lookup_session: Session | None = None,
    ) -> None:
        self.session_factory = session_factory
        self.lookup_session = lookup_session

    def permit(
        self,
        identity: DirectOperationIdentity,
        *,
        requested_quantity: int | Decimal | None = None,
        required_quantity_basis: str | None = None,
    ) -> DirectOperationPermit:
        if self.lookup_session is not None:
            with self.lookup_session.no_autoflush:
                configured = matching_runtime_meters(
                    self.lookup_session,
                    tenant_id=identity.tenant_id,
                    tool_type=identity.tool_type,
                    tool_name=identity.tool_name,
                    as_of=identity.started_at,
                )
            if not configured:
                return DirectOperationPermit(
                    enforced=False,
                    allowed=True,
                    reason_code="runtime_meter_not_configured",
                    reason="该真实运行入口未显式配置商业计量。",
                    operation_call_id=identity.operation_call_id,
                )
        with self.session_factory() as db:
            try:
                meters = matching_runtime_meters(
                    db,
                    tenant_id=identity.tenant_id,
                    tool_type=identity.tool_type,
                    tool_name=identity.tool_name,
                    as_of=identity.started_at,
                )
                if not meters:
                    db.rollback()
                    return DirectOperationPermit(
                        enforced=False,
                        allowed=True,
                        reason_code="runtime_meter_not_configured",
                        reason="该真实运行入口未显式配置商业计量。",
                        operation_call_id=identity.operation_call_id,
                    )
                meter = _unique_meter(meters)
                basis, reserved = _preflight(
                    meter,
                    requested_quantity=requested_quantity,
                    required_quantity_basis=required_quantity_basis,
                )
                reservation, _created = CommercialRuntimeReservationService(db).reserve(
                    tenant_id=identity.tenant_id,
                    entitlement_id=meter.entitlement.id,
                    run_id=identity.metering_run_id,
                    tool_call_id=identity.operation_call_id,
                    tool_type=identity.tool_type,
                    tool_name=identity.tool_name,
                    quantity_basis=basis,
                    reserved_quantity=reserved,
                    meter_config=meter.config,
                    as_of=identity.started_at,
                )
                db.commit()
                return DirectOperationPermit(
                    enforced=True,
                    allowed=True,
                    reason_code="reserved",
                    reason="真实运行调用已完成独立事务额度预占。",
                    operation_call_id=identity.operation_call_id,
                    reservation_id=reservation.id,
                    entitlement_id=reservation.entitlement_id,
                    quantity_basis=reservation.quantity_basis,
                    reserved_quantity=Decimal(reservation.reserved_quantity),
                )
            except (
                CommercialConfigurationError,
                CommercialConflictError,
                LookupError,
                ValueError,
            ) as error:
                db.rollback()
                return DirectOperationPermit(
                    enforced=True,
                    allowed=False,
                    reason_code="quota_or_configuration_denied",
                    reason=str(error),
                    operation_call_id=identity.operation_call_id,
                )
            except Exception:
                db.rollback()
                raise

    def complete(
        self,
        identity: DirectOperationIdentity,
        *,
        outcome: DirectOperationOutcome,
        authoritative_quantities: Mapping[str, int | Decimal | None],
        completed_at: datetime,
        usage_source: str,
        usage_availability: str,
    ) -> DirectOperationResult:
        completed = _utc(completed_at)
        request_sent = outcome != "not_sent"
        with self.session_factory() as db:
            reservation = CommercialRuntimeReservationService(db).by_tool_call(
                identity.operation_call_id
            )
            if reservation is None:
                db.rollback()
                if not request_sent:
                    return _result(
                        identity,
                        status="skipped",
                        reason_code="not_sent_without_reservation",
                        reason="调用未发送且没有商业预占，无需计量。",
                    )
                return self._backlog_without_reservation(
                    identity,
                    outcome=outcome,
                    quantities=authoritative_quantities,
                    completed_at=completed,
                )
            reservation_id = reservation.id
            if not request_sent:
                try:
                    CommercialRuntimeReservationService(db).release(
                        reservation_id,
                        reason_code="direct_operation_not_sent",
                        settled_at=completed,
                    )
                    db.commit()
                    return _result(
                        identity,
                        status="released",
                        reason_code="not_sent_released",
                        reason="调用未发送，商业预占已释放。",
                        reservation=reservation,
                    )
                except CommercialConflictError:
                    db.rollback()
                    return self._terminal_replay(identity, reservation_id)

            actual = _actual_quantity(
                reservation.quantity_basis,
                authoritative_quantities,
                started_at=identity.started_at,
                completed_at=completed,
            )
            if actual is None:
                db.rollback()
                return self._mark_reconciliation(
                    identity,
                    reservation_id,
                    reason_code="authoritative_usage_unavailable",
                    actual_quantity=None,
                )
            if actual > Decimal(reservation.reserved_quantity):
                db.rollback()
                return self._mark_reconciliation(
                    identity,
                    reservation_id,
                    reason_code="actual_exceeds_preflight_reservation",
                    actual_quantity=actual,
                )
            try:
                locked = CommercialRuntimeReservationService(db).mark_committed(
                    reservation_id,
                    actual,
                    settled_at=completed,
                )
                result = _record_facts(
                    db,
                    identity=identity,
                    reservation=locked,
                    outcome=outcome,
                    quantity=actual,
                    usage_source=usage_source,
                    usage_availability=usage_availability,
                )
                db.commit()
                return result
            except Exception:
                db.rollback()
                return self._mark_reconciliation(
                    identity,
                    reservation_id,
                    reason_code="direct_operation_metering_failed",
                    actual_quantity=actual,
                )

    def _backlog_without_reservation(
        self,
        identity: DirectOperationIdentity,
        *,
        outcome: DirectOperationOutcome,
        quantities: Mapping[str, int | Decimal | None],
        completed_at: datetime,
    ) -> DirectOperationResult:
        del outcome
        with self.session_factory() as db:
            meters = matching_runtime_meters(
                db,
                tenant_id=identity.tenant_id,
                tool_type=identity.tool_type,
                tool_name=identity.tool_name,
                as_of=identity.started_at,
            )
            if not meters:
                db.rollback()
                return _result(
                    identity,
                    status="skipped",
                    reason_code="runtime_meter_not_configured",
                    reason="调用已发生，但该入口未显式启用商业计量。",
                )
            try:
                meter = _unique_meter(meters)
                basis, reserved = _preflight(meter)
                actual = _actual_quantity(
                    basis,
                    quantities,
                    started_at=identity.started_at,
                    completed_at=completed_at,
                )
                backlog, _created = CommercialRuntimeReservationService(
                    db
                ).record_reconciliation_backlog(
                    tenant_id=identity.tenant_id,
                    entitlement_id=meter.entitlement.id,
                    run_id=identity.metering_run_id,
                    tool_call_id=identity.operation_call_id,
                    tool_type=identity.tool_type,
                    tool_name=identity.tool_name,
                    quantity_basis=basis,
                    reserved_quantity=reserved,
                    actual_quantity=actual,
                    meter_config=meter.config,
                    resolution_code="missing_pre_execution_reservation",
                    as_of=identity.started_at,
                )
                db.commit()
                return _result(
                    identity,
                    status="reconciliation_required",
                    reason_code="missing_pre_execution_reservation",
                    reason="真实调用缺少执行前预占，已冻结额度并进入补偿队列。",
                    reservation=backlog,
                    quantity=actual,
                    requires_reconciliation=True,
                )
            except Exception:
                db.rollback()
                raise

    def _mark_reconciliation(
        self,
        identity: DirectOperationIdentity,
        reservation_id: str,
        *,
        reason_code: str,
        actual_quantity: Decimal | None,
    ) -> DirectOperationResult:
        with self.session_factory() as db:
            row = CommercialRuntimeReservationService(db).require_reconciliation(
                reservation_id,
                reason_code=reason_code,
                actual_quantity=actual_quantity,
            )
            db.commit()
            return _result(
                identity,
                status="reconciliation_required",
                reason_code=reason_code,
                reason="真实调用尚不能安全结算，已保留可审计补偿状态。",
                reservation=row,
                quantity=actual_quantity,
                requires_reconciliation=True,
            )

    def _terminal_replay(
        self,
        identity: DirectOperationIdentity,
        reservation_id: str,
    ) -> DirectOperationResult:
        with self.session_factory() as db:
            row = CommercialRuntimeReservationService(db).get_for_update(reservation_id)
            if row.status == "released":
                db.rollback()
                return _result(
                    identity,
                    status="released",
                    reason_code="not_sent_release_replayed",
                    reason="调用未发送，原商业预占已释放。",
                    reservation=row,
                )
            db.rollback()
            raise CommercialConflictError(f"直接运行预占已处于不兼容终态 {row.status}。")


def _record_facts(
    db: Session,
    *,
    identity: DirectOperationIdentity,
    reservation: CommercialRuntimeReservation,
    outcome: DirectOperationOutcome,
    quantity: Decimal,
    usage_source: str,
    usage_availability: str,
) -> DirectOperationResult:
    subscription = db.scalar(
        select(TenantSubscription).where(
            TenantSubscription.tenant_id == identity.tenant_id,
            TenantSubscription.id == reservation.subscription_id,
        )
    )
    entitlement = db.scalar(
        select(CommercialEntitlement).where(
            CommercialEntitlement.tenant_id == identity.tenant_id,
            CommercialEntitlement.subscription_id == reservation.subscription_id,
            CommercialEntitlement.id == reservation.entitlement_id,
        )
    )
    if subscription is None or entitlement is None:
        raise LookupError("直接运行预占引用的订阅或权益不存在。")
    metadata = {
        "meter_version": _METER_VERSION,
        "operation_call_id": identity.operation_call_id,
        "tool_type": identity.tool_type,
        "tool_name": identity.tool_name,
        "quantity_basis": reservation.quantity_basis,
        "entitlement_key": entitlement.entitlement_key,
        "reservation_id": reservation.id,
        "provider": identity.provider,
        "model_name": identity.model_name,
        "outcome": outcome,
        "usage_source": _optional(usage_source, 80),
        "usage_availability": _optional(usage_availability, 40),
    }
    usage, usage_created = CommercialMeteringService(db).record_usage(
        identity.tenant_id,
        UsageMeterEventCreate(
            subscription_id=subscription.id,
            entitlement_id=entitlement.id,
            quantity=quantity,
            occurred_at=_utc(reservation.created_at),
            source_system=_SOURCE_SYSTEM,
            idempotency_key=_usage_key(identity.operation_call_id, entitlement.id),
            subject_type="runtime_provider_attempt",
            subject_id=identity.operation_call_id,
            correlation_id=identity.metering_run_id,
            metadata_json=metadata,
        ),
        actor_type="system",
        actor_id="commercial-direct-runtime-meter",
    )
    cost = runtime_cost_config(
        reservation.meter_config_json.get("internal_cost"),
        entitlement.unit,
    )
    cost_event = None
    cost_created = False
    if cost is not None:
        try:
            with db.begin_nested():
                cost_event, cost_created = CommercialMeteringService(db).record_cost(
                    identity.tenant_id,
                    CommercialCostEventCreate(
                        subscription_id=subscription.id,
                        usage_event_id=usage.id,
                        cost_category=cost.cost_category,  # type: ignore[arg-type]
                        quantity=quantity,
                        unit=cost.unit,
                        unit_cost=cost.unit_cost,
                        original_currency=cost.original_currency,
                        reporting_currency=cost.reporting_currency,
                        fx_rate=cost.fx_rate,
                        provider=cost.provider,
                        sku=cost.sku,
                        model_name=cost.model_name,
                        allocation_key=f"direct-runtime:{entitlement.id}",
                        occurred_at=_utc(reservation.created_at),
                        source_system=_SOURCE_SYSTEM,
                        idempotency_key=_cost_key(
                            identity.operation_call_id,
                            entitlement.id,
                        ),
                        correlation_id=identity.metering_run_id,
                        metadata_json=metadata,
                    ),
                )
        except Exception:
            CommercialRuntimeReservationService(db).require_committed_reconciliation(
                reservation.id,
                reason_code="direct_operation_cost_failed",
            )
            return _result(
                identity,
                status="reconciliation_required",
                reason_code="direct_operation_cost_failed",
                reason="真实用量已持久化，内部成本等待幂等补偿。",
                reservation=reservation,
                quantity=quantity,
                usage_event_id=usage.id,
                requires_reconciliation=True,
            )
    created = usage_created or cost_created
    return _result(
        identity,
        status="created" if created else "replayed",
        reason_code="metered" if created else "idempotent_replay",
        reason="真实运行用量与已配置成本已追加。" if created else "相同真实运行事实已计量。",
        reservation=reservation,
        quantity=quantity,
        usage_event_id=usage.id,
        cost_event_id=cost_event.id if cost_event is not None else None,
    )


def _unique_meter(meters: list[ConfiguredRuntimeMeter]) -> ConfiguredRuntimeMeter:
    if len(meters) != 1:
        raise CommercialConfigurationError("多个权益匹配同一真实运行入口，拒绝重复计量。")
    return meters[0]


def _preflight(
    meter: ConfiguredRuntimeMeter,
    *,
    requested_quantity: int | Decimal | None = None,
    required_quantity_basis: str | None = None,
) -> tuple[str, Decimal]:
    basis = str(meter.config.get("quantity_basis") or "").strip()
    if basis not in _SUPPORTED_BASES:
        raise CommercialConfigurationError("runtime_meter.quantity_basis 未配置或不受支持。")
    required_basis = str(required_quantity_basis or "").strip()
    if required_basis and basis != required_basis:
        raise CommercialConfigurationError(
            f"该真实资源边界只接受 {required_basis} 计量，当前配置为 {basis}。"
        )
    if basis == "call":
        if requested_quantity is not None and _positive_optional(requested_quantity) != 1:
            raise CommercialConfigurationError("call 计量的 requested_quantity 只能是 1。")
        return basis, Decimal("1")
    if "preflight_quantity" not in meter.config:
        raise CommercialConfigurationError(
            "变量用量的直接运行入口必须显式配置可强制的 preflight_quantity。"
        )
    maximum = preflight_quantity([meter.config])
    if requested_quantity is None:
        return basis, maximum
    requested = _positive_optional(requested_quantity)
    if requested is None:
        raise CommercialConfigurationError("requested_quantity 必须是权威正数。")
    if requested > maximum:
        raise CommercialConfigurationError(
            "requested_quantity 超过 runtime_meter.preflight_quantity 硬上限。"
        )
    return basis, requested


def _actual_quantity(
    basis: str,
    quantities: Mapping[str, int | Decimal | None],
    *,
    started_at: datetime,
    completed_at: datetime,
) -> Decimal | None:
    if basis == "call":
        return Decimal("1")
    if basis == "duration_ms":
        milliseconds = int((_utc(completed_at) - _utc(started_at)).total_seconds() * 1000)
        return Decimal(milliseconds) if milliseconds > 0 else None
    if basis == "input_tokens":
        return _positive_optional(quantities.get("input_tokens"))
    if basis == "output_tokens":
        return _positive_optional(quantities.get("output_tokens"))
    if basis in {"bytes", "pages", "objects", "events"}:
        return _positive_optional(quantities.get(basis))
    total = _positive_optional(quantities.get("total_tokens"))
    if total is not None:
        return total
    input_tokens = _positive_optional(quantities.get("input_tokens"))
    output_tokens = _positive_optional(quantities.get("output_tokens"))
    if input_tokens is None or output_tokens is None:
        return None
    return input_tokens + output_tokens


def _result(
    identity: DirectOperationIdentity,
    *,
    status: DirectOperationStatus,
    reason_code: str,
    reason: str,
    reservation: CommercialRuntimeReservation | None = None,
    quantity: Decimal | None = None,
    usage_event_id: str | None = None,
    cost_event_id: str | None = None,
    requires_reconciliation: bool = False,
) -> DirectOperationResult:
    return DirectOperationResult(
        status=status,
        reason_code=reason_code,
        reason=reason,
        operation_call_id=identity.operation_call_id,
        reservation_id=reservation.id if reservation is not None else None,
        quantity_basis=reservation.quantity_basis if reservation is not None else None,
        quantity=quantity,
        usage_event_id=usage_event_id,
        cost_event_id=cost_event_id,
        requires_reconciliation=requires_reconciliation,
    )


def _stable_uuid(domain: str, *parts: str) -> str:
    key = "\x1f".join((domain, *(str(item) for item in parts)))
    return str(uuid.uuid5(uuid.NAMESPACE_URL, f"x-financial:{key}"))


def _usage_key(operation_call_id: str, entitlement_id: str) -> str:
    return f"direct:{operation_call_id}:{entitlement_id}:usage:v1"


def _cost_key(operation_call_id: str, entitlement_id: str) -> str:
    return f"direct:{operation_call_id}:{entitlement_id}:cost:v1"


def _positive_optional(value: Any) -> Decimal | None:
    if value is None or isinstance(value, bool):
        return None
    try:
        parsed = Decimal(str(value))
    except (InvalidOperation, ValueError):
        return None
    if not parsed.is_finite() or parsed <= 0:
        return None
    return parsed


def _required(value: Any, field: str, maximum: int) -> str:
    normalized = str(value or "").strip()
    if not normalized or len(normalized) > maximum:
        raise ValueError(f"{field} is required and must be at most {maximum} characters.")
    return normalized


def _optional(value: Any, maximum: int) -> str | None:
    normalized = str(value or "").strip()
    return normalized[:maximum] or None


def _utc(value: datetime) -> datetime:
    return value.replace(tzinfo=UTC) if value.tzinfo is None else value.astimezone(UTC)
