package com.jkcredit.invoice.hub.service.apiCarFree;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jkcredit.invoice.hub.constant.CommonConstant;
import com.jkcredit.invoice.hub.enums.ApiResponseCodeEnum;
import com.jkcredit.invoice.hub.model.dto.apiCarFree.InvoiceResult;
import com.jkcredit.invoice.hub.model.dto.apiCarFree.InvoiceResultDto;
import com.jkcredit.invoice.hub.model.dto.needCharge.NeedChargeDto;
import com.jkcredit.invoice.hub.model.dto.realCharge.RealChargeDto;
import com.jkcredit.invoice.hub.model.dto.searchInvoice.SearchInvoiceDto;
import com.jkcredit.invoice.hub.model.dto.searchInvoiceResult.SearchInvoiceResultDto;
import com.jkcredit.invoice.hub.model.dto.user.UserDto;
import com.jkcredit.invoice.hub.model.dto.userBalance.UserBalanceDto;
import com.jkcredit.invoice.hub.model.dto.userBalance.UserBalanceInvoiceDto;
import com.jkcredit.invoice.hub.model.po.carFreeCarrierBillStart.CarFreeCarrierBillStartPo;
import com.jkcredit.invoice.hub.puducer.ChargeProducer;
import com.jkcredit.invoice.hub.service.carFreeCarrierBillStart.CarFreeCarrierBillStartService;
import com.jkcredit.invoice.hub.service.needCharge.NeedChargeService;
import com.jkcredit.invoice.hub.service.realCharge.RealChargeService;
import com.jkcredit.invoice.hub.service.searchInvoice.SearchInvoiceService;
import com.jkcredit.invoice.hub.service.searchInvoiceResult.SearchInvoiceResultService;
import com.jkcredit.invoice.hub.service.user.UserService;
import com.jkcredit.invoice.hub.service.userBalance.UserBalanceService;
import com.jkcredit.invoice.hub.spi.lang.exception.ServiceException;
import com.jkcredit.invoice.hub.spi.rest.data.ApiResponseData;
import com.jkcredit.invoice.hub.util.BeanUtil;
import com.jkcredit.invoice.hub.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: xusonglin
 * @create: 2020/1/19 14:05
 * @version: V1.0
 **/
@Slf4j
@Service
public class ApiCarFreeChargeServiceImpl implements ApiCarFreeChargeService {
    @Autowired
    CarFreeCarrierBillStartService startService;
    @Autowired
    ApiCarFreeService carFreeService;
    @Autowired
    SearchInvoiceService searchInvoiceService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ChargeProducer chargeProducer;
    @Autowired
    UserBalanceService userBalanceService;
    @Autowired
    SearchInvoiceResultService searchInvoiceResultService;
    @Autowired
    NeedChargeService needChargeService;
    @Autowired
    RealChargeService realChargeService;
    @Autowired
    UserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResponseData charge(CarFreeCarrierBillStartPo po) {
        // 封装查询参数
        JSONObject param = new JSONObject();
        param.put("num", po.getNum());

        // 接口调用
        ApiResponseData apiResponseData = carFreeService.wayBillNumFindInvoice(param);

        // 判断接口是否调用成功
        if (apiResponseData.getData().equals(CommonConstant.SUCCESS_CODE)
                && apiResponseData.getCode().equals(ApiResponseCodeEnum.CODE_200.getValue())) {
            // 接口调用成功
            InvoiceResultDto invoiceResultDto = JSON.toJavaObject(JSON.parseObject(apiResponseData.getMsg()), InvoiceResultDto.class);
            List<InvoiceResult> newSearchInvoiceResultList;

            // 根据运单发票状态更新运单状态
            if (invoiceResultDto.getWaybillStatus().equals("3")) {
                if (po.getId() == null) {
                    po.setIsSearch(2);
                    po.setStatus(CommonConstant.STATUS_INVOICE_OVER);
                    startService.saveBillStart(po);
                } else {
                    // 开票完成
                    startService.updateBillStartStatus(invoiceResultDto.getWaybillNum(), CommonConstant.STATUS_INVOICE_OVER);
                }
            } else {
                if (po.getId() == null) {
                    po.setIsSearch(2);
                    po.setStatus(CommonConstant.STATUS_MAKING_INVOICE);
                    startService.saveBillStart(po);
                } else {
                    // 开票中
                    startService.updateBillStartStatus(invoiceResultDto.getWaybillNum(), CommonConstant.STATUS_MAKING_INVOICE);
                }
            }
            if (invoiceResultDto.getResult() != null) {
                // 判断运单查询发票返回共用信息在数据库中是否存在，不存在则存入
                SearchInvoiceDto searchInvoiceDto = searchInvoiceService.getSearchInvoiceByNum(invoiceResultDto.getWaybillNum());
                if (searchInvoiceDto == null) {
                    searchInvoiceService.saveSearchInvoice(invoiceResultDto);
                }
                log.info("invoiceResultDto.getResult().size() = {}", invoiceResultDto.getResult().size());
                if (invoiceResultDto.getResult().size() > 0) {
                    //去重列表
                    newSearchInvoiceResultList = invoiceResultDto.getResult().stream().collect(
                            Collectors.collectingAndThen(
                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InvoiceResult::getFee))), ArrayList::new));
                    //计费
                    for (InvoiceResult t : newSearchInvoiceResultList) {
                        if (!redisTemplate.hasKey(CommonConstant.TRANSACTION_ID_KEY + t.getTransactionId())) {
                            // todo 此处计费需要使用消息实现
//                                UserBalanceDto userBalanceDto = userBalanceService.getUserBalance(po.getUserId());
//                                UserBalanceInvoiceDto userBalanceInvoiceDto = new UserBalanceInvoiceDto();
//                                BeanUtil.copyProperties(userBalanceInvoiceDto, userBalanceDto);
//                                userBalanceInvoiceDto.setNum(t.getWaybillNum());
//                                userBalanceInvoiceDto.setTransactionId(t.getTransactionId());
//                                //发送到消息队列
//                                log.info("发送到消息队列");
//                                chargeProducer.send(userBalanceInvoiceDto);
                            // 将需要计费数据插入数据库
                            UserDto userDto = userService.getUser(po.getUserId());
                            NeedChargeDto needChargeDto = new NeedChargeDto();
                            needChargeDto.setUserId(po.getUserId());
                            needChargeDto.setNum(t.getWaybillNum());
                            needChargeDto.setPrice(userDto.getPrice());
                            needChargeDto.setTransactionId(t.getTransactionId());
                            needChargeService.saveNeedCharge(needChargeDto);

                            // 计费
                            UserBalanceDto userBalanceDto = userBalanceService.getUserBalance(po.getUserId());
                            userBalanceDto.setBalance(userBalanceDto.getBalance().subtract(userDto.getPrice()));
                            userBalanceService.updateUserBalance(userBalanceDto);

                            // 实际扣费数据
                            RealChargeDto realChargeDto = new RealChargeDto();
                            realChargeDto.setUserId(userBalanceDto.getUserId());
                            realChargeDto.setPrice(userDto.getPrice());
                            realChargeDto.setNum(po.getNum());
                            realChargeDto.setTransactionId(t.getTransactionId());
                            realChargeService.saveRealCharge(realChargeDto);
                            log.warn("计费日志:{},计费用户id:{}", JSON.toJSONString(t), po.getUserId());
                        }
                    }
                }
                for (InvoiceResult t : invoiceResultDto.getResult()) {
                    if (!redisTemplate.hasKey(CommonConstant.NUM_FIND_INVOICE_KEY + t.getInvoiceNum() + "_" + t.getInvoiceCode())) {
                        SearchInvoiceResultDto dto = new SearchInvoiceResultDto();
                        BeanUtil.copyProperties(dto, t);
                        dto.setUserId(po.getUserId());
                        //插入发票信息
                        searchInvoiceResultService.saveSearchInvoiceResult(dto);
                        log.info("插入的发票信息:{}", JSON.toJSONString(t));
                        //存入redis发票信息
                        redisTemplate.opsForValue().set(CommonConstant.NUM_FIND_INVOICE_KEY + t.getInvoiceNum() + "_" + t.getInvoiceCode(), JSON.toJSONString(t));
                        //存入redis交易id
                        redisTemplate.opsForValue().set(CommonConstant.TRANSACTION_ID_KEY + t.getTransactionId(), t.getTransactionId());
                    }
                }
            }
            return apiResponseData;
        } else {
            log.error("调用接口失败；时间：{}；运单编号：{}", CommonUtil.dateFormat(new Date()), po.getNum());
            throw new ServiceException("调用接口失败");
        }
    }
}
