package com.huangzj.base.cmd;

import com.huangzj.cmd.gen.CmdRpcEnvelope;
import com.google.protobuf.Message;
import org.springframework.util.ClassUtils;

/**
 * 强类型 PB 命令：CTS/STC 由 {@link ProtoRegistryAutoConfigurer} 根据本类泛型与 {@link Cmd} 自动注册为
 * {@link ProtoInfo}；网络层解析请求并创建 {@link CommandContext#responseBuilder()}，子类只实现 {@link #run}。
 */
public abstract class AbstractTypedPbCommand<C extends Message, B extends Message.Builder> implements GameCommand {

    @Override
    public CmdRpcEnvelope execute(CommandContext ctx, CmdRpcEnvelope request) throws Exception {
        if (ctx.protoInfo() == null || ctx.decodedRequest() == null || ctx.responseBuilder() == null) {
            throw new IllegalStateException(
                    "缺少 ProtoInfo 或网络层未解码: "
                            + ClassUtils.getUserClass(getClass()).getName()
                            + "，请确认本类带 @Cmd 且继承 AbstractTypedPbCommand<CTS, STC.Builder> 以自动注册 ProtoInfo");
        }
        @SuppressWarnings("unchecked")
        C cts = (C) ctx.decodedRequest();
        @SuppressWarnings("unchecked")
        B stcBuilder = (B) ctx.responseBuilder();
        run(ctx, cts, stcBuilder);
        // CmdRpcEnvelope头原样带回：保证请求方（含区服↔跨服 link_seq）能把响应与请求对齐
        return CmdRpcEnvelope.newBuilder()
                .setServiceId(request.getServiceId())
                .setMethodId(request.getMethodId())
                .setCrossRet(request.getCrossRet())
                .setLinkSeq(request.getLinkSeq())
                .setPayload(stcBuilder.build().toByteString())
                .build();
    }

    protected abstract void run(CommandContext ctx, C cts, B stcBuilder) throws Exception;
}
