package cn.nianxx.thhotel.integrations.messaging.agentbus.adapter;

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Component;

/**
 * AgentBus 连接与入站处理状态。该组件只保存安全计数器和错误代码，不保存 raw frame。
 */
@Component
public class AgentBusConnectionStatus {

    private final AtomicLong receivedFrameCount = new AtomicLong();
    private final AtomicLong capturedFrameCount = new AtomicLong();
    private final AtomicLong ignoredFrameCount = new AtomicLong();
    private final AtomicLong rejectedFrameCount = new AtomicLong();
    private final AtomicLong failedFrameCount = new AtomicLong();

    private volatile boolean connected;
    private volatile boolean sessionReady;
    private volatile String lastErrorCode;
    private volatile String lastErrorSummary;
    private volatile OffsetDateTime connectedAt;
    private volatile OffsetDateTime disconnectedAt;
    private volatile OffsetDateTime lastFrameReceivedAt;

    /**
     * 标记 WebSocket 已连接。
     */
    public void markConnected() {
        connected = true;
        connectedAt = nowUtc();
        lastErrorCode = null;
        lastErrorSummary = null;
    }

    /**
     * 标记 WebSocket 已断开。
     */
    public void markDisconnected() {
        connected = false;
        sessionReady = false;
        disconnectedAt = nowUtc();
    }

    /**
     * 标记已经收到 AgentBus session.ready 控制事件。
     */
    public void markSessionReady() {
        sessionReady = true;
    }

    /**
     * 记录收到一条入站 frame。
     */
    public void markFrameReceived() {
        receivedFrameCount.incrementAndGet();
        lastFrameReceivedAt = nowUtc();
    }

    /**
     * 记录一条 frame 已写入 SourceMessage Inbox。
     */
    public void markFrameCaptured() {
        capturedFrameCount.incrementAndGet();
    }

    /**
     * 记录一条控制事件或配置关闭时被忽略的 frame。
     */
    public void markFrameIgnored() {
        ignoredFrameCount.incrementAndGet();
    }

    /**
     * 记录一条因为安全边界被拒绝的 frame。
     */
    public void markFrameRejected(String errorCode, String errorSummary) {
        rejectedFrameCount.incrementAndGet();
        recordError(errorCode, errorSummary);
    }

    /**
     * 记录一条处理失败的 frame。
     */
    public void markFrameFailed(String errorCode, String errorSummary) {
        failedFrameCount.incrementAndGet();
        recordError(errorCode, errorSummary);
    }

    /**
     * 记录最近一次安全错误代码和摘要，不包含 raw frame、Token 或正文。
     */
    public void recordError(String errorCode, String errorSummary) {
        lastErrorCode = errorCode;
        lastErrorSummary = errorSummary;
    }

    /**
     * 返回当前安全状态快照，供系统探针接口展示。
     */
    public AgentBusStatusSnapshot snapshot() {
        return new AgentBusStatusSnapshot(
                connected,
                sessionReady,
                receivedFrameCount.get(),
                capturedFrameCount.get(),
                ignoredFrameCount.get(),
                rejectedFrameCount.get(),
                failedFrameCount.get(),
                lastErrorCode,
                lastErrorSummary,
                connectedAt,
                disconnectedAt,
                lastFrameReceivedAt
        );
    }

    /**
     * 生成 UTC 时间，保证状态接口时间字段稳定。
     */
    private OffsetDateTime nowUtc() {
        return OffsetDateTime.now(ZoneOffset.UTC);
    }
}
