package cn.axzo.workflow.common.model.request.bpmn.task;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

import static cn.axzo.workflow.common.constant.BpmnConstants.DUMMY_ASSIGNEE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.HIDDEN_ASSIGNEE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.ROBOT_ASSIGNEE_ID;


/**
 * 该模型的属性, 尽量给全, 虽然部分字段是非必填, 但实际上是为了兼容不同场景.如 ouId: 工人是没人的,但是从业人员一定会有.
 * <p>
 * 统一的工作流中的人员模型,兼容不同的业务方,如安心筑"唯一"人的定义需要工作台+身份 ID+身份类型;<br/>
 * 而枢智业务则只需要简单的 userId 即可
 * <p>
 * 为了解决各种业务的差异,统一定义该模型,以大范围覆盖小范围的方式进行兼容.
 *
 * @author wangli
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Validated
@Slf4j
public class BpmnTaskDelegateAssigner implements Serializable {

    private static final long serialVersionUID = -8106887960942113552L;

    /**
     * 审核人标识, 应该必传
     * <p>
     * 枢智:用户 ID
     * 安心筑:身份 ID
     */
    private String assignee;

    /**
     * 审核人标识扩展信息
     * <p>
     * 枢智:可不传
     * 安心筑:身份 Type   应该必传
     */
    private String assigneeType;

    /**
     * 审核人姓名, 应该必传
     * <p>
     * 枢智:用户姓名
     * 安心筑:用户姓名
     */
    private String assignerName;

    /**
     * 对应安心筑特殊的PersonId
     * <p>
     * 仅安心筑使用,  应该必传
     */
    private String personId;

    /**
     * 所属租户, 必传
     * <p>
     * 枢智: 企业 ID
     * 安心筑: 工作台 ID
     */
    private String tenantId;

    /**
     * 人所在的单位 ID
     * 仅安心筑使用, 工人可以没有, 其他身份一定需要
     */
    private String ouId;

    /**
     * 该属性业务接入时无需关系. 尽量保证其他属性都设值.
     * 头像
     */
    private String avatar;

    public final String buildAssigneeId_1_2_1() {
        if (StringUtils.hasLength(assigneeType)) {
            return tenantId + "|" + assignee + "|" + assigneeType;
        }
        return tenantId + "|" + assignee;
    }

    /**
     * @since 1.3.0 版本起, 使用 ouId + personId 作为审批人唯一标识
     */
    public final String buildAssigneeId() {
        if (StringUtils.hasLength(ouId)) {
            return ouId + "|" + personId;
        } else {
            return "|" + personId;
        }
    }

    public final boolean comparePersonIdToOther(BpmnTaskDelegateAssigner other) {
        return Objects.equals(personId, other.getPersonId());
    }

    /**
     * 对引擎表中存的真实 assignee 进行比对
     *
     * @param assignee
     * @return true 是同一人
     */
    public final boolean comparePersonIdToOther(String assignee) {
        log.info("comparePersonIdToOther: {}, current PersonId: {}", assignee, personId);
        if (!StringUtils.hasText(assignee)) {
            return false;
        }

        List<String> filterAssignee = Lists.newArrayList(NO_ASSIGNEE, HIDDEN_ASSIGNEE_ID, ROBOT_ASSIGNEE_ID,
                DUMMY_ASSIGNEE_ID);
        // 多版本兼容
        if (filterAssignee.contains(assignee)) {
            return false;
        }

        try {
            String[] split = assignee.split("\\|");
            if (split.length == 2) {
                if (Objects.equals(split[1], personId)) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.error("审批人模型数据比对发现意外数据, assignee: " + assignee);
        }
        return false;
    }

    public static BpmnTaskDelegateAssigner buildDummyAssigner(String assignee,
                                                              String assigneeType,
                                                              String assignerName) {
        return buildDummyAssigner(assignee, assigneeType, assignerName, "", "", NO_TENANT_ID);
    }

    public static BpmnTaskDelegateAssigner buildDummyAssigner(String assignee,
                                                              String assigneeType,
                                                              String assignerName,
                                                              String personId,
                                                              String ouId,
                                                              String tenantId) {
        return new BpmnTaskDelegateAssigner()
                .setAssignee(assignee)
                .setAssigneeType(assigneeType)
                .setAssignerName(assignerName)
                .setPersonId(personId)
                .setOuId(ouId)
                .setTenantId(tenantId);
    }

    public String toJson() {
        return JSON.toJSONString(this);
    }


    /**
     * 兼容版本间的不同类型转换成审批人模型
     *
     * @param request 目前存在两种类型,一种为 BpmnTaskDelegateAssigner 实例对象, 另一种为 String 类型的 JSON 数据
     * @return
     */
    public static BpmnTaskDelegateAssigner toObjectCompatible(Object request) {
        if (Objects.isNull(request)) {
            return null;
        }
        if (request instanceof BpmnTaskDelegateAssigner) {
            return (BpmnTaskDelegateAssigner) request;
        } else if (request instanceof String) {
            return toObject((String) request);
        } else {
            return null;
        }
    }

    public static BpmnTaskDelegateAssigner toObject(String jsonStr) {
        return JSON.parseObject(jsonStr, BpmnTaskDelegateAssigner.class);
    }
}
