package com.bcxin.tenant.domain.services.commands;

import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.bcxin.Infrastructures.commands.CommandAbstract;
import com.bcxin.Infrastructures.entities.OperatorValueType;
import com.bcxin.Infrastructures.enums.AbnormalPersonnelEmployeeType;
import com.bcxin.Infrastructures.enums.CredentialType;
import com.bcxin.Infrastructures.enums.EmploymentStatus;
import com.bcxin.Infrastructures.enums.OccupationType;
import com.bcxin.Infrastructures.exceptions.ArgumentTenantException;
import com.bcxin.Infrastructures.models.CredentialModel;
import com.bcxin.Infrastructures.utils.AuthUtil;
import com.bcxin.Infrastructures.utils.DateUtil;
import com.bcxin.Infrastructures.validations.Credential;
import com.bcxin.Infrastructures.validations.CredentialValidator;
import com.bcxin.Infrastructures.validations.TelephoneValidator;
import com.bcxin.tenant.domain.entities.EmployeeEntity;
import com.bcxin.tenant.domain.readers.dtos.BatchEmployeeValidationDto;
import com.bcxin.tenant.domain.configs.TenantUserConfig;
import lombok.Getter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.Embedded;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;

/**
 * 执行职员
 */
@Getter
public class CreateEmployeeRequestCommand extends CommandAbstract {
    @NotEmpty
    private final String name;

    @NotEmpty
    private final String telephone;
    /**
     * 所属本部门
     */
    @NotEmpty
    private final String departId;
    /**
     * 职业类型
     */
    @NotNull
    private final OccupationType occupationType;
    /**
     * 岗位
     */
    private final String position;
    /**
     * 入职时间
     */
    @NotNull
    private Date hiredDate;

    /**
     * 证件信息
     */
    @Credential
    private CredentialModel credential;

    private final String organizationId;

    private String areaCode;

    private String password;

    @Embedded
    private final OperatorValueType operator;

    /**
     * 异常人员入职：-1：不校验，直接入职，1：需要校验，2：需要校验并且仅提醒确定入职
     */
    private final AbnormalPersonnelEmployeeType abnormalPersonnelEmployeeType;

    public CreateEmployeeRequestCommand(String organizationId, String name, String telephone,
                                        String password,
                                        String departId, OccupationType occupationType, String position,
                                        Date hiredDate, CredentialType credentialType,
                                        String credentialNumber,
                                        OperatorValueType operator,
                                        AbnormalPersonnelEmployeeType abnormalPersonnelEmployeeType) {
        this.name = name;
        this.telephone = telephone;
        this.departId = departId;
        this.password = password;
        this.occupationType = occupationType;
        this.position = position;
        this.hiredDate = hiredDate;
        this.credential = CredentialModel.create(credentialType, credentialNumber);
        this.organizationId = organizationId;
        this.operator = operator;
        this.abnormalPersonnelEmployeeType = abnormalPersonnelEmployeeType;
    }

    public void validate(boolean isRequiredPhoneAsLoginName, TenantUserConfig tenantUserConfig) {
        super.validate();

        if (!StringUtils.hasLength(this.getOrganizationId())) {
            throw new ArgumentTenantException("所属企业无效");
        }

        if (!StringUtils.hasLength(this.getDepartId())) {
            throw new ArgumentTenantException("所属部门不能为空");
        }

        if (!StringUtils.hasLength(this.getName())) {
            throw new ArgumentTenantException("姓名不能为空");
        }

        if (!StringUtils.hasLength(this.getTelephone())) {
            throw new ArgumentTenantException("手机号码不能为空");
        }
        if (!PhoneUtil.isPhone(this.getTelephone()) && !PhoneUtil.isTel(this.getTelephone())) {
            throw new ArgumentTenantException("手机号码格式不正确");
        }

        if(this.getCredential() == null){
            throw new ArgumentTenantException("证件信息不能为空");
        }
        if(!StringUtils.hasLength(this.getCredential().getNumber())){
            throw new ArgumentTenantException("证件号码不能为空");
        }
        if (this.getCredential().getType() == null) {
            throw new ArgumentTenantException("证件类型不能为空");
        }

        //验证手机号码格式
        if(!isRequiredPhoneAsLoginName &&
                this.getOccupationType() != OccupationType.Police) {
            //警员不验证手机号格式
            if (!TelephoneValidator.checkIsValid(this.getTelephone())) {
                throw new ArgumentTenantException("手机号码格式不正确");
            }
        }

        if (this.getOccupationType() == null) {
            throw new ArgumentTenantException("职业类型不能为空");
        }

        if (this.getHiredDate() == null) {
            throw new ArgumentTenantException("入职日期不能为空");
        }

        // 根据配置判断是否需要校验入职日期必须是当天
        if (tenantUserConfig != null && tenantUserConfig.isHiredDateMustBeToday() 
            && !DateUtil.format2ShortDate().equals(DateUtil.format2ShortDate(this.getHiredDate()))) {
            throw new ArgumentTenantException("入职日期必须是当天");
        }
    }

    public static CreateEmployeeRequestCommand create(String organizationId, String name, String telephone,
                                                      String password,
                                                      String departId, OccupationType occupationType, String position,
                                                      Date hiredTime, CredentialType credentialType,
                                                      String credentialNumber,
                                                      OperatorValueType operator,
                                                      AbnormalPersonnelEmployeeType abnormalPersonnelEmployeeType) {
        return new CreateEmployeeRequestCommand(organizationId, name, telephone, password,departId, occupationType, position,
                hiredTime, credentialType, credentialNumber,operator, abnormalPersonnelEmployeeType);
    }

    public void setHiredDate(Date hiredDate) {
        this.hiredDate = hiredDate;
    }
}
