package com.bcxin.tenant.open.domains.utils;

import com.bcxin.tenant.open.document.domains.documents.*;
import com.bcxin.tenant.open.document.domains.repositories.RdEmployeeDocumentRepository;
import com.bcxin.tenant.open.document.domains.utils.GeoPointUtils;
import com.bcxin.tenant.open.domains.entities.RdEmployeeEntity;
import com.bcxin.tenant.open.domains.readers.RdCompositedReader;
import com.bcxin.tenant.open.domains.repositories.AttendanceRepository;
import com.bcxin.tenant.open.domains.repositories.RdWorkstationRepository;
import com.bcxin.tenant.open.infrastructures.constants.BusinessConstants;
import com.bcxin.tenant.open.infrastructures.enums.DutySignInType;
import com.bcxin.tenant.open.infrastructures.enums.ResourceType;
import com.bcxin.tenant.open.infrastructures.enums.RoleType;
import com.bcxin.tenant.open.infrastructures.exceptions.DocumentIndexNoFoundException;
import com.bcxin.tenant.open.infrastructures.utils.BusinessUtil;
import com.bcxin.tenant.open.infrastructures.utils.ExceptionUtil;
import com.bcxin.tenant.open.infrastructures.utils.StringUtil;
import com.redis.om.spring.search.stream.EntityStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.data.geo.Point;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

public class RdEmployeeEntityUtils{
    private static final Logger logger = LoggerFactory.getLogger(RdEmployeeEntityUtils.class);
    public static RdEmployeeDocument toDocument(RdEmployeeEntity ii,
                                                boolean isFlushStation,
                                                RdEmployeeDocumentRepository rdEmployeeDocumentRepository,
                                                AttendanceRepository attendanceRepository,
                                                RdCompositedReader compositedReader,
                                                BeanFactory beanFactory,
                                                Collection<RdCommunityUserDocument> communityUserDocuments,
                                                Collection<RdDispatchDataScopeDocument> dataScopeDocuments,
                                                Collection<RdCompanyDocument> proprietorCompanyDocuments
                                                ) {

        try {
            RdEmployeeDocument document = null;
            Optional<RdEmployeeDocument> documentOptional =
                    rdEmployeeDocumentRepository.findById(ii.getId());

            /**
             * 新增的时候设置所属驻勤点, 其他情况通过SecurityStationPerson来触发
             */
            if (documentOptional.isPresent()) {
                document = documentOptional.get();
            } else {
                document = new RdEmployeeDocument();
                document.setId(ii.getId());
            }


            document.rest();
            document.setCLevel(ii.getCLevel());
            document.setName(ii.getName());
            document.setContact(ii.getContact());
            document.setCheckedStatus(ii.getCheckedStatus());
            document.setAuthenticatedStatus(ii.getAuthenticatedStatus());
            document.setTenantImUserId(ii.getTenantImUserId());
            document.setOrganizationId(ii.getOrganizationId());
            document.setCompanyName(ii.getCompanyName());
            document.setDeviceNumber(ii.getDeviceNumber());
            document.setHeadPhoto(ii.getHeadPhoto());
            document.setHiredDate(ii.getHiredDate());
            document.setIdCardNo(ii.getIdCardNo());
            document.setInsure(ii.isInsure());
            document.setMilitaryStatus(ii.getMilitaryStatus());
            document.setOccupationType(ii.getOccupationType());
            document.setStatus(ii.getStatus());
            document.setSecurityCertificateNo(ii.getSecurityCertificateNo());
            document.setTenantEmployeeId(ii.getTenantEmployeeId());
            document.setCId(ii.getCId());
            document.setSuperviseRegionCode(ii.getSuperviseRegionCode());
            document.setThirdParty(ii.getThirdParty());

            /**
             * 坐标信息来自于签到数据
             */
            if (document.getLonLat() == null || (document.getLonLat().getX() < 2 || document.getLonLat().getY() == 1l)) {
                /**
                 * 当经纬度无效的时候; 尝试从rdEmployee表中取经纬度信息.
                 */
                if (!StringUtil.isEmpty(ii.getLonLat())) {
                    document.setLonLat(GeoPointUtils.translate(ii.getLonLat()));
                }

                if (document.getLonLat() == null || (document.getLonLat().getX() < 2 || document.getLonLat().getY() == 1l)) {
                    document.setLonLat(new Point(BusinessConstants.INVALID_LON_LAT, BusinessConstants.INVALID_LON_LAT));
                }

                if (StringUtil.isEmpty(document.getDutyStatus())) {
                    document.setDutyStatus(ii.getDutyStatus().name());
                }
            }

            if(StringUtil.isEmpty(document.getDutyStatus()) || !DutySignInType.SignIn.name().equalsIgnoreCase(document.getDutyStatus())) {
                document.makeDispatchable(false, "签到离岗人员");
                document.setLastDutyStatusChangedTime(Timestamp.from(Instant.now()));
            }

            document.setTenantUserId(ii.getTenantUserId());

            document.addScopePermissions(ii.getOrganizationId());
            document.setSuperviseDepartId(ii.getSuperviseDepartId());
            document.addScopePermissions(ii.getSuperviseDepartId());

            if(!StringUtil.isEmpty(ii.getResponsibleOfStationId())) {
                String[] respStationIds = Arrays.stream(ii.getResponsibleOfStationId().split(";"))
                        .filter(ix -> !StringUtil.isEmpty(ix)).toArray(sz -> new String[sz]);
                document.addScopePermissions(respStationIds);
            }


            boolean noFoundPer = false;
            /**
             * 添加内保单位信息; 保证可以被内保单位进行调度
             */
            if (!CollectionUtils.isEmpty(dataScopeDocuments)) {
                Collection<String> scopeIds =
                        dataScopeDocuments.stream()
                                .filter(it -> StringUtil.isEqual(it.getId(), ii.getSecurityStationId()) && !CollectionUtils.isEmpty(it.getScopes()))
                                .flatMap(it -> it.getScopes().stream())
                                .distinct()
                                .collect(Collectors.toList());

                if (!CollectionUtils.isEmpty(scopeIds)) {
                    /**
                     * 内保单位本身可调用
                     */
                    document.addScopePermissions(scopeIds.toArray(ix -> new String[ix]));

                    /**
                     * 内保单位所属监管可以调度
                     */
                    if (!CollectionUtils.isEmpty(proprietorCompanyDocuments)) {
                        Collection<RdCompanyDocument> perCompanies
                                = proprietorCompanyDocuments.stream().filter(it -> scopeIds.contains(it.getId()))
                                .collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(perCompanies)) {
                            document.addScopePermissions(
                                    perCompanies.stream().map(ix -> ix.getSuperviseDepartId())
                                            .filter(ix -> !StringUtil.isEmpty(ix))
                                            .collect(Collectors.toList())
                                            .toArray(ix -> new String[ix])
                            );
                            RdCompanyDocument firstCom = perCompanies.stream().findFirst().get();
                            document.assignProprietor(firstCom.getId(), firstCom.getName());
                            document.addResourceTypes(ResourceType.ProprietorManaged.name());
                        }
                    }
                } else {
                    noFoundPer = true;
                }
            }

            document.setSuperviseDepartName(ii.getSuperviseDepartName());
            document.setSecurityStationId(ii.getSecurityStationId());
            document.setSecurityStationName(ii.getSecurityStationName());
            if(!StringUtil.isEmpty(ii.getSecurityStationId()) && !BusinessConstants.DefaultEmptyValue.equalsIgnoreCase(ii.getSecurityStationId())) {
                document.addScopePermissions(ii.getSecurityStationId());
            }

            document.setSex(ii.getSex());
            /**
             * 驻勤点负责人
             */
            document.addResponsibleOfStationIds(ii.getResponsibleOfStationId());
            document.setDomainAdmin(ii.isDomainAdmin());

            document.setIndustry(ii.getIndustry());
            document.setInstitutional(ii.getInstitutional());
            RoleType roleType = RoleType.create(ii.getInstitutional(), ii.getCompanyName());
            /**
             * 企业（保安+勤防）或者内保才设置如下
             */
            if (roleType == RoleType.Company || roleType == RoleType.Proprietor) {
                document.addResourceTypes(
                        ResourceType.create(ii.getInstitutional())
                );
            }

            /**
             * 已经有安排驻勤点的人员才可以加入
             */
            if (!CollectionUtils.isEmpty(communityUserDocuments) && !BusinessConstants.DefaultEmptyValue.equalsIgnoreCase(document.getSecurityStationId())) {
                Collection<RdCommunityUserDocument> selectedUserDocuments
                        = communityUserDocuments.stream().filter(ix -> StringUtil.isEqual(ix.getTenantUserId(), ii.getTenantUserId()))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(selectedUserDocuments)) {
                    String[] superviseDepartIds =
                            selectedUserDocuments.stream()
                                    .map(ix -> ix.getSuperviseDepartId()).distinct()
                                    .filter(ix -> StringUtils.hasLength(ix))
                                    .collect(Collectors.toList())
                                    .toArray(ix -> new String[ix]);

                    document.addScopePermissions(superviseDepartIds);
                    document.addResourceTypes(ResourceType.Population.name());
                }
            }

            if (noFoundPer) {
                // document.setSyncNote("找不到内保配置信息");
            } else {
                //document.setSyncNote("来自:EmployeeUtils.");
            }

            Set<String> stationTypes = new HashSet<>();
            if (!StringUtil.isEmpty(ii.getSecurityStationId())) {
                stationTypes.add(ii.getSecurityStationId());
            }

            /**
             * 临保业务
             */
            if (ii.getResourceType() == ResourceType.TemporarySecurity) {
                document.addResourceTypes(ResourceType.TemporarySecurity.name());
                if (!BusinessConstants.DefaultEmptyValue.equalsIgnoreCase(document.getSecurityStationId())) {
                    EntityStream entityStream =
                            beanFactory.getBean(EntityStream.class);
                    RdSecurityStationDocument securityStationDocument =
                            entityStream.of(RdSecurityStationDocument.class)
                                    .filter(RdSecurityStationDocument$.ID.eq(document.getSecurityStationId()))
                                    .findFirst().orElse(null);
                    if (securityStationDocument != null) {
                        document.addScopePermissions(securityStationDocument.getProjectId());
                        stationTypes = securityStationDocument.getStationTypes();

                        /**
                         * 临保情况, 由驻勤点创建企业来支付
                         */
                        document.setPaymentOrgId(securityStationDocument.getOrganizationId());
                    }
                }
            }

            document.setStationTypes(stationTypes);
            document.setLastUpdatedTime(Timestamp.from(Instant.now()));

            RdWorkstationRepository workstationRepository = beanFactory.getBean(RdWorkstationRepository.class);
            long countOfStations = workstationRepository.getCountOfStationsByEmployeeId(document.getId());
            document.updateCountOfStations((int)countOfStations);
            return document;
        } catch (Exception ex) {
            if(ExceptionUtil.getStackMessage(ex).contains("no such index")) {
                throw new DocumentIndexNoFoundException("索引异常", ex);
            }
            logger.error("职员信息-解析数据发生异常:id={};name={}", ii.getId(), ii.getName(), ex);

            return null;
        }
    }
}
