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

import com.alibaba.fastjson.JSON;
import com.cusc.nirvana.common.result.Response;
import com.cusc.nirvana.user.eiam.dto.OrganizationDTO;
import com.cusc.nirvana.user.rnr.fp.constants.ResultCodeEnum;
import com.cusc.nirvana.user.rnr.fp.dto.BindRequestDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FpRnrSmsInfoDTO;
import com.cusc.nirvana.user.rnr.fp.dto.UnbindReceiceSMSDTO;
import com.cusc.nirvana.user.rnr.fp.handler.MessageCallbackHandler;
import com.cusc.nirvana.user.rnr.fp.service.*;
import com.cusc.nirvana.user.rnr.mg.client.MgRnrCardInfoClient;
import com.cusc.nirvana.user.rnr.mg.client.MgSurplusBindClient;
import com.cusc.nirvana.user.rnr.mg.client.OrgSimRelClient;
import com.cusc.nirvana.user.rnr.mg.constants.RnrBizzTypeEnum;
import com.cusc.nirvana.user.rnr.mg.constants.RnrOrderStatusEnum;
import com.cusc.nirvana.user.rnr.mg.constants.RnrStatus;
import com.cusc.nirvana.user.rnr.mg.dto.MgCardNoticeDTO;
import com.cusc.nirvana.user.rnr.mg.dto.MgRnrCardInfoDTO;
import com.cusc.nirvana.user.rnr.mg.dto.RnrOrderDTO;
import com.cusc.nirvana.user.util.CuscStringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ChangeTBoxMessageCallBackHandler implements MessageCallbackHandler {
    @Value("${message.callback.timeout:120}")
    private int timeOut;

    @Resource
    private IFpCardUnBindService cardUnBindService;

    @Resource
    private IFpChangeTboxService changeTboxService;

    @Resource
    private MgRnrCardInfoClient cardInfoClient;

    @Resource
    private MgSurplusBindClient mgSurplusBindClient;

    @Autowired
    private IRnrService rnrService;

    @Autowired
    private ISimVehicleRelService simVehicleRelService;

	@Autowired
	private IOrganService organService;

	@Resource
	private OrgSimRelClient orgSimRelClient;


    @Override
    public Response callBack(FpRnrSmsInfoDTO rnrSmsInfoDTOResponseData, UnbindReceiceSMSDTO bean,long receiveTIme) {
        RnrOrderDTO rnrOrderDTO = new RnrOrderDTO();
        rnrOrderDTO.setUuid(rnrSmsInfoDTOResponseData.getOrderId());
        Response<RnrOrderDTO> orderStatus = cardUnBindService.getOrderStatus(rnrOrderDTO);
        if (!orderStatus.isSuccess() || orderStatus.getData() == null) {
            return Response.createError(orderStatus.getMsg(), orderStatus.getData());
        }
        RnrOrderDTO orderDTO = orderStatus.getData();
        long startTime = rnrSmsInfoDTOResponseData.getCreateTime().getTime();
        log.info("当前时间: {},短信发送时间: {}", receiveTIme, toString());
        boolean isTimeOut = receiveTIme - timeOut * 1000 > startTime;
        if (isTimeOut) {
            //更新工单 超时
            orderDTO.setOrderStatus(RnrOrderStatusEnum.CANCEL.getCode());
            return cardUnBindService.updateOrder(orderDTO);
        }
        //根据工单id获取工单
        if (!bean.getReplyContent().toLowerCase().equals("y")) {
            //更新工单 失败
            orderDTO.setOrderStatus(RnrOrderStatusEnum.NOT_PASS.getCode());
            return cardUnBindService.updateOrder(orderDTO);
        } else {
        	//更新工单
        	orderDTO.setOrderStatus(RnrOrderStatusEnum.PASS.getCode());
			cardUnBindService.updateOrder(orderDTO);

			//根据工单查询 卡信息
			MgRnrCardInfoDTO query = new MgRnrCardInfoDTO();
			query.setOrderId(rnrOrderDTO.getUuid());

			List<MgRnrCardInfoDTO> newCardList = cardInfoClient.queryByList(query).getData();

			//获取老卡信息
			List<String> oldUuIdList = newCardList.stream().map(MgRnrCardInfoDTO::getOldCardId).collect(Collectors.toList());
			List<MgRnrCardInfoDTO> oldCardList = oldUuIdList.parallelStream().map(oldUuid -> {
				MgRnrCardInfoDTO oldQuery = new MgRnrCardInfoDTO();
				oldQuery.setUuid(oldUuid);
				return cardInfoClient.getByUuid(oldQuery).getData();
			}).collect(Collectors.toList());


			//新卡设置绑定成功
			//log.info("换件 新卡设置绑定成功:{}");
			newCardList.parallelStream().forEach(card->{
				MgRnrCardInfoDTO bindUpdate = new MgRnrCardInfoDTO();
				bindUpdate.setUuid(card.getUuid());
				bindUpdate.setRnrStatus(RnrStatus.RNR.getCode());
				cardInfoClient.update(bindUpdate);
				log.info("换件 新卡设置绑定 orderId = {},uuid= {},iccid = {}",rnrOrderDTO.getUuid(),card.getUuid(),card.getIccid());
			});

			//更新卡和VIN数据
			MgRnrCardInfoDTO mgRnrCardInfoDTO = new MgRnrCardInfoDTO();
			List<MgRnrCardInfoDTO> mgRnrCardInfoDTOList = newCardList.stream().map(a->{
				mgRnrCardInfoDTO.setIccid(a.getIccid());
				mgRnrCardInfoDTO.setIotId(a.getIotId());
				return mgRnrCardInfoDTO;
			}).collect(Collectors.toList());

			orgSimRelClient.updateVin(mgRnrCardInfoDTOList);

			//老卡设置解绑
			oldCardList.parallelStream().forEach(card->{
				MgRnrCardInfoDTO unBind = new MgRnrCardInfoDTO();
				unBind.setUuid(card.getUuid());
				unBind.setRnrStatus(RnrStatus.UNBOUND.getCode());
				cardInfoClient.update(unBind);
				log.info("换件 老卡设置解绑 orderId = {},uuid= {},iccid = {}",rnrOrderDTO.getUuid(),card.getUuid(),card.getIccid());
			});

			oldCardList.parallelStream().forEach(oldCard->{
				//删除原有vin iccid 关联关系
				BindRequestDTO bindRequestDTO = new BindRequestDTO();
				bindRequestDTO.setVin(oldCard.getIotId());
				bindRequestDTO.setIccid(oldCard.getIccid());
				Response response = simVehicleRelService.unbind(bindRequestDTO);
				if (!response.isSuccess()) {
					log.error("解绑车卡关系失败,iccid:{}, vin:{}",oldCard.getIccid(),oldCard.getIotId());
				}
			});

			List<String> oldIccid = oldCardList.stream().map(a->a.getIccid()).collect(Collectors.toList());
			//换件需要将老卡VIN置空
			orgSimRelClient.updateBindIccid(oldIccid);

			//查询车企信息
			String manufacturerOrgId;
			OrganizationDTO organ = new OrganizationDTO();
			organ.setTenantNo(orderDTO.getTenantNo());
			organ.setUuid(orderDTO.getOrgId());
			Response<OrganizationDTO> organResp = organService.getCarSubOrganByOrgId(organ);
			if (organResp != null && organResp.isSuccess() && organResp.getData() != null) {
				manufacturerOrgId = organResp.getData().getUuid();
			} else {
				log.warn("sendCardNoticeByOrderId 获取车企组织失败，{}", JSON.toJSONString(organResp));
				manufacturerOrgId = "0";
			}

			//发送mq通知
			List<MgCardNoticeDTO> mgCardNoticeList = createMqDTO(newCardList, oldCardList, orderDTO, manufacturerOrgId);
            mgSurplusBindClient.sendMQ(mgCardNoticeList);

			List<MgRnrCardInfoDTO> dtoList = new ArrayList<>();
			mgCardNoticeList.forEach(e ->{
				MgRnrCardInfoDTO dto = new MgRnrCardInfoDTO();
				dto.setIotId(e.getVin());
				dto.setIccid(e.getIccid());
				dto.setOldCardId(e.getOldIccid());
				dtoList.add(dto);
			});
			rnrService.notifyResult(dtoList,RnrBizzTypeEnum.ChangeBinding.getCode().toString(),UUID.randomUUID().toString(),null, ResultCodeEnum.PASS.getCode());
			return com.cusc.nirvana.common.result.Response.createSuccess("解绑卡/更新工单成功");

        }
    }



	private List<MgCardNoticeDTO> createMqDTO(List<MgRnrCardInfoDTO> newCardList, List<MgRnrCardInfoDTO> oldCardList,
											  RnrOrderDTO orderDTO,
											  String manufacturerOrgId) {

		Map<String, MgRnrCardInfoDTO> oldCardMap = oldCardList.stream().collect(Collectors.toMap(MgRnrCardInfoDTO::getUuid, Function.identity(), (o1, o2) -> o1));

		List<MgCardNoticeDTO> cardNoticeList = new ArrayList<>();
		for (MgRnrCardInfoDTO newCard:newCardList) {
			MgCardNoticeDTO mgCardNoticeDTO = new MgCardNoticeDTO();
			mgCardNoticeDTO.setIccid(newCard.getIccid());

			MgRnrCardInfoDTO oldCard = oldCardMap.get(newCard.getOldCardId());
			if (null != oldCard) {
				mgCardNoticeDTO.setOldIccid(oldCard.getIccid());
			}

			mgCardNoticeDTO.setTenantNo(newCard.getTenantNo());
			mgCardNoticeDTO.setVin(newCard.getIotId());

			mgCardNoticeDTO.setRnrBizzType(orderDTO.getRnrBizzType());
			mgCardNoticeDTO.setOrderId(orderDTO.getUuid());
			mgCardNoticeDTO.setManufacturerOrgId(manufacturerOrgId);
			mgCardNoticeDTO.setResultCode(orderDTO.getOrderStatus());
			mgCardNoticeDTO.setOrgId(orderDTO.getOrgId());
			cardNoticeList.add(mgCardNoticeDTO);
		}
		return cardNoticeList;
	}
}
