package cn.axzo.msg.center.message.service.impl.v3;

import cn.axzo.basics.profiles.api.UserProfileServiceApi;
import cn.axzo.basics.profiles.dto.basic.*;
import cn.axzo.meepo.api.definition.bankcard.query.dto.response.WorkerBankCardApiRes;
import cn.axzo.msg.center.common.utils.BizAssertions;
import cn.axzo.msg.center.message.service.gateway.BackCardApiGateway;
import cn.axzo.msg.center.service.enums.KVContentType;
import cn.axzo.msg.center.service.pending.response.v3.model.*;
import cn.axzo.trade.datasecurity.core.util.DataSecurityHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.*;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;

/**
 * @author yanglin
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class V3ExtPopulator {

    private final UserProfileServiceApi userProfileServiceApi;

    private final BackCardApiGateway backCardApiGateway;

    public void populate(ParsedModelV3... models) {
        ArrayList<ParsedKV> personKeyValues = new ArrayList<>();
        List<ComponentWorkerGroup> componentWorkerGroups = new ArrayList<>();
        for (ParsedModelV3 model : models) {
            if (model == null) continue;
            personKeyValues.addAll(model.getPersonKeyValues());
            componentWorkerGroups.addAll(model.getComponentWorkerGroups());
        }
        populatePersonKV(personKeyValues);
        populateComponentWorkGroup(componentWorkerGroups);
    }

    public void populatePersonKV(ParsedKV keyValue) {
        populatePersonKV(Collections.singletonList(keyValue));
    }

    public void populatePersonKV(List<ParsedKV> keyValues) {
        List<ParsedKV> personKeyValues = keyValues.stream()
                .filter(kv -> kv.getContentType() == KVContentType.PERSON_ID)
                .collect(toList());
        if (CollectionUtils.isEmpty(personKeyValues)) return;
        List<Long> personIds = personKeyValues.stream()
                .map(ParsedKV::getValueAsLong)
                .filter(Objects::nonNull)
                .distinct()
                .collect(toList());
        Map<Long, PersonProfileDto> personId2Profile = BizAssertions.assertResponse(
                        userProfileServiceApi.postPersonProfiles(personIds)).stream()
                .collect(toMap(BasicDto::getId, identity()));
        for (ParsedKV kv : personKeyValues) {
            Long personId = kv.getValueAsLong();
            if (personId == null) continue;
            PersonProfileDto profile = personId2Profile.get(personId);
            if (profile == null) continue;
            PersonInfo personInfo = new PersonInfo();
            personInfo.setRealName(profile.getRealName());
            personInfo.setAvatar(profile.getAvatarUrl());
            personInfo.setMobilePhone(profile.getPhone());
            personInfo.setMobilePhoneCiphertext(DataSecurityHelper.encrypt(profile.getPhone()));
            kv.setPersonInfo(personInfo);
        }
    }

    private void populateComponentWorkGroup(List<ComponentWorkerGroup> groups) {
        if (CollectionUtils.isEmpty(groups)) return;
        List<Long> workerIdentityIds = groups.stream()
                .map(ComponentWorkerGroup::getWorkerIdentityId)
                .distinct()
                .collect(toList());
        List<WorkerProfileDto> workerResp = BizAssertions.assertResponse(
                userProfileServiceApi.postWorkerProfileList(workerIdentityIds));
        Map<Long, WorkerProfileDto> workerIdentityId2WorkerProfile = workerResp == null
                ? Collections.emptyMap()
                : workerResp.stream().collect(toMap(BasicDto::getId, identity()));
        List<Long> personIds = workerResp == null
                ? Collections.emptyList()
                : workerResp.stream()
                .map(AbstractIdentityProfileDto::getPersonProfile)
                .map(BasicDto::getId)
                .distinct()
                .collect(toList());
        List<WorkerBankCardApiRes> bankCardRes = null;
        if (CollectionUtils.isNotEmpty(personIds)){
            bankCardRes = backCardApiGateway.getPersonBackCard(personIds);
//            bankCardRes = BizAssertions.assertResponse(bankCardApi.batchGetBankCardByPersonId(personIds));
        }


        Map<Long, List<WorkerBankCardApiRes>> personId2BankCard = bankCardRes == null
                ? Collections.emptyMap()
                : bankCardRes.stream().collect(groupingBy(WorkerBankCardApiRes::getPersonId));
        for (ComponentWorkerGroup workerGroup : groups) {
            WorkerProfileDto worker = workerIdentityId2WorkerProfile.get(workerGroup.getWorkerIdentityId());
            if (worker == null) {
                log.warn("worker info not found, workerIdentityId: {}", workerGroup.getWorkerIdentityId());
                workerGroup.removeFromModel();
                continue;
            }
            PersonProfileDto person = worker.getPersonProfile();
            WorkerInfo workerInfo = new WorkerInfo();
            workerInfo.setName(person.getRealName());
            workerInfo.setIcon(person.getAvatarUrl());
            workerInfo.setPhone(person.getPhone());
            workerInfo.setPhoneCiphertext(DataSecurityHelper.encrypt(person.getPhone()));
            workerInfo.setBirthday(person.getBirthday());
            workerInfo.setNationality(person.getNationality());
            workerInfo.setIdNumber(person.getIdNumber());
            workerInfo.setIdNumberCiphertext(DataSecurityHelper.encrypt(person.getIdNumber()));
            workerInfo.setIdentityValid(isWorkerIdentityValid(worker));
            List<WorkerBankCardApiRes> bankCards = personId2BankCard.get(worker.getPersonProfile().getId());
            workerInfo.setCardValid(CollectionUtils.isNotEmpty(bankCards)
                    && StringUtils.isNotBlank(bankCards.get(0).getBankCardNo()));
            workerInfo.setProfessionNames(worker.getProfessionTags().stream()
                    .map(ProfessionTagDto::getProfessionName)
                    .collect(joining("、")));
            workerGroup.getGroup().setWorkerInfo(workerInfo);
        }
    }

    /**
     * 从yoke拷贝过来的
     */
    private boolean isWorkerIdentityValid(WorkerProfileDto worker) {
        if (worker == null) return false;
        PersonProfileDto personProfile = worker.getPersonProfile();
        return !(null == personProfile
                || !StringUtils.isNotBlank(personProfile.getIdNumber())
                || !StringUtils.isNotBlank(personProfile.getRealName())
                || !StringUtils.isNotBlank(personProfile.getSex().toString())
                || !StringUtils.isNotBlank(personProfile.getNationality())
                || null == personProfile.getBirthday()
                || !StringUtils.isNotBlank(personProfile.getIdAddress())
                || !StringUtils.isNotBlank(personProfile.getIdAuthority())
                || null == personProfile.getIdStartDate()
                || null == personProfile.getIdEndDate()
                || !StringUtils.isNotBlank(personProfile.getAvatarUrl()));
    }
}