package cn.axzo.workflow.starter;

import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.enums.RpcInvokeModeEnum;
import cn.axzo.workflow.starter.api.WorkflowCoreService;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC;

/**
 * Workflow Engine Starter Properties
 * <p>
 * 全量参数参考：META-INF/application.yml.demo
 *
 * @author wangli
 * @since 2024/5/21 15:24
 */
@ConfigurationProperties(prefix = "workflow.engine.starter")
public class WorkflowEngineStarterProperties {
    /**
     * 是否开启原始 ProcessInstanceApi、ProcessTaskApi 等类似的 FeignClient，具体可用的 API 参考 cn.axzo.workflow.client.feign 包
     * <p>
     * 默认 false，优先 starter 提供的 coreService、manageServer。
     * 为 true 时，会为当前应用注册原始 xxxApi FeignClient
     */
//    private Boolean metaFeign = false;

    /**
     * 特殊用途，不建议接入方使用
     */
//    private Boolean manageable = false;

    /**
     * <h3>该参数只针对<strong color=orange>非</strong>容器环境生效</h3>
     * 本地启动时,是否将本地的 MQ 消费者加入集群消费组
     * <pre>
     * 默认 false, 本地启动应用时, 将创建消息组名称中含有"debugging"的消费组.
     * 否则, 本地启动应用时, 消费者将加入容器环境, 进行集群消费.
     * </pre>
     */
    private Boolean joinContainerGroup = false;

    /**
     * <h3>该参数只针对<strong color=orange>非</strong>容器环境生效</h3>
     * 配合 joinContainerGroup 使用，且只在 joinContainerGroup = false 时生效
     * <pre>
     * 在本地有多台开发机同时启动时，又会组成新的集群消费，也会导致消息异常消费，
     * 所以该参数就是为了创建完全唯一的消费者，避免本地开发机组成集群。
     * </pre>
     */
    private String specialId;

    /**
     * WorkflowCoreService 类中所有方法未标记{@link InvokeMode}注解的方法调用时, 默认采用的模式
     *
     * <pre>
     * 如果是同步调用，则直接通过普通 FeignClient 进行调用,
     * 否则将通过 MQ 将 RPC 调用进行解耦
     * </pre>
     * <p>
     * 如果方法上有{@link InvokeMode}注解, 则以注解上的模式优先, 如果还想覆盖注解中的模式,
     * 则可以通过 {@link WorkflowCoreService#sync()}或{@link WorkflowCoreService#async()}方法进行覆盖
     */
    private RpcInvokeModeEnum invokeMode = ASYNC;

    /**
     * 监听流程引擎广播的处理器，异常后的重试相关策略及配置
     */
    @NestedConfigurationProperty
    private BroadcastListenerProperties broadcast = new BroadcastListenerProperties();

    /**
     * 是否开启死信队列的监控的特性，不代表真实开始监控，如果需要默认开始，请设置 monitorStatus = true
     */
    private Boolean enableDlqMonitor = true;

    /**
     * 监控状态，默认 true，真实开始监控 RPC 的私信队列监控
     */
    private Boolean rpcMonitorStatus = true;

    /**
     * 监控死信队列，周期间隔，单位：毫秒
     */
    private long dlqMonitorIntervalInMs = 4 * 60 * 60 * 1000L;

    /**
     * 开启后，会在主动给“工作流小分队”群中发送信息
     * <p>
     * 只针对容器环境中的应用生效
     */
    private Boolean alert = false;

//    public Boolean getMetaFeign() {
//        return metaFeign;
//    }
//
//    public void setMetaFeign(Boolean metaFeign) {
//        this.metaFeign = metaFeign;
//    }
//
//    public Boolean getManageable() {
//        return manageable;
//    }
//
//    public void setManageable(Boolean manageable) {
//        this.manageable = manageable;
//    }

    public Boolean getJoinContainerGroup() {
        return joinContainerGroup;
    }

    public void setJoinContainerGroup(Boolean joinContainerGroup) {
        this.joinContainerGroup = joinContainerGroup;
    }

    public String getSpecialId() {
        return specialId;
    }

    public void setSpecialId(String specialId) {
        this.specialId = specialId;
    }

    public RpcInvokeModeEnum getInvokeMode() {
        return invokeMode;
    }

    public void setInvokeMode(RpcInvokeModeEnum invokeMode) {
        this.invokeMode = invokeMode;
    }

    public BroadcastListenerProperties getBroadcast() {
        return broadcast;
    }

    public void setBroadcast(BroadcastListenerProperties broadcast) {
        this.broadcast = broadcast;
    }

    public Boolean getEnableDlqMonitor() {
        return enableDlqMonitor;
    }

    public void setEnableDlqMonitor(Boolean enableDlqMonitor) {
        this.enableDlqMonitor = enableDlqMonitor;
    }

    public Boolean getRpcMonitorStatus() {
        return rpcMonitorStatus;
    }

    public void setRpcMonitorStatus(Boolean rpcMonitorStatus) {
        this.rpcMonitorStatus = rpcMonitorStatus;
    }

    public long getDlqMonitorIntervalInMs() {
        return dlqMonitorIntervalInMs;
    }

    public void setDlqMonitorIntervalInMs(long dlqMonitorIntervalInMs) {
        this.dlqMonitorIntervalInMs = dlqMonitorIntervalInMs;
    }

    public Boolean getAlert() {
        return alert;
    }

    public void setAlert(Boolean alert) {
        this.alert = alert;
    }
}
