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.math.BigDecimal;
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;

            // 根据接口返回运单状态更新表h_car_free_carrier_bill_start 状态
            updateWaybillStartStatus(po, invoiceResultDto);

            if (invoiceResultDto.getResult() != null) {
                // 保存运单查询发票接口返回的外层数据，表h_search_invoice
                saveSearchInvoice(invoiceResultDto);
                log.info("invoiceResultDto.getResult().size() = {}", invoiceResultDto.getResult().size());

                if (!invoiceResultDto.getResult().isEmpty()) {
                    //接口返回发票去重列表
                    newSearchInvoiceResultList = invoiceResultDto.getResult().stream().collect(
                            Collectors.collectingAndThen(
                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InvoiceResult::getFee))), ArrayList::new));
                    UserDto userDto = userService.getUser(po.getUserId());
                    UserBalanceDto userBalanceDto = userBalanceService.getUserBalance(po.getUserId());
                    BigDecimal balance = userBalanceDto.getBalance();
                    //计费
                    for (InvoiceResult t : newSearchInvoiceResultList) {
                        List<InvoiceResult> invoiceResultList = searchInvoiceResultService.getInvoiceByTransactionId(t.getTransactionId());
                        if (invoiceResultList.size() == 0) {
                            // 计算余额
                            balance = balance.subtract(userDto.getPrice());
                            // 实际扣费数据
                            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:{},计费流水号:{},计费日志:{}", po.getUserId(), t.getTransactionId(), JSON.toJSONString(t));
                        }
                    }
                    userBalanceDto.setBalance(balance);
                    userBalanceService.updateUserBalance(userBalanceDto);

                    // 保存发票信息
                    for (InvoiceResult t : invoiceResultDto.getResult()) {
                        List<InvoiceResult> invoiceResultList = searchInvoiceResultService.getInvoiceByInvoiceNum(t.getInvoiceNum(), t.getInvoiceCode());
                        if (invoiceResultList.size() == 0) {
                            SearchInvoiceResultDto dto = new SearchInvoiceResultDto();
                            BeanUtil.copyProperties(dto, t);
                            dto.setUserId(po.getUserId());
                            //插入发票信息
                            searchInvoiceResultService.saveSearchInvoiceResult(dto);
                            log.info("插入的发票信息:{}", JSON.toJSONString(t));
                        }
                    }
                }
            }
            return apiResponseData;
        } else {
            log.error("调用接口失败；时间：{}；运单编号：{}", CommonUtil.dateFormat(new Date()), po.getNum());
            throw new ServiceException("调用接口失败");
        }
    }

    // 根据接口返回运单状态更新表h_car_free_carrier_bill_start 状态
    private void updateWaybillStartStatus(CarFreeCarrierBillStartPo po, InvoiceResultDto invoiceResultDto) {
        if (invoiceResultDto.getWaybillStatus().equals(CommonConstant.STATUS_INVOICE_OVER)) {
            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 {
                // 开票中或未结束
                if (invoiceResultDto.getWaybillStatus().equals(1)) {
                    // 未结束
                    startService.updateBillStartStatus(invoiceResultDto.getWaybillNum(), CommonConstant.STATUS_NOT_OVER);
                } else {
                    // 开票中
                    startService.updateBillStartStatus(invoiceResultDto.getWaybillNum(), CommonConstant.STATUS_MAKING_INVOICE);
                }

            }
        }
    }

    // 保存运单查询发票接口返回的外层数据
    private void saveSearchInvoice(InvoiceResultDto invoiceResultDto) {
        // 判断运单查询发票返回共用信息在数据库中是否存在，不存在则存入
        SearchInvoiceDto searchInvoiceDto = searchInvoiceService.getSearchInvoiceByNum(invoiceResultDto.getWaybillNum());
        if (searchInvoiceDto == null) {
            searchInvoiceService.saveSearchInvoice(invoiceResultDto);
        } else {
            BeanUtil.copyProperties(searchInvoiceDto, invoiceResultDto);
            searchInvoiceService.updateSearchInvoice(searchInvoiceDto);
        }
    }
}
