package com.bcxin.api.interfaces.commons.responses;

import com.bcxin.Infrastructures.components.JsonProvider;
import com.bcxin.Infrastructures.enums.*;
import com.bcxin.Infrastructures.snapshots.OrgGisLocationSnapshot;
import com.bcxin.Infrastructures.utils.GeoLocationValueType;
import com.bcxin.api.interfaces.tenants.requests.organizations.LocationRequest;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;

@ApiModel("企业注册信息返回对象")
@Data
public class CompanyResponse implements Serializable {
    private static final Logger logger = LoggerFactory.getLogger(CompanyResponse.class);

    @ApiModelProperty(value = "ID")
    private String id;

    @ApiModelProperty(value = "行业类型")
    private String industryCode;

    @ApiModelProperty(value = "机构类型")
    private String institutionalCode;


    @ApiModelProperty(value = "行业名称")
    private String industryName;

    @ApiModelProperty(value = "机构名称")
    private String institutionalName;

    @ApiModelProperty(value = "保安服务公司类型", notes = "com.bcxin.Infrastructures.enums.IndustryDetailType")
    private Integer industryDetailType;


    //基本信息
    @ApiModelProperty(value = "公司名称")
    private String name;

    @ApiModelProperty(value = "总/分/子公司", notes = "com.bcxin.Infrastructures.enums.ParentSubsidiary")
    private Integer type;

    @ApiModelProperty(value = "联系电话")
    private String telephone;

    @ApiModelProperty(value = "经济类型", notes = "com.bcxin.Infrastructures.enums.EconomicType")
    private Integer economicType;

    @ApiModelProperty(value = "公司类型", notes = "com.bcxin.Infrastructures.enums.CompanyNature")
    private Integer nature;

    @ApiModelProperty(value = "注册地区")
    private LocationRequest placeOfRegister;

    @ApiModelProperty(value = "经营地区")
    private LocationRequest placeOfBusiness;


    //总公司信息，保安行业必填
    @ApiModelProperty(value = "总公司名称")
    private String parentName;

    @ApiModelProperty(value = "总公司证件类型", notes = "com.bcxin.Infrastructures.enums.CompanyCertificateType")
    private Integer parentCertificateType;

    @ApiModelProperty(value = "总公司证件号码")
    private String parentCertificateNumber;

    @ApiModelProperty(value = "总公司法人姓名")
    private String parentLegalPersonName;

    @ApiModelProperty(value = "总公司联系电话")
    private String parentLegalPersonTelephone;


    //法人或负责人信息
    @ApiModelProperty(value = "法人姓名")
    private String legalPersonName;

    @ApiModelProperty(value = "法人手机号码")
    private String legalPersonTelephone;

    @ApiModelProperty(value = "法人证件类型", notes = "com.bcxin.Infrastructures.enums.CompanyCertificateType")
    private Integer legalPersonCredentialType;

    @ApiModelProperty(value = "法人证件号码")
    private String legalPersonCredentialNumber;

    @ApiModelProperty(value = "法人国籍")
    private String legalPersonNationality;

    //保安负责人信息
    @ApiModelProperty(value = "保安负责人姓名")
    private String securityPersonName;

    @ApiModelProperty(value = "保安负责人手机号码")
    private String securityPersonTelephone;

    @ApiModelProperty(value = "保安负责人证件类型", notes = "com.bcxin.Infrastructures.enums.CompanyCertificateType")
    private Integer securityPersonCredentialType;

    @ApiModelProperty(value = "保安负责人证件号码")
    private String securityPersonCredentialNumber;


    //注册信息
    @ApiModelProperty(value = "注册资本（万元）")
    private String registeredCapital;

    @ApiModelProperty(value = "固定资产（万元）")
    private String fixedCapital;

    @ApiModelProperty(value = "年营业额（万元）")
    private String annualSalesVolume;

    @ApiModelProperty(value = "年利税（万元）")
    private String annualProfitTax;

    @ApiModelProperty(value = "证件类型", notes = "com.bcxin.Infrastructures.enums.CompanyCertificateType")
    private Integer certificateType;

    @ApiModelProperty(value = "统一社会信用代码")
    private String unifySocialCreditCode;

    @ApiModelProperty(value = "营业执照扫描件")
    private String unifySocialCreditCodeFile;


    //资质信息
    @ApiModelProperty(value = "保安服务许可/保安培训备案证号")
    private String servicePermitNumber;

    @ApiModelProperty(value = "发证机关名称")
    private String nameOfIssuingAuthority;

    @ApiModelProperty(value = "保安服务许可证首次发证日期或者培训单位的发证日期")
    private Date firstIssueServicePermit;

    @ApiModelProperty(value = "保安服务许可证扫描件或者保安培训许可（备案）证扫描件")
    private String servicePermitAttachment;

    @ApiModelProperty(value = "批准文号")
    private String securityApprovalNumber;

    @ApiModelProperty(value = "服务范围）")
    private List<String> serviceScopeList;

    @ApiModelProperty(value = "人力防范评定等级", notes = "com.bcxin.Infrastructures.enums.SecurityPreparednessRating")
    private Integer securityPreparednessRating;

    @ApiModelProperty(value = "武装守护押运评定等级", notes = "com.bcxin.Infrastructures.enums.SecurityArmedRating")
    private Integer securityArmedRating;

    @ApiModelProperty(value = "安全技术防范评定等级", notes = "com.bcxin.Infrastructures.enums.SecuritySafetyDefenseRating")
    private Integer securitySafetyDefenseRating;

    @ApiModelProperty(value = "是否有风险评估资质")
    private Boolean isRiskAssessment;


    @ApiModelProperty(value = "培训单位的培训内容")
    private String trainContent;


    //自行招用保安员单位
    @ApiModelProperty(value = "拟自招保安员数")
    private Integer numberOfSecurityGuards;

    @ApiModelProperty(value = "是否治安保卫重点单位")
    private Boolean isPublicSecuritySecurity;

    @ApiModelProperty(value = "是否物业企业")
    private Boolean isPropertyEnterprise;

    @ApiModelProperty(value = "自招保安单位性质")
    private String natureOfSelfRecruitedUnits;


    //监管归属
    @ApiModelProperty(value = "监管地区")
    private LocationRequest placeOfSupervise;

    @ApiModelProperty(value = "监管机构")
    private String superviseDepartId;

    @ApiModelProperty(value = "监管机构名称")
    private String superviseDepartName;

    @ApiModelProperty(value = "分享单位名称")
    private String shareOrganizationName;

    @ApiModelProperty(value = "分享职员姓名")
    private String shareEmployeeName;


    @ApiModelProperty(value = "系统管理员")
    private ContactRequest administrator;
    @ApiModelProperty(value = "经度")
    private Double longitude;
    @ApiModelProperty(value = "纬度")
    private Double latitude;

    @ApiModelProperty(value = "是否强提醒经纬度信息")
    private boolean IsValidLonlat;

    @ApiModelProperty(value = "是否允许更改经纬度")
    private boolean IsAllowedChangeLonlat;

    @ApiModelProperty(value = "经纬度最大允许修改次数")
    private int allowedMonthGisChangesCount;

    @ApiModelProperty(value = "经纬度剩余修改次数")
    private int alreadyChangedCount;

    @ApiModelProperty(value = "经纬度地址")
    private String locationAddress;


    @ApiModel("企业人员信息")
    @Data
    public static class ContactRequest implements Serializable {
        @ApiModelProperty(value = "姓名")
        private String name;

        @ApiModelProperty(value = "手机号码")
        private String telephone;

        @ApiModelProperty(value = "证件类型", notes = "com.bcxin.Infrastructures.enums.CredentialType")
        private Integer credentialType;

        @ApiModelProperty(value = "证件号码")
        private String credentialNumber;

        @ApiModelProperty(value = "国籍")
        private String nationality;


        public ContactRequest() {
        }

        public ContactRequest(String name, String telephone, Integer credentialType, String credentialNumber, String nationality) {
            this.name = name;
            this.telephone = telephone;
            this.credentialType = credentialType;
            this.credentialNumber = credentialNumber;
            this.nationality = nationality;
        }
    }

    public CompanyResponse() {
    }

    public CompanyResponse(String id, String industryCode, String institutionalCode,String industryName, String institutionalName, IndustryDetailType industryDetailType, String name,
                           ParentSubsidiary type, String telephone, EconomicType economicType, CompanyNature nature, LocationRequest placeOfRegister,
                           LocationRequest placeOfBusiness, String parentName, CompanyCertificateType parentCertificateType,
                           String parentCertificateNumber, String parentLegalPersonName, String parentLegalPersonTelephone,
                           String legalPersonName, String legalPersonTelephone, CredentialType legalPersonCredentialType,
                           String legalPersonCredentialNumber, String legalPersonNationality, String securityPersonName,
                           String securityPersonTelephone, CredentialType securityPersonCredentialType, String securityPersonCredentialNumber,
                           String registeredCapital, String fixedCapital, String annualSalesVolume, String annualProfitTax,
                           CompanyCertificateType certificateType, String unifySocialCreditCode, String unifySocialCreditCodeFile,
                           String servicePermitNumber, String nameOfIssuingAuthority, Date firstIssueServicePermit,
                           String servicePermitAttachment, String securityApprovalNumber, List<String> serviceScopeList,
                           SecurityPreparednessRating securityPreparednessRating, SecurityArmedRating securityArmedRating, SecuritySafetyDefenseRating securitySafetyDefenseRating,
                           Boolean isRiskAssessment, String trainContent, Integer numberOfSecurityGuards, Boolean isPublicSecuritySecurity,
                           Boolean isPropertyEnterprise, String natureOfSelfRecruitedUnits, String superviseRegionCode,
                           String superviseDepartId, String superviseDepartName,
                           String shareOrganizationName, String shareEmployeeName, ContactRequest administrator,
                           Double longitude, Double latitude, String lonLatJson, JsonProvider jsonProvider,int allowedMonthGisChanges) {
        this.id = id;
        this.industryName = industryName;
        this.institutionalName = institutionalName;
        this.industryCode = industryCode;
        this.institutionalCode = institutionalCode;
        this.industryDetailType = industryDetailType == null ? null : industryDetailType.ordinal();
        this.name = name;
        this.type = type == null ? null : type.ordinal();
        this.telephone = telephone;
        this.economicType = economicType == null ? null : economicType.ordinal();
        this.nature = nature == null ? null : nature.ordinal();
        this.placeOfRegister = placeOfRegister==null?LocationRequest.createEmpty():placeOfRegister; ;
        this.placeOfBusiness = placeOfBusiness==null?LocationRequest.createEmpty():placeOfBusiness;
        this.parentName = parentName;
        this.parentCertificateType = parentCertificateType == null ? null : parentCertificateType.ordinal();
        this.parentCertificateNumber = parentCertificateNumber;
        this.parentLegalPersonName = parentLegalPersonName;
        this.parentLegalPersonTelephone = parentLegalPersonTelephone;
        this.legalPersonName = legalPersonName;
        this.legalPersonTelephone = legalPersonTelephone;
        this.legalPersonCredentialType = legalPersonCredentialType == null ? null : legalPersonCredentialType.ordinal();
        this.legalPersonCredentialNumber = legalPersonCredentialNumber;
        this.legalPersonNationality = legalPersonNationality;
        this.securityPersonName = securityPersonName;
        this.securityPersonTelephone = securityPersonTelephone;
        this.securityPersonCredentialType = securityPersonCredentialType == null ? null : securityPersonCredentialType.ordinal();
        this.securityPersonCredentialNumber = securityPersonCredentialNumber;
        this.registeredCapital = registeredCapital;
        this.fixedCapital = fixedCapital;
        this.annualSalesVolume = annualSalesVolume;
        this.annualProfitTax = annualProfitTax;
        this.certificateType = certificateType == null ? null : certificateType.ordinal();
        this.unifySocialCreditCode = unifySocialCreditCode;
        this.unifySocialCreditCodeFile = unifySocialCreditCodeFile;
        this.servicePermitNumber = servicePermitNumber;
        this.nameOfIssuingAuthority = nameOfIssuingAuthority;
        this.firstIssueServicePermit = firstIssueServicePermit;
        this.servicePermitAttachment = servicePermitAttachment;
        this.securityApprovalNumber = securityApprovalNumber;
        this.serviceScopeList = serviceScopeList;
        this.securityPreparednessRating = securityPreparednessRating == null ? null : securityPreparednessRating.ordinal();
        this.securityArmedRating = securityArmedRating == null ? null : securityArmedRating.ordinal();
        this.securitySafetyDefenseRating = securitySafetyDefenseRating == null ? null : securitySafetyDefenseRating.ordinal();
        this.isRiskAssessment = isRiskAssessment;
        this.trainContent = trainContent;
        this.numberOfSecurityGuards = numberOfSecurityGuards;
        this.isPublicSecuritySecurity = isPublicSecuritySecurity;
        this.isPropertyEnterprise = isPropertyEnterprise;
        this.natureOfSelfRecruitedUnits = natureOfSelfRecruitedUnits;
        this.superviseDepartId = superviseDepartId;
        this.superviseDepartName = superviseDepartName;
        this.shareOrganizationName = shareOrganizationName;
        this.shareEmployeeName = shareEmployeeName;
        this.administrator = administrator;
        this.longitude = longitude;
        this.latitude = latitude;

        if (this.getPlaceOfSupervise() == null) {
            this.setPlaceOfSupervise(new LocationRequest());
        }
        if (this.getPlaceOfSupervise().getProvince() == null) {
            this.getPlaceOfSupervise().setProvince(new LocationRequest.ItemValueRequest());
        }
        if (this.getPlaceOfSupervise().getCity() == null) {
            this.getPlaceOfSupervise().setCity(new LocationRequest.ItemValueRequest());
        }
        if (this.getPlaceOfSupervise().getDistrict() == null) {
            this.getPlaceOfSupervise().setDistrict(new LocationRequest.ItemValueRequest());
        }
        if (StringUtils.isNotBlank(superviseRegionCode) && superviseRegionCode.length() == 6) {
            this.getPlaceOfSupervise().getProvince().setCode(superviseRegionCode.substring(0,2).concat("0000"));
            this.getPlaceOfSupervise().getCity().setCode(superviseRegionCode.substring(0,4).concat("00"));
            this.getPlaceOfSupervise().getDistrict().setCode(superviseRegionCode);
        }

        if(this.latitude == null || this.longitude == null){
            this.IsValidLonlat = true;
        }
        if(GeoLocationValueType.isValidLocation(this.latitude,this.longitude)){
            this.IsValidLonlat = false;
        }else{
            this.IsValidLonlat = true;
        }
        try {
            OrgGisLocationSnapshot sn = jsonProvider.toObject(OrgGisLocationSnapshot.class,lonLatJson);
            this.allowedMonthGisChangesCount = allowedMonthGisChanges;
            if(sn != null) {
                this.locationAddress = sn.getAddress();
                int count = allowedMonthGisChanges - sn.getCount();
                if(count <= 0){
                    this.alreadyChangedCount = 0;
                }else{
                    this.alreadyChangedCount = count;
                }
            }else{
                this.alreadyChangedCount = allowedMonthGisChanges;
            }
            if(this.IsValidLonlat){
                this.IsAllowedChangeLonlat = true;
            }else {
                if (sn != null) {
                    LocalDate localDate = sn.getTime().toLocalDateTime().toLocalDate();
                    LocalDate localDate2 = Timestamp.from(Instant.now()).toLocalDateTime().toLocalDate();
                    long days = ChronoUnit.DAYS.between(localDate, localDate2);
                    if (days <= 30){
                        if(sn.getCount() < allowedMonthGisChanges){
                            this.IsAllowedChangeLonlat = true;
                        }else{
                            this.IsAllowedChangeLonlat = false;
                        }
                    }else{
                        this.IsAllowedChangeLonlat = true;
                        this.alreadyChangedCount = allowedMonthGisChanges;
                    }
                }else{
                    this.IsAllowedChangeLonlat = true;
                }
            }
        }
        catch (Exception ex) {
            logger.error("无效数据{}问题", lonLatJson, ex);
        }
    }
}
