package com.bcxin.tenant.domain.events.handlers;

import cn.hutool.core.util.IdcardUtil;
import com.bcxin.Infrastructures.enums.CredentialType;
import com.bcxin.Infrastructures.enums.EmploymentStatus;
import com.bcxin.Infrastructures.enums.OccupationType;
import com.bcxin.Infrastructures.events.handlers.DomainEventHandlerAbstract;
import com.bcxin.Infrastructures.exceptions.ArgumentTenantException;
import com.bcxin.Infrastructures.utils.AuthUtil;
import com.bcxin.Infrastructures.validations.CredentialValidator;
import com.bcxin.tenant.domain.configs.EnvConfig;
import com.bcxin.tenant.domain.dto.EmployeeOccupationTypeValidationBasicDto;
import com.bcxin.tenant.domain.entities.OrganizationEntity;
import com.bcxin.tenant.domain.events.EmployeeBeforeEntryValidationEvent;
import com.bcxin.tenant.domain.exceptions.EntryEmployeeValidationException;
import com.bcxin.tenant.domain.readers.TenantDbReader;
import com.bcxin.tenant.domain.readers.dtos.UserOrganBasicDto;
import com.bcxin.tenant.domain.repositories.OrganizationRepository;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
public class EmployeeBeforeEntryValidationEvent_ValidationHandler
        extends DomainEventHandlerAbstract<EmployeeBeforeEntryValidationEvent> {
    private final TenantDbReader dbReader;
    private final OrganizationRepository organizationRepository;
    private final EnvConfig envConfig;

    public EmployeeBeforeEntryValidationEvent_ValidationHandler(TenantDbReader dbReader, EnvConfig envConfig, OrganizationRepository organizationRepository) {
        this.dbReader = dbReader;
        this.envConfig = envConfig;
        this.organizationRepository = organizationRepository;
    }

    @Override
    protected void execute(EmployeeBeforeEntryValidationEvent event) {
        Collection<EntryEmployeeValidationException.EntryNotAllowedInfo> notAllowedCompanyInfos =
                new ArrayList<>();


        /**
         * 执行前的验证:
         * 保安人员的证件类型必须为身份证&符合年龄要求
         */
        Collection<String> preMatchTenantUserIds = new ArrayList<>();
        for(EmployeeBeforeEntryValidationEvent.TenantUserOccupationTypeInfo userOccupationTypeInfo: event.getTenantUsers()) {
            try {
                if (userOccupationTypeInfo.getOccupationType() == OccupationType.SecurityGuard &&
                        userOccupationTypeInfo.getCredentialType() != CredentialType.IdCard) {
                    throw new ArgumentTenantException(
                            String.format("%s 复职为保安人员的时候, 证件类型必须为身份证", userOccupationTypeInfo.getName()));
                } else {
                    /**
                     * 根据职业类型; 验证身份证的有效性
                     */
                    if(userOccupationTypeInfo.getCredentialType() == CredentialType.IdCard){
                        Optional<OrganizationEntity> organizationOptional = organizationRepository.findById(event.getOrganizationId());
                        userOccupationTypeInfo.getOccupationType().validate(
                                userOccupationTypeInfo.getCredentialType(), userOccupationTypeInfo.getCredentialNumber(),
                                event.getAreaCode(), organizationOptional.map(OrganizationEntity::getInstitutionalCode).orElse(null)
                        );
                    }
                    preMatchTenantUserIds.add(userOccupationTypeInfo.getTenantUserId());
                }
            } catch (Exception ex) {
                notAllowedCompanyInfos.add(EntryEmployeeValidationException.EntryNotAllowedInfo.create(
                        userOccupationTypeInfo.getName(),
                        ex.getMessage(),
                        userOccupationTypeInfo.getTelephone(),
                        userOccupationTypeInfo.getCredentialType(),
                        userOccupationTypeInfo.getCredentialNumber()
                ));
            }
        }

        /**
         * 即将进行验证的职员信息
         */
        Collection<EmployeeOccupationTypeValidationBasicDto> allEmployeeOccupationTypeValidationBasics =
                this.dbReader.getOnDutyEmployeeValidationDtoByIdsAndAreaCode(
                        event.getAreaCode(),
                        event.getOrganizationId(),
                        preMatchTenantUserIds
                );


        if (!CollectionUtils.isEmpty(allEmployeeOccupationTypeValidationBasics)) {
            Collection<EmployeeOccupationTypeValidationBasicDto> employeeOccupationTypeValidationBasics =
                    allEmployeeOccupationTypeValidationBasics.stream().filter(ii->!ii.getOrganizationId().equalsIgnoreCase(event.getOrganizationId()))
                            .collect(Collectors.toList());
            for (EmployeeBeforeEntryValidationEvent.TenantUserOccupationTypeInfo tenantUserOccupationTypeInfo :
                    event.getTenantUsers()) {
                /**
                 * 核对该职员是否已经在职
                 */
                EmployeeOccupationTypeValidationBasicDto currentEmployee =
                        allEmployeeOccupationTypeValidationBasics.stream().filter(ii->ii.getOrganizationId().equalsIgnoreCase(event.getOrganizationId()) &&
                                ii.getStatus()== EmploymentStatus.OnJob).findFirst().orElse(null);
                if(currentEmployee!=null) {
                    notAllowedCompanyInfos.add(
                            EntryEmployeeValidationException.EntryNotAllowedInfo.create(
                                    tenantUserOccupationTypeInfo.getName(),
                                    "该职员已在职, 请勿重复入职",
                                    tenantUserOccupationTypeInfo.getTelephone(),
                                    tenantUserOccupationTypeInfo.getCredentialType(),
                                    tenantUserOccupationTypeInfo.getCredentialNumber()
                            ));
                }


                if (tenantUserOccupationTypeInfo.getOccupationType() == OccupationType.Normal) {
                    String dutyCompanyName
                            = employeeOccupationTypeValidationBasics.stream()
                            .filter(
                                    ix -> ix.getOccupationType() == OccupationType.SecurityGuard &&
                                            ix.getTenantUserId().equalsIgnoreCase(tenantUserOccupationTypeInfo.getTenantUserId())
                            )
                            .map(ii -> ii.getOrganizationName()).distinct().collect(Collectors.joining(",")
                            );
                    if (StringUtils.hasLength(dutyCompanyName)) {
                        notAllowedCompanyInfos.add(
                                EntryEmployeeValidationException.EntryNotAllowedInfo.create(
                                        tenantUserOccupationTypeInfo.getName(),
                                        String.format(" 在(%s)公司以保安员身份在职, 因此, 无法入职一般职员, 请联系以上公司办理离职之后, 重新在本公司入职!", dutyCompanyName),
                                        tenantUserOccupationTypeInfo.getTelephone(),
                                        tenantUserOccupationTypeInfo.getCredentialType(),
                                        tenantUserOccupationTypeInfo.getCredentialNumber()
                                ));
                    }
                } else if (tenantUserOccupationTypeInfo.getOccupationType() == OccupationType.SecurityGuard) {
                    String dutyCompanyName
                            = employeeOccupationTypeValidationBasics.stream()
                            .filter(
                                    ix -> ix.getOccupationType() == OccupationType.Normal &&
                                            ix.getTenantUserId().equalsIgnoreCase(tenantUserOccupationTypeInfo.getTenantUserId())
                            )
                            .map(ii -> ii.getOrganizationName()).distinct().collect(Collectors.joining(",")
                            );

                    String dutySecurityGuardCompanyName
                            = employeeOccupationTypeValidationBasics.stream()
                            .filter(
                                    ix -> ix.getOccupationType() == OccupationType.SecurityGuard &&
                                            ix.getTenantUserId().equalsIgnoreCase(tenantUserOccupationTypeInfo.getTenantUserId())
                            )
                            .map(ii -> ii.getOrganizationName()).distinct().collect(Collectors.joining(",")
                            );

                    if (StringUtils.hasLength(dutyCompanyName) || StringUtils.hasLength(dutySecurityGuardCompanyName)) {
                        String message = null;
                        if (StringUtils.hasLength(dutyCompanyName)) {
                            message = String.format(" 在(%s)公司以一般职员身份在职, 因此, 无法入职保安员, 请联系以上公司办理离职之后, 重新在本公司入职!",
                                    dutyCompanyName);
                        }

                        if (StringUtils.hasLength(dutySecurityGuardCompanyName)) {
                            message = String.format(" 在(%s)公司以保安员份在职, 因此, 无法再次入职保安员, 请联系以上公司办理离职之后, 重新在本公司入职!",
                                    dutySecurityGuardCompanyName);
                        }

                        notAllowedCompanyInfos.add(
                                EntryEmployeeValidationException.EntryNotAllowedInfo.create(
                                        tenantUserOccupationTypeInfo.getName(),
                                        message,
                                        tenantUserOccupationTypeInfo.getTelephone(),
                                        tenantUserOccupationTypeInfo.getCredentialType(),
                                        tenantUserOccupationTypeInfo.getCredentialNumber()
                                ));
                    }
                }
            }
        }

        if (!CollectionUtils.isEmpty(notAllowedCompanyInfos)) {
            throw new EntryEmployeeValidationException("", notAllowedCompanyInfos);
        }
    }
}
