package com.infoepoch.pms.agent.domain.baisc.organization;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.infoepoch.pms.agent.common.utils.SnowFlake;
import com.infoepoch.pms.agent.domain.baisc.user.User;
import org.apache.commons.lang3.StringUtils;

import javax.validation.ValidationException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 组织
 */
public class Organization {

    // region

    public void setName(String name) {
        this.name = name;
    }

    public void setPId(String pId) {
        this.pId = pId;
    }

    public void setParentOrgCode(String parentOrgCode) {
        this.parentOrgCode = parentOrgCode;
    }

    public void setLevel(Integer level) {
        this.level = level;
    }

    public void setFrontDisabled(Boolean frontDisabled) {
        this.frontDisabled = frontDisabled;
    }

    // endregion

    // region

    public Organization() {
    }

    /**
     * 新增室经理组织
     */
    public Organization(String id, String name, String shortName, String oaOrgCode, String displayOrder, String pId, String parentOrgCode,
                        Integer level) {
        this.id = id;
        this.name = name;
        this.shortName = shortName;
        this.oaOrgCode = oaOrgCode;
        this.displayOrder = displayOrder;
        this.pId = pId;
        this.parentOrgCode = parentOrgCode;
        this.level = level;

        this.disabled = false;
    }

    /**
     *
     */
    public Organization(String id, String name, String shortName, boolean disabled, String description, String oaOrgCode,
                        String hrOrgCode, String pId, String displayOrder, String parentOrgCode, Integer level) {
        this.id = id;
        this.name = name;
        this.shortName = shortName;
        this.disabled = disabled;
        this.description = description;
        this.oaOrgCode = oaOrgCode;
        this.hrOrgCode = hrOrgCode;
        this.pId = pId;
        this.displayOrder = displayOrder;
        this.parentOrgCode = parentOrgCode;
        this.level = level;
    }

    /**
     * 构造函数，新建
     */
    public Organization(String name, String shortName, boolean disabled, String description
            , String oaOrgCode, String hrOrgCode, String pId, String displayOrder, String parentOrgCode, Integer level) {

        name = StringUtils.trim(name);
        if (StringUtils.isEmpty(name))
            throw new ValidationException("名称不能为空。");

        this.id = SnowFlake.instant().nextId().toString();
        this.name = name;
        this.shortName = shortName;
        this.disabled = disabled;
        this.description = description;
        this.oaOrgCode = oaOrgCode;
        this.hrOrgCode = hrOrgCode;
        this.pId = pId;
        this.displayOrder = displayOrder;
        this.parentOrgCode = parentOrgCode;
        this.level = level;
    }

    /**
     * OA同步修改
     *
     * @param name
     * @param shortName
     * @param oaOrgCode
     * @param hrOrgCode
     * @param displayOrder
     */
    public void modify(String name, String shortName, String oaOrgCode, String hrOrgCode, String displayOrder, boolean disabled) {
        this.name = name;
        this.shortName = shortName;
        this.oaOrgCode = oaOrgCode;
        this.hrOrgCode = hrOrgCode;
        this.displayOrder = displayOrder;
        this.disabled = disabled;
    }

    /**
     * 修改
     */
    public void modify(String name, String shortName, boolean disabled, String description
            , String oaOrgCode, String hrOrgCode, String displayOrder, String parentOrgCode, Integer level) {

        name = StringUtils.trim(name);
        if (StringUtils.isEmpty(name))
            throw new ValidationException("名称不能为空。");

        this.name = name;
        this.shortName = shortName;
        this.disabled = disabled;
        this.description = description;
        this.oaOrgCode = oaOrgCode;
        this.hrOrgCode = hrOrgCode;
        this.displayOrder = displayOrder;
        this.parentOrgCode = parentOrgCode;
        this.level = level;
    }

    // endregion

    //region 属性
    private String id;          //id （组织机构code）
    private String name;        //全称
    private String shortName;   //简称 (❌)
    private boolean disabled;   //是否禁用
    private String description; //描述 （❌）
    private String oaOrgCode;   //OA组织编码 （组织机构编码）
    private String hrOrgCode;   //HR组织编码 （❌）
    private String displayOrder;        //显示顺序
    private String pId;    //父组织机构id
    private String parentOrgCode; // 父组织机构编码
    private Integer level;

    private Boolean frontDisabled;//前端组件禁用选择

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getShortName() {
        return shortName;
    }

    public boolean isDisabled() {
        return disabled;
    }

    public String getDescription() {
        return description;
    }

    public String getOaOrgCode() {
        return oaOrgCode;
    }

    public String getOaOrgCodeNotNull() {
        return oaOrgCode == null ? "999999" : oaOrgCode;
    }

    public String getHrOrgCode() {
        return hrOrgCode;
    }

    public String getDisplayOrder() {
        return displayOrder;
    }

    public String getpId() {
        return pId;
    }

    public String getParentOrgCode() {
        return parentOrgCode;
    }

    /**
     * 获取排序值
     */

    public Integer getDisplayOrderValue() {
        if (displayOrder == null)
            return 999999;
        return Integer.parseInt(displayOrder);
    }

    public Integer getLevel() {
        return level == null ? 1 : level;
    }

    public Boolean getFrontDisabled() {
        return frontDisabled;
    }


//endregion

    //region 下级组织
    //下级组织
    private List<Organization> children = new ArrayList<>();

    /**
     * 下级组织
     */
    public List<Organization> getChildren() {
        return children.stream().sorted(Comparator.comparing(Organization::getDisplayOrderValue)).collect(Collectors.toList());
    }

    /**
     * 是否有下级组织，此属性需参与Json序列化
     */
    @JsonProperty
    public boolean hasChildren() {
        return children.size() > 0;
    }

    /**
     * 取所有下级组织id
     *
     * @param includeSelf 是否包含自身
     * @return
     */
    public List<String> getAllChildrenId(boolean includeSelf) {
        List<String> list = new ArrayList<>();
        if (includeSelf)
            list.add(id);

        if (children != null && children.size() > 0) {
            for (Organization child : children) {
                list.addAll(child.getAllChildrenId(true));
            }
        }

        return list;
    }

    //endregion

    /**
     * 添加子组织集合
     */
    public void addChildren(List<Organization> organizations) {
        children.addAll(organizations);
    }

    public void setChildren(List<Organization> value) {
        children = value;
    }

    @JsonIgnore
    private List<User> userList;

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Organization organization = (Organization) o;
        return disabled == organization.disabled &&
                Objects.equals(id, organization.id) &&
                Objects.equals(name, organization.name) &&
                Objects.equals(shortName, organization.shortName) &&
                Objects.equals(description, organization.description) &&
                Objects.equals(oaOrgCode, organization.oaOrgCode) &&
                Objects.equals(hrOrgCode, organization.hrOrgCode) &&
                Objects.equals(pId, organization.pId) &&
                Objects.equals(displayOrder, organization.displayOrder);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, shortName, disabled, description, oaOrgCode, hrOrgCode, pId, displayOrder);
    }
}
