"""Prometheus 指标定义：发送计数/耗时/失败/图像匹配/DB校验/队列/运行态/熔断/缓存/自适应等待。

所有指标用 prometheus_client 定义，通过 /metrics 端点暴露（app.py 挂载）。

prometheus_client 为可选依赖：缺失时本模块降级为 NoOp 桩件，所有指标调用
（.labels()/.inc()/.set()/.observe() 等）变为 no-op，bridge 核心业务不受影响。
app.py 的 /metrics 端点会同步降级（make_asgi_app 仍 ImportError → 禁用并 warning）。
"""

from __future__ import annotations

import logging
import time

logger = logging.getLogger("woc-bridge")


class _NoOpMetric:
    """prometheus_client 缺失时的 NoOp 桩件。

    覆盖上层所有调用模式：实例化（接收任意参数）+
    .labels(*args, **kwargs) → 返回 self，支持链式 .inc()/.dec()/.set()/.observe()。
    所有操作 no-op，不持有任何状态。
    """

    __slots__ = ()

    def __init__(self, *args, **kwargs) -> None:
        pass

    def labels(self, *args, **kwargs) -> "_NoOpMetric":
        return self

    def inc(self, amount: float = 1.0) -> None:
        pass

    def dec(self, amount: float = 1.0) -> None:
        pass

    def set(self, value: float) -> None:
        pass

    def observe(self, amount: float) -> None:
        pass

    def info(self, val) -> None:
        pass


try:
    from prometheus_client import (
        Counter,
        Gauge,
        Histogram,
        Info,
    )
    _PROMETHEUS_AVAILABLE = True
except ImportError:
    logger.warning(
        "[metrics] prometheus_client 不可用，指标降级为 NoOp；"
        "/metrics 端点将自动禁用，核心业务不受影响"
    )
    _PROMETHEUS_AVAILABLE = False
    # 类型忽略：故意将多个指标类名重绑定为同一个 NoOp 类，
    # 使所有 Counter/Gauge/Histogram/Info(...) 实例化返回 _NoOpMetric 实例
    Counter = Gauge = Histogram = Info = _NoOpMetric  # type: ignore[assignment,misc]

# 发送总数（按 flow_name / result 标签）
send_total = Counter(
    "woc_send_total",
    "Total send operations",
    ["flow_name", "result"],  # result: success / failed / skipped
)

# 发送耗时分布
send_duration = Histogram(
    "woc_send_duration_seconds",
    "Send operation duration in seconds",
    ["flow_name"],
    buckets=(0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0),
)

# 按失败状态分类的失败计数
send_failed_by_state = Counter(
    "woc_send_failed_by_state_total",
    "Send failures by flow state",
    ["flow_name", "state"],
)

# 图像匹配置信度分布
image_match_confidence = Histogram(
    "woc_image_match_confidence",
    "OpenCV template match confidence",
    ["kind"],
    buckets=(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.0),
)

# DB 校验耗时
db_verify_duration = Histogram(
    "woc_db_verify_duration_seconds",
    "DB verify duration in seconds",
    buckets=(0.1, 0.2, 0.5, 1.0, 2.0, 3.0, 5.0),
)

# 发送队列待处理数
send_queue_pending = Gauge(
    "woc_send_queue_pending",
    "Send queue pending count",
)

# WeChat 运行态（1=running, 0=not running）
wechat_running = Gauge(
    "woc_wechat_running",
    "WeChat process running state (1=running, 0=not)",
)

# 熔断器状态（0=closed, 1=open, 2=half_open）
circuit_state = Gauge(
    "woc_circuit_state",
    "Circuit breaker state (0=closed, 1=open, 2=half_open)",
    ["name"],
)

# 会话缓存命中
session_cache_hit = Counter(
    "woc_session_cache_hit_total",
    "Session cache hit count",
    ["result"],  # hit / miss
)

# 自适应等待超时计数
adaptive_wait_timeout = Counter(
    "woc_adaptive_wait_timeout_total",
    "Adaptive wait timeout count",
    ["kind"],
)

# 首次发送耗时（无缓存）
send_duration_first = Histogram(
    "woc_send_duration_first_seconds",
    "First send duration (no session cache) in seconds",
    buckets=(1.0, 3.0, 5.0, 10.0, 30.0, 60.0),
)

# 缓存命中后的发送耗时
send_duration_cached = Histogram(
    "woc_send_duration_cached_seconds",
    "Cached send duration (session cache hit) in seconds",
    buckets=(0.5, 1.0, 2.0, 5.0, 10.0, 30.0),
)


# UIActionScheduler 调度器指标
ui_action_executed = Counter(
    "woc_ui_action_executed_total",
    "UI actions executed total",
    ["priority"],  # CRITICAL / HIGH / NORMAL / LOW
)

ui_action_wait_duration = Histogram(
    "woc_ui_action_wait_duration_seconds",
    "UI action wait duration (queue wait time)",
    buckets=(0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0),
)

ui_action_exec_duration = Histogram(
    "woc_ui_action_exec_duration_seconds",
    "UI action execution duration",
    ["priority"],
    buckets=(0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0),
)

ui_action_timeout = Counter(
    "woc_ui_action_timeout_total",
    "UI action wait timeout count",
)

ui_action_rate_limited = Counter(
    "woc_ui_action_rate_limited_total",
    "UI action rate limited (queue full) count",
)

ui_action_fast_fail = Counter(
    "woc_ui_action_fast_fail_total",
    "UI action fast-fail count (wechat dead window)",
)


def set_circuit_state(name: str, state_int: int) -> None:
    """更新熔断器状态指标。

    Args:
        name: 熔断器名称
        state_int: 0=closed, 1=open, 2=half_open
    """
    circuit_state.labels(name=name).set(state_int)
