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

import com.bcxin.tenant.open.document.domains.documents.*;
import com.bcxin.tenant.open.document.domains.repositories.RdSecurityStationDocumentRepository;
import com.bcxin.tenant.open.document.domains.utils.GeoPointUtils;
import com.bcxin.tenant.open.domains.entities.RdSecurityStationEntity;
import com.bcxin.tenant.open.domains.entities.StationDeviceEntity;
import com.bcxin.tenant.open.infrastructures.enums.ResourceType;
import com.bcxin.tenant.open.infrastructures.exceptions.DocumentIndexNoFoundException;
import com.bcxin.tenant.open.infrastructures.exceptions.NoFoundTenantException;
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 com.redis.om.spring.search.stream.SearchStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.stream.Collectors;

public class RdSecurityStationEntityUtil implements BeanFactoryAware {
    private static final Logger logger = LoggerFactory.getLogger(RdSecurityStationEntityUtil.class);

    public static RdSecurityStationDocument toDocument(RdSecurityStationEntity ii,
                                                       boolean isFromSync,
                                                       RdSecurityStationDocumentRepository securityStationDocumentRepository,
                                                       EntityStream entityStream,
                                                       Collection<RdDispatchDataScopeDocument> dataScopeDocuments,
                                                       Collection<RdCompanyDocument> proprietorCompanyDocuments,
                                                       Collection<StationDeviceEntity> stationDevices) {
        try {
            RdSecurityStationDocument document = null;
            if (!isFromSync) {
                Optional<RdSecurityStationDocument> securityStationDocumentOptional =
                        securityStationDocumentRepository.findById(ii.getId());
                if (securityStationDocumentOptional.isPresent()) {
                    document = securityStationDocumentOptional.get();
                }
            }

            if (document == null) {
                document = new RdSecurityStationDocument();

                document.setId(ii.getId());
            }

            document.rest();
            StringBuilder countOfSec = new StringBuilder();
            countOfSec.append(String.format("org.countOfSecurityMan=%s;", ii.getCountOfSecurityMan()));
            document.setCountOfSecurityMan(ii.getCountOfSecurityMan());

            /**
             * 走实时计算数据库的, 因此, rd_中的数量肯定是对的
             */
            /**
             * 新增的是时候统计驻勤点的保安人员; 其他情况走StationPerson来触发
             */
            document.setName(ii.getName());
            document.setAddress(ii.getAddress());
            document.setOrganizationId(ii.getOrganizationId());
            document.setCompanyName(ii.getCompanyName());

            if (StringUtils.hasLength(ii.getStationType())) {
                document.setStationTypes(Arrays.stream(ii.getStationType().split(",")).collect(Collectors.toSet()));
            } else {
                document.setStationTypes(new HashSet<>());
            }

            document.setPrincipalId(ii.getPrincipalId());
            document.setPrincipalName(ii.getPrincipalName());
            document.setPrincipalContact(ii.getPrincipalContact());

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

            /**
             * 添加内保单位信息; 保证可以被内保单位进行查看
             */
            if (!CollectionUtils.isEmpty(dataScopeDocuments)) {
                Collection<String> scopeIds =
                        dataScopeDocuments.stream()
                                .filter(it -> StringUtil.isEqual(it.getId(), ii.getId()) && !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());
                        }
                    }
                }
            }

            document.setServiceScope(ii.getServiceScope());
            document.setLonLat(GeoPointUtils.translate(ii.getLonLat()));
            document.changeState(ii.getBeginDate(), ii.getEndDate(), ii.getSiteState());

            document.updateWord(document.getName());

            document.setIndustry(ii.getIndustry());
            document.setInstitutional(ii.getInstitutional());
            document.addResourceTypes(ResourceType.create(ii.getInstitutional()));

            /**
             * 临保业务
             */
            if (ii.getResourceType() == ResourceType.TemporarySecurity) {
                document.addResourceTypes(ResourceType.TemporarySecurity.name());
            }


            /**
             * 社区警务业务: 社会力量/社区警务
             * todo: 待优化
             */
            if(true) {
                SearchStream<RdEmployeeDocument> searchStream =
                        entityStream.of(RdEmployeeDocument.class);
                Collection<RdEmployeeDocument> employeeDocuments =
                        searchStream
                                .filter(RdEmployeeDocument$.SECURITY_STATION_ID.eq(document.getId()))
                                .filter(RdEmployeeDocument$.RESOURCE_TYPES.in(ResourceType.Population.name()))
                                .collect(Collectors.toList());
                document.updateCountOfCommunityUser((int) employeeDocuments.stream().count());

                for (RdEmployeeDocument re : employeeDocuments) {
                    if (!CollectionUtils.isEmpty(re.getScopePermissions())) {
                        document.addScopePermissions(re.getScopePermissions().toArray(ix -> new String[ix]));
                    }
                }
            }

            document.setLastUpdatedTime(ii.getLastSyncTime());
            /**
             * 把临保项目Id也作为搜索范围
             */
            if (StringUtils.hasLength(ii.getProjectId())) {
                document.addScopePermissions(ii.getProjectId());
                /**
                 * 可以根据临保项目; 找到对应的公司
                 * 临保业务: 需要允许承办单位进行搜索; 因此
                 * todo: 20241214
                 */

                /**
                 * 管理人员看到的数据权限
                 */
                //todo: 20241214
            }

            /**
             * 驻勤点的执行范围
             */
            document.setPerformRange(ii.getPerformRange());
            document.setProjectId(ii.getProjectId());
            document.setProjectName(ii.getProjectName());
            document.setHasVideo(false);
            if(!CollectionUtils.isEmpty(stationDevices)) {
                document.setHasVideo(stationDevices.stream().anyMatch(ic -> ii.getId().equalsIgnoreCase(ic.getStationId())));
            }

            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;
        }
    }

    private static BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory bf) throws BeansException {
        beanFactory = bf;
    }
}
