package com.cusc.nirvana.user.rnr.fp.handler.impl;

import com.alibaba.fastjson.JSONObject;
import com.cusc.nirvana.common.result.Response;
import com.cusc.nirvana.user.exception.CuscUserException;
import com.cusc.nirvana.user.rnr.fp.common.constant.VinCardCheckBussinessDetailType;
import com.cusc.nirvana.user.rnr.fp.dto.*;
import com.cusc.nirvana.user.rnr.fp.handler.VinCardCheckMessageHandler;
import com.cusc.nirvana.user.rnr.fp.service.ISimVehicleRelService;
import com.cusc.nirvana.user.rnr.mg.client.MgRnrCardInfoClient;
import com.cusc.nirvana.user.rnr.mg.constants.RnrStatus;
import com.cusc.nirvana.user.rnr.mg.dto.MgRnrCardInfoDTO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author stayAnd
 * @date 2022/6/1
 * 通用绑卡业务 车卡关系校验实现
 */
@Component("commonBindVinCardCheckHandler")
@Slf4j
public class CommonBindVinCardCheckHandlerImpl implements VinCardCheckMessageHandler {

	@Resource
	private MgRnrCardInfoClient cardInfoClient;

	@Resource
	private ISimVehicleRelService simVehicleRelService;


	@Override
	public VinCardCheckMessageResultDTO checkVinCard(String vin, List<String> iccidList, VinCardCheckBussinessDetailType type) {
		VinCardCheckMessageResultDTO resultDTO = new VinCardCheckMessageResultDTO();
		checkVin(vin);

		List<VinCardCheckMessageFailDTO> failDTOList = new ArrayList<>();

		//输入的卡是否存在 已实名/初始化(认证中)的记录
		List<VinCardCheckMessageFailDTO> localCheckList = checkCardFromLocal(iccidList);
		if (!CollectionUtils.isEmpty(localCheckList)) {
			failDTOList.addAll(localCheckList);
		}

		//查询卡是否存在
		List<VinCardCheckMessageFailDTO> exsitCheckList =  checkCardExist(iccidList);
		if (!CollectionUtils.isEmpty(exsitCheckList)) {
			failDTOList.addAll(exsitCheckList);
		}

		//查询车卡关系
		List<VinCardCheckMessageFailDTO> vinRelationCheckList = checkVinCardRelation(iccidList,vin);
		if (!CollectionUtils.isEmpty(vinRelationCheckList)) {
			failDTOList.addAll(vinRelationCheckList);
		}

		//构建参数
		resultDTO.build(failDTOList);

		return resultDTO;
	}




	protected void checkVin(String vin){
		//子类有特殊判断实现此方法
	}

	/**
	 * 通过mg 查询本地库是否存在车卡关系
	 * @param iccidList
	 * @return
	 */
	private List<VinCardCheckMessageFailDTO> checkCardFromLocal(List<String> iccidList) {
		MgRnrCardInfoDTO query = new MgRnrCardInfoDTO();
		query.setIccidList(iccidList);
		Response<List<MgRnrCardInfoDTO>> response = cardInfoClient.queryByList(query);
		if (null == response || !response.isSuccess()) {
			throw new CuscUserException("", "查询实名库卡信息失败");
		}

		List<MgRnrCardInfoDTO> cardInfoDTOList = response.getData();
		if (CollectionUtils.isEmpty(cardInfoDTOList)) {
			return new ArrayList<>();
		}
		return cardInfoDTOList.stream()
				.filter(card ->
						RnrStatus.INIT.getCode() == card.getRnrStatus() || RnrStatus.RNR.getCode() == card.getRnrStatus()
				).map(card ->
						new VinCardCheckMessageFailDTO().setIccid(card.getIccid()).setErrorMsg("输入的卡信息已存在实名记录")
				).collect(Collectors.toList());

	}


	/**
	 * 判断绑业务的卡 是不是 存在
	 * @param iccidList
	 * @return
	 */
	private List<VinCardCheckMessageFailDTO> checkCardExist(List<String> iccidList) {
		List<VinCardCheckMessageFailDTO> returnList = Collections.synchronizedList(new ArrayList<>());
		if (CollectionUtils.isEmpty(iccidList)) {
			return returnList;
		}
		List<List<String>> partitionIccIdList = Lists.partition(iccidList, 100);
		partitionIccIdList.parallelStream().forEach(list -> {
			IccidListDTO dto = new IccidListDTO();
			dto.setIccidList(list);
			Response<List<IccidDetailDTO>> detailResponse = simVehicleRelService.queryByIccids(dto);
			log.info("checkCardExist,request = {},response = {}", JSONObject.toJSONString(list), JSONObject.toJSONString(detailResponse));
			if (null == detailResponse || !detailResponse.isSuccess()) {
				throw new CuscUserException("", "查询卡详情失败");
			}

			//查询到详情的iccid列表
			List<String> detailIccidList = detailResponse.getData().stream().map(IccidDetailDTO::getIccid).collect(Collectors.toList());

			//过滤出未查询到详情的iccid卡
			List<VinCardCheckMessageFailDTO> notExsitList = list.stream()
					.filter(iccid ->
							!detailIccidList.contains(iccid)
					).map(iccid ->
							new VinCardCheckMessageFailDTO().setIccid(iccid).setErrorMsg("")
					).collect(Collectors.toList());

			returnList.addAll(notExsitList);
		});
		return returnList;
	}


	/**
	 * 判断绑定的卡的 vin 是否一致
	 * @param iccidList
	 * @param vin
	 * @return
	 */
	private List<VinCardCheckMessageFailDTO> checkVinCardRelation(List<String> iccidList, String vin) {
		return iccidList.parallelStream().filter(iccid->{
			Response<VinIccidDTO> response = simVehicleRelService.getVinByIccid(iccid);
			log.info("checkVinCardRelation request = {} , response = {}",iccid,JSONObject.toJSONString(response));
			if (null == response || !response.isSuccess()) {
				throw new CuscUserException("","根据iccid查询vin失败，iccid:"+iccid);
			}
			return null != response.getData() && !vin.equals(response.getData().getVin());
		}).map(iccid->new VinCardCheckMessageFailDTO().setIccid(iccid).setErrorMsg("卡信息的vin码和输入的vin不一致")).collect(Collectors.toList());
	}
}
