package com.dxhy.core.job.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dxhy.api.model.db.TdxTdysMhxcdEntity;
import com.dxhy.api.model.db.TdxTdysMhxcdMxEntity;
import com.dxhy.api.model.db.TdxTdysTldzkpEntity;
import com.dxhy.api.model.invoice.InvoiceDetailInfo;
import com.dxhy.common.constant.ConfigureConstant;
import com.dxhy.common.constant.CoreConstants;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.FplxEnum;
import com.dxhy.common.utils.CommonUtil;
import com.dxhy.core.dao.CoreCheckTaskDao;
import com.dxhy.core.dao.CoreConfirmDao;
import com.dxhy.core.job.dao.TDxRecordInvoiceDetailJobDao;
import com.dxhy.core.job.dao.TDxRecordInvoiceStatisticsJobDao;
import com.dxhy.core.job.dao.TDxVehicleSaleInvoiceDao;
import com.dxhy.core.job.entity.InvoiceCheckVehicleDetailModel;
import com.dxhy.core.job.entity.TAcOrg;
import com.dxhy.core.job.entity.TDxRecordInvoiceStatisticsJobEntity;
import com.dxhy.core.job.pojo.*;
import com.dxhy.core.job.service.CheckTaskService;
import com.dxhy.core.job.service.TDxRecordInvoiceDetailJobService;
import com.dxhy.jxpt.baseService.dao.TdxTdysMhxcdCoreDao;
import com.dxhy.jxpt.baseService.dao.TdxTdysMhxcdMxCoreDao;
import com.dxhy.jxpt.baseService.dao.TdxTdysTldzkpCoreDao;
import com.dxhy.jxpt.baseService.poolPush.PoolLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 功能描述
 *
 * @author 陈刚扬
 * @date 2020/10/28
 */
@SuppressWarnings({"AlibabaUndefineMagicConstant", "AlibabaMethodTooLong"})
@Service("checkTaskService")
@Slf4j
public class CheckTaskServiceImpl implements CheckTaskService {
    @Resource
    private CoreCheckTaskDao coreCheckTaskDao;
    @Resource
    private TdxTdysMhxcdCoreDao tdxTdysMhxcdCoreDao;
    @Resource
    private TdxTdysMhxcdMxCoreDao tdxTdysMhxcdMxCoreDao;
    @Resource
    private TdxTdysTldzkpCoreDao tdxTdysTldzkpCoreDao;
    @Resource
    private CoreConfirmDao coreConfirmDao;
    @Resource
    private TDxRecordInvoiceDetailJobDao tDxRecordInvoiceDetailDao;
    @Resource
    private TDxRecordInvoiceStatisticsJobDao tDxRecordInvoiceStatisticsDao;
    @Resource
    private PoolLogService poolLogService;
    @Resource
    private TDxVehicleSaleInvoiceDao tDxVehicleSaleInvoiceDao;
    @Resource
    private TDxRecordInvoiceDetailJobService tDxRecordInvoiceDetailJobService;

    @Override
    public List<CheckNoDetailInvoice> getNoDetailInvoice() {
        return coreCheckTaskDao.getNoDetailInvoice();
    }

    @Override
    public List<CheckNoDetailInvoice> getNoDetailInvoiceOld() {
        return coreCheckTaskDao.getNoDetailInvoiceOld();
    }

    /**
     * 查验
     *
     * @author 陈刚扬
     * @date 2020/10/28
     * @param checkNoDetailInvoice
     * @param db
     * @return void
     */
    @Override
    public void checkOne(CheckNoDetailInvoice checkNoDetailInvoice, String db) {
        // 构建请求数据
        final RequestData requestData = buildRequestData(checkNoDetailInvoice);
        // 调用接口验证
        final ResponseInvoice responseInvoice = sendRequest(requestData);
        // 查验成功
        DynamicContextHolder.push(db + DbConstant.BUSINESS_WRITE);
        if (responseInvoice != null) {
            if ("0001".equals(responseInvoice.getResultCode())) {
                List<InvoiceDetail> detailList = responseInvoice.getDetailList();
                String codeNo = CommonUtil.getUuid(responseInvoice.getInvoiceCode(),responseInvoice.getInvoiceNo());
                if ("03".equals(responseInvoice.getInvoiceType())) {
                    log.info("03票种：机动车统一销售发票 构建机动车统一销售发票明细");
                    List<InvoiceCheckVehicleDetailModel> vehicleDetailList = buildVehicleDetailList(responseInvoice);
                    if (vehicleDetailList.size() > 0) {
                        InvoiceCheckVehicleDetailModel invoiceCheckVehicleDetail = vehicleDetailList.get(0);
                        tDxRecordInvoiceDetailDao.delDetailJd(invoiceCheckVehicleDetail.getUuid());

                        for (InvoiceCheckVehicleDetailModel invoiceCheckVehicleDetailModel : vehicleDetailList) {
                            tDxVehicleSaleInvoiceDao.insert(invoiceCheckVehicleDetailModel);
                        }
                    }
                    tDxRecordInvoiceDetailDao.delDetailTaxRate(responseInvoice.getInvoiceCode(),
                            responseInvoice.getInvoiceNo());
                    // 保存抵账统计明细
                    // 设置税额统计表字段值
                    TDxRecordInvoiceStatisticsJobEntity tDxRecordInvoiceStatistics =
                            new TDxRecordInvoiceStatisticsJobEntity();
                    tDxRecordInvoiceStatistics.setInvoiceCode(responseInvoice.getInvoiceCode());
                    tDxRecordInvoiceStatistics.setInvoiceNo(responseInvoice.getInvoiceNo());
                    tDxRecordInvoiceStatistics.setDetailAmount(new BigDecimal(responseInvoice.getInvoiceAmount()));
                    if (responseInvoice.getTaxRate().contains("%")) {
                        responseInvoice.setTaxRate(responseInvoice.getTaxRate().replace("%", ""));
                    }
                    tDxRecordInvoiceStatistics.setTaxRate(CommonUtil.processTaxRate(responseInvoice.getTaxRate()));
                    try {
                        tDxRecordInvoiceStatistics.setTaxAmount(new BigDecimal(responseInvoice.getTaxAmount()));

                    } catch (Exception e) {
                        tDxRecordInvoiceStatistics.setTaxAmount(new BigDecimal("0"));
                    }
                    tDxRecordInvoiceStatistics.setTotalAmount(new BigDecimal(responseInvoice.getTotalAmount()));
                    tDxRecordInvoiceStatisticsDao.insert(tDxRecordInvoiceStatistics);

                    // 构建主表实体
                    InvoiceCollectionInfo invoiceCollectionInfo =
                            buildInvoiceCollectionInfo(responseInvoice, checkNoDetailInvoice.getBuyerTaxNo());
                    DynamicContextHolder.push(db + DbConstant.BUSINESS_READ);
                    int countdetail = tDxRecordInvoiceDetailDao
                            .getDetailJd(invoiceCollectionInfo.getInvoiceCode() + invoiceCollectionInfo.getInvoiceNo());
                    // 更新主表
                    if (countdetail > 0) {
                        invoiceCollectionInfo.setDetailYesorno("1");
                    } else {
                        invoiceCollectionInfo.setDetailYesorno("0");
                    }
                    DynamicContextHolder.push(db + DbConstant.BUSINESS_WRITE);
                    // 更新主表
                    coreCheckTaskDao.updateRecordInvoice(invoiceCollectionInfo);
                }
                else if("161".equals(responseInvoice.getInvoiceType())){
                    log.info("数电-航空票处理");
                    String uuid = StringUtils.isEmpty(responseInvoice.getInvoiceCode())?"":responseInvoice.getInvoiceCode() + responseInvoice.getInvoiceNo();
                    // 构建主表实体
                    InvoiceCollectionInfo invoiceCollectionInfo =
                            buildInvoiceCollectionInfo(responseInvoice, checkNoDetailInvoice.getBuyerTaxNo());

                    log.info("处理航空票数据");
                    log.info("1、航空主体表数据处理");
                    TdxTdysMhxcdEntity tdxTdysMhxcdEntity = buildTdysMhxcd(responseInvoice);
                    //先删除，再插入
                    tdxTdysMhxcdCoreDao.delete(new LambdaQueryWrapper<TdxTdysMhxcdEntity>().eq(TdxTdysMhxcdEntity::getUuid, uuid));
                    tdxTdysMhxcdCoreDao.insert(tdxTdysMhxcdEntity);

                    log.info("2、航空明细表数据处理");
                    List<TdxTdysMhxcdMxEntity> mhxcdMxEntityList = buildTdysMhxcdMx(responseInvoice,uuid);
                    //先删除，再插入
                    tdxTdysMhxcdMxCoreDao.delete(new LambdaQueryWrapper<TdxTdysMhxcdMxEntity>().eq(TdxTdysMhxcdMxEntity::getTdysId, uuid));
                    for (int i = 0; i < mhxcdMxEntityList.size(); i++) {
                        tdxTdysMhxcdMxCoreDao.insert(mhxcdMxEntityList.get(i));
                    }

                    int countdetail = mhxcdMxEntityList.size();
                    log.info("更新主表");
                    if (countdetail > 0) {
                        invoiceCollectionInfo.setDetailYesorno("1");
                    } else {
                        invoiceCollectionInfo.setDetailYesorno("0");
                    }
                    coreCheckTaskDao.updateRecordInvoice(invoiceCollectionInfo);
                }
                else if("283".equals(responseInvoice.getInvoiceType())){
                    log.info("数电-铁路客运票处理");
                    String uuid = StringUtils.isEmpty(responseInvoice.getInvoiceCode())?"":responseInvoice.getInvoiceCode() + responseInvoice.getInvoiceNo();
                    // 构建主表实体
                    InvoiceCollectionInfo invoiceCollectionInfo =
                            buildInvoiceCollectionInfo(responseInvoice, checkNoDetailInvoice.getBuyerTaxNo());

                    log.info("构建铁路客运票");
                    TdxTdysTldzkpEntity tdxTdysTldzkpEntity = buildTdysTldzkp(responseInvoice,uuid);
                    //先删除，再插入
                    tdxTdysTldzkpCoreDao.delete(new LambdaQueryWrapper<TdxTdysTldzkpEntity>().eq(TdxTdysTldzkpEntity::getUuid, uuid));
                    tdxTdysTldzkpCoreDao.insert(tdxTdysTldzkpEntity);

                    //数电-铁路用主体和明细组装，肯定有明细
                    invoiceCollectionInfo.setDetailYesorno("1");

                    log.info("更新主表");
                    coreCheckTaskDao.updateRecordInvoice(invoiceCollectionInfo);
                }
                else {
                    // 如果明细不为空则保存明细,保存明细统计，更新主表
                    final List<InvoiceDetailInfo> invoiceDetailInfoList = buildDetailList(responseInvoice);
                    if (detailList != null && detailList.size() > 0) {
                        // 保存明细表 之前先删除
                        InvoiceDetailInfo invoiceDetail = invoiceDetailInfoList.get(0);
                        deleteDetail(invoiceDetail, db);
                    }
                    // 插入明细数据
                    insertDetail(db, invoiceDetailInfoList);
                    // 构建统计表发票明细
                    DynamicContextHolder.push(db + DbConstant.BUSINESS_WRITE);
                    final List<TDxRecordInvoiceStatisticsJobEntity> recordInvoiceStatisticsList =
                            buildRecordInvoiceStatisticsList(responseInvoice);
                    if (recordInvoiceStatisticsList.size() > 0) {
                        // 保存抵账统计明细
                        TDxRecordInvoiceStatisticsJobEntity recordInvoiceStatistics =
                                recordInvoiceStatisticsList.get(0);
                        tDxRecordInvoiceDetailDao.delDetailTaxRate(recordInvoiceStatistics.getInvoiceCode(),
                                recordInvoiceStatistics.getInvoiceNo());

                        for (TDxRecordInvoiceStatisticsJobEntity invoiceStatistics : recordInvoiceStatisticsList) {
                            // 需要用mybatisPlus转换一下插入数据库
                            tDxRecordInvoiceStatisticsDao.insert(invoiceStatistics);
                        }

                    }

                    // 构建主表实体
                    InvoiceCollectionInfo invoiceCollectionInfo =
                            buildInvoiceCollectionInfo(responseInvoice, checkNoDetailInvoice.getBuyerTaxNo());

                    int countdetail = getDetailCount(invoiceCollectionInfo, db);
                    // 更新主表
                    if (countdetail > 0) {
                        invoiceCollectionInfo.setDetailYesorno("1");
                    } else {
                        invoiceCollectionInfo.setDetailYesorno("0");
                    }
                    DynamicContextHolder.push(db + DbConstant.BUSINESS_WRITE);
                    coreCheckTaskDao.updateRecordInvoice(invoiceCollectionInfo);

                }
                //推送新票池记录表
                poolLogService.pushChangeToPool(ConfigureConstant.POOL_SJLX_JXFP_1, codeNo, ConfigureConstant.POOL_BGLX_SJBG_1);
            }
        }

    }

    /**
    * @Description 构建数电-铁路信息 tdys_tldzkp
    * @param responseInvoice
    * @param uuid
     * @Return com.dxhy.api.model.db.TdxTdysTldzkpEntity
    * @Author wangruwei
    * @Date 2024/4/22 16:02
    **/
    private TdxTdysTldzkpEntity buildTdysTldzkp(ResponseInvoice responseInvoice, String uuid) {
        InvoiceDetail detail = new InvoiceDetail();
        if(!CollectionUtils.isEmpty(responseInvoice.getDetailList())){
            detail = responseInvoice.getDetailList().get(0);
        }
        TdxTdysTldzkpEntity tdxTdysTldzkpEntity = new TdxTdysTldzkpEntity();
        tdxTdysTldzkpEntity.setUuid(uuid);
        //tdxTdysTldzkpEntity.setGmfjbr();
        //tdxTdysTldzkpEntity.setJbrsfzjhm();
        //tdxTdysTldzkpEntity.setJbrlxdh();
        //tdxTdysTldzkpEntity.setKprsrrzdzxx();
        //tdxTdysTldzkpEntity.setSjkpdzxx();
        //tdxTdysTldzkpEntity.setHtbh();
        //tdxTdysTldzkpEntity.setNsywfssj();
        //tdxTdysTldzkpEntity.setJbrsfzjzlDm();
        tdxTdysTldzkpEntity.setSpsl(detail.getNum());
        //tdxTdysTldzkpEntity.setSfwzzfp();
        tdxTdysTldzkpEntity.setFphm(responseInvoice.getInvoiceNo());
        tdxTdysTldzkpEntity.setZjhm(responseInvoice.getIdNumber());
        tdxTdysTldzkpEntity.setKprq(responseInvoice.getInvoiceDate());
        tdxTdysTldzkpEntity.setYwlxmc(CommonUtil.changeTlkpYwlx(responseInvoice.getBusinessType()));
        tdxTdysTldzkpEntity.setCfz(responseInvoice.getDepartureStation());
        //tdxTdysTldzkpEntity.setCfzpy();
        tdxTdysTldzkpEntity.setDdz(responseInvoice.getDestinationStation());
        //tdxTdysTldzkpEntity.setDdzpy();
        tdxTdysTldzkpEntity.setCccc(responseInvoice.getTrainNumber());
        tdxTdysTldzkpEntity.setRq(responseInvoice.getRideDate());
        tdxTdysTldzkpEntity.setCfsjl(responseInvoice.getDepartureTime());
        tdxTdysTldzkpEntity.setTldzkppzmc(responseInvoice.getCurrency());
        tdxTdysTldzkpEntity.setKttz(responseInvoice.getAirConditionerType());
        tdxTdysTldzkpEntity.setXbl(responseInvoice.getSchiebetsu());
        tdxTdysTldzkpEntity.setCx(responseInvoice.getCarriage());
        tdxTdysTldzkpEntity.setXw(responseInvoice.getSeat());
        tdxTdysTldzkpEntity.setZfje(detail.getDetailAmount());
        //tdxTdysTldzkpEntity.setYtje();
        //tdxTdysTldzkpEntity.setYppj();
        tdxTdysTldzkpEntity.setTaxRate(detail.getTaxRate());
        tdxTdysTldzkpEntity.setYpcfz(responseInvoice.getDepartureStation());
        tdxTdysTldzkpEntity.setYpddz(responseInvoice.getDestinationStation());
        tdxTdysTldzkpEntity.setDzkph(responseInvoice.getElectronicTicketNumber());
        tdxTdysTldzkpEntity.setXm(responseInvoice.getName());
        //tdxTdysTldzkpEntity.setTlkpyhlx();
        //tdxTdysTldzkpEntity.setYfphm();
        tdxTdysTldzkpEntity.setCreateTime(new Date());
        return tdxTdysTldzkpEntity;
    }

    /**
    * @Description 构建民航行程单-明细信息
    * @param responseInvoice
    * @param uuid
     * @Return java.util.List<com.dxhy.api.model.db.TdxTdysMhxcdMxEntity>
    * @Author wangruwei
    * @Date 2024/4/22 15:49
    **/
    private List<TdxTdysMhxcdMxEntity> buildTdysMhxcdMx(ResponseInvoice responseInvoice, String uuid) {
        List<TdxTdysMhxcdMxEntity> mhxcdMx = new LinkedList<>();
        if(!CollectionUtils.isEmpty(responseInvoice.getDetailList())){
            for (int i = 0; i < responseInvoice.getDetailList().size(); i++) {
                //大企业返回的对象
                InvoiceDetail invoiceDetail = responseInvoice.getDetailList().get(i);
                TdxTdysMhxcdMxEntity item = new TdxTdysMhxcdMxEntity();
                item.setTdysId(uuid);
                item.setSfz(responseInvoice.getIdNumber());
                item.setMdz(invoiceDetail.getDestinationStation());
                item.setHd(invoiceDetail.getLeg());
                item.setCyr(invoiceDetail.getCarrier());
                item.setHbh(invoiceDetail.getFlightNumber());
                item.setZwdj(invoiceDetail.getSeatingClass());
                item.setCyrq(invoiceDetail.getShipmentDate());
                item.setQfsj(invoiceDetail.getDepartureTime());
                item.setKpjbkplb(invoiceDetail.getTicketClass());
                //item.setKpsxrq();
                //item.setYxjzrq();
                //item.setMfxle();
                item.setCreateTime(new Date());
                mhxcdMx.add(item);
            }
        }
        return mhxcdMx;
    }

    /**
    * @Description 构建民航行程单-主信息
    * @param responseInvoice
    * @Return com.dxhy.api.model.db.TdxTdysMhxcdEntity
    * @Author wangruwei
    * @Date 2024/4/22 14:56
    **/
    private TdxTdysMhxcdEntity buildTdysMhxcd(ResponseInvoice responseInvoice) {
        TdxTdysMhxcdEntity tdxTdysMhxcdEntity = new TdxTdysMhxcdEntity();
        tdxTdysMhxcdEntity.setUuid(StringUtils.isBlank(responseInvoice.getInvoiceCode())?"":responseInvoice.getInvoiceCode()+responseInvoice.getInvoiceNo());
        //tdxTdysMhxcdEntity.setGmfjbr();
        //tdxTdysMhxcdEntity.setTicketPrice();
        //tdxTdysMhxcdEntity.setFuelSurcharge();
        //tdxTdysMhxcdEntity.setValueAddedTaxAmount();
        //tdxTdysMhxcdEntity.setVatRate();
        //tdxTdysMhxcdEntity.setAviationDevelopmentFund();
        //tdxTdysMhxcdEntity.setOtherTaxes();
        //tdxTdysMhxcdEntity.setJbrsfzjhm();
        //tdxTdysMhxcdEntity.setJbrlxdh();
        //tdxTdysMhxcdEntity.setKprsrrzdzxx();
        //tdxTdysMhxcdEntity.setSjkpdzxx();
        //tdxTdysMhxcdEntity.setHtbh();
        //tdxTdysMhxcdEntity.setNsywfssj();
        //tdxTdysMhxcdEntity.setJbrsfzjzlDm();
        //tdxTdysMhxcdEntity.setSpsl();
        //tdxTdysMhxcdEntity.setSfwzzfp();
        tdxTdysMhxcdEntity.setFphm(responseInvoice.getInvoiceNo());
        tdxTdysMhxcdEntity.setGngjbz(responseInvoice.getNationalMark());
        tdxTdysMhxcdEntity.setGpdh(responseInvoice.getGpNumber());
        //tdxTdysMhxcdEntity.setSflzfpbz();
        tdxTdysMhxcdEntity.setXm(responseInvoice.getName());
        tdxTdysMhxcdEntity.setZjhm(responseInvoice.getIdNumber());
        //tdxTdysMhxcdEntity.setQz();
        tdxTdysMhxcdEntity.setDzkphm(responseInvoice.getElectronicTicketNumber());
        //tdxTdysMhxcdEntity.setYzm();
        //tdxTdysMhxcdEntity.setTsxx();
        //tdxTdysMhxcdEntity.setBxf();
        //tdxTdysMhxcdEntity.setXswddh();
        //tdxTdysMhxcdEntity.setTkdw();
        tdxTdysMhxcdEntity.setKprq(responseInvoice.getInvoiceDate());
        tdxTdysMhxcdEntity.setXsfmc(responseInvoice.getSalerName());
        tdxTdysMhxcdEntity.setXsfnsrsbh(responseInvoice.getSalerTaxNo());
        tdxTdysMhxcdEntity.setGmfmc(responseInvoice.getBuyerName());
        tdxTdysMhxcdEntity.setGmfnsrsbh(responseInvoice.getBuyerTaxNo());
        tdxTdysMhxcdEntity.setCreateTime(new Date());
        return tdxTdysMhxcdEntity;
    }

    private int getDetailCount(InvoiceCollectionInfo invoiceCollectionInfo, String db) {
        DynamicContextHolder.push(db + DbConstant.DETAIL_WRITE);
        return tDxRecordInvoiceDetailDao
            .getDetailCount(invoiceCollectionInfo.getUuid());
    }

    private void insertDetail(String db, List<InvoiceDetailInfo> invoiceDetailInfoList) {
        if (invoiceDetailInfoList != null && invoiceDetailInfoList.size() > 0) {
            DynamicContextHolder.push(db + DbConstant.DETAIL_WRITE);
            tDxRecordInvoiceDetailJobService.saveBatch(invoiceDetailInfoList);
        }
    }

    private void deleteDetail(InvoiceDetailInfo invoiceDetail, String db) {
        DynamicContextHolder.push(db + DbConstant.DETAIL_WRITE);
        coreCheckTaskDao.deleteDetail(invoiceDetail);
    }

    private RequestData buildRequestData(CheckNoDetailInvoice checkNoDetailInvoice) {
        // 请求数据
        final RequestData requestData = new RequestData();
        // 购方税号
        requestData.setBuyerTaxNo(checkNoDetailInvoice.getBuyerTaxNo());
        // 发票类型
        requestData.setInvoiceType(checkNoDetailInvoice.getInvoiceType());
        if (FplxEnum.QDZZP.getFplxDm().equals(checkNoDetailInvoice.getInvoiceType()) ||
                FplxEnum.QDPP.getFplxDm().equals(checkNoDetailInvoice.getInvoiceType()) ||
                FplxEnum.TLKP.getFplxDm().equals(checkNoDetailInvoice.getInvoiceType()) ||
                FplxEnum.HKDZFP.getFplxDm().equals(checkNoDetailInvoice.getInvoiceType())) {
            requestData.setInvoiceCode("");
            requestData.setInvoiceNo(checkNoDetailInvoice.getInvoiceCode() + checkNoDetailInvoice.getInvoiceNo());
            // 金额
            requestData.setInvoiceAmount(checkNoDetailInvoice.getTotalAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        } else {
            // 发票代码
            requestData.setInvoiceCode(checkNoDetailInvoice.getInvoiceCode());
            // 发票号码
            requestData.setInvoiceNo(checkNoDetailInvoice.getInvoiceNo());
            // 金额
            requestData.setInvoiceAmount(checkNoDetailInvoice.getInvoiceAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        }

        // 开票时间
        String sdate = (new SimpleDateFormat("yyyyMMdd")).format(checkNoDetailInvoice.getInvoiceDate());
        requestData.setInvoiceDate(sdate);
        // 验证码
        requestData.setCheckCode(checkNoDetailInvoice.getCheckCode());

        return requestData;
    }

    public ResponseInvoice sendRequest(RequestData requestData) {
        String taxno = requestData.getBuyerTaxNo();
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        //区分secretId和secretKey是从配置文件来还是数据库读取
        if(CoreConstants.enterprisePermissionFlag){
            // 通过税号获取id和key
            TAcOrg org = coreConfirmDao.findIdAndKeyByTaxno(taxno);
            if(org!=null){
                CoreConstants.aceId = org.getAceId();
                CoreConstants.aceKey = org.getAceKey();
            }
        }
        // 定义返回值
        ResponseInvoice responseInvoice = null;

        // 请求通用头
        final GlobalInfo globalInfo = new GlobalInfo();
        // 请求通用
        final Authorize authorize = new Authorize();

        final BaseQueJson bqj = new BaseQueJson();

        log.info("-定时查验封装参数-");
        try {
            // 封装参数
            globalInfo.setAppId(CoreConstants.appId);
            globalInfo.setVersion(CoreConstants.version);
            String dataExchangeId = getDataExchangeId();
            globalInfo.setDataExchangeId(dataExchangeId);
            globalInfo.setInterfaceCode(CoreConstants.invoiceCheckOne);
            globalInfo.setEnterpriseCode(CoreConstants.enterpriseCode);

            authorize.setAppSecId(CoreConstants.aceId);

            String dataStr = JSONObject.toJSONString(requestData);

            log.info("data：{}", dataStr);
            String base64Data = Base64.encode(dataStr);

            String appSec = makeAppSec(base64Data, dataExchangeId, CoreConstants.invoiceCheckOne, CoreConstants.aceId, CoreConstants.aceKey);
            authorize.setAppSec(appSec);
            bqj.setAuthorize(authorize);
            bqj.setGlobalInfo(globalInfo);

            bqj.setData(base64Data);
            String collectDataStr = JSONObject.toJSONString(bqj);

            log.info("url:{}", CoreConstants.collectUrl);
            log.info("请求参数：{}", collectDataStr);
            log.info("发送请求--");
            final String responseJson = HttpUtil.post(CoreConstants.collectUrl, collectDataStr, 600000);

            log.info("返回报文:{}", responseJson);

            final BaseResJson baseResJson = JSONObject.parseObject(responseJson, BaseResJson.class);

            if ("0000".equals(baseResJson.getReturnStateInfo().getReturnCode())) {
                String dataJson = Base64.decodeStr(baseResJson.getData());

                log.info("查验返回data体：{}", dataJson);
                responseInvoice = JSONObject.parseObject(dataJson, ResponseInvoice.class);
            }

        } catch (Exception e) {
           log.info("业务处理异常：{}", e);
            log.error("手动验证失败:{}", e.getMessage());
        }
        return responseInvoice;
    }

    /**
     * 生成交换流水号
     *
     * @return
     */
    private String getDataExchangeId() {
        // enterpriseCode+8 位日期
        // (YYYYMMDD)+9 位序列号
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        StringBuilder sb = new StringBuilder();
        Random rand = new Random();
        for (int i = 0; i < 9; i++) {
            sb.append(rand.nextInt(10));
        }
        String data = sb.toString();
        return CoreConstants.enterpriseCode + simpleDateFormat.format(new Date()) + data;
    }

    /**
     * 加密方法
     */
    public String makeAppSec(String data, String dataExchangeId, String interfaceCode, String secretId,
        String secretKey) {
        String srcStr =
            "POST/rest/invoice/dii?authorize={\"appSecId\":\"" + secretId + "\"}&globalInfo={\"appId\":\"" + CoreConstants.appId
                + "\",\"version\":\"" + CoreConstants.version + "\",\"interfaceCode\":\"" + interfaceCode + "\",\"enterpriseCode\":\""
                + CoreConstants.enterpriseCode + "\",\"dataExchangeId\":\"" + dataExchangeId + "\"}&" + "data=" + data + "";
        log.info("待加密的请求：" + srcStr);
        SecretKeySpec keySpec = null;
        keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
        Mac mac = null;
        try {
            mac = Mac.getInstance("HmacSHA1");
        } catch (NoSuchAlgorithmException e) {
           log.info("业务处理异常：{}", e);
        }
        try {
            mac.init(keySpec);
        } catch (InvalidKeyException e) {
           log.info("业务处理异常：{}", e);
        }
        byte[] singBytes = new byte[0];
        singBytes = mac.doFinal(srcStr.getBytes(StandardCharsets.UTF_8));
        String appSec = Base64.encode(singBytes);
        log.info("interfaceCode接口生成的加密串=appSec--");
        return appSec;
    }

    /**
     * 解析明細
     *
     * @param responseInvoice
     * @return
     */
    private List<InvoiceDetailInfo> buildDetailList(ResponseInvoice responseInvoice) {
        // 构建返回值
        final List<InvoiceDetailInfo> invoiceDetailInfoList = new ArrayList<>();

        // 明细
        final List<InvoiceDetail> invoiceDetailList = responseInvoice.getDetailList();

        invoiceDetailList.forEach(invoiceDetail -> {
            final InvoiceDetailInfo invoiceDetailInfo = new InvoiceDetailInfo();
            // 税额
            invoiceDetailInfo.setTaxAmount(invoiceDetail.getTaxAmount());
            // 货物或应税劳务名称
            invoiceDetailInfo.setGoodsName(invoiceDetail.getGoodsName());
            // 发票号码
            invoiceDetailInfo.setInvoiceNo(responseInvoice.getInvoiceNo());
            // 发票代码
            invoiceDetailInfo.setInvoiceCode(responseInvoice.getInvoiceCode());
            // 数量
            invoiceDetailInfo.setNum(invoiceDetail.getNum());
            // 明细序号
            invoiceDetailInfo.setDetailNo(invoiceDetail.getDetailNo());
            // 单价
            invoiceDetailInfo.setUnitPrice(invoiceDetail.getUnitPrice());
            // 类型
            invoiceDetailInfo.setLx(invoiceDetail.getLx());
            // uuid唯一标识(发票代码+发票号码)
            invoiceDetailInfo.setUuid(responseInvoice.getInvoiceCode() + responseInvoice.getInvoiceNo());
            // 通行日期起
            invoiceDetailInfo.setTxrqq(invoiceDetail.getTxrqq());
            // 通行日期止
            invoiceDetailInfo.setTxrqz(invoiceDetail.getTxrqz());
            // 税率
            invoiceDetailInfo.setTaxRate(CommonUtil.processTaxRate(invoiceDetail.getTaxRate()));
            // 单位
            invoiceDetailInfo.setUnit(invoiceDetail.getUnit());
            // 金额
            invoiceDetailInfo.setDetailAmount(invoiceDetail.getDetailAmount());
            // 规格型号
            invoiceDetailInfo.setModel(invoiceDetail.getSpecificationModel());
            // 车牌号
            invoiceDetailInfo.setCph(invoiceDetail.getCph());
            // 放入集合
            invoiceDetailInfoList.add(invoiceDetailInfo);
        });
        return invoiceDetailInfoList;
    }

    /**
     * 构建统计实体集
     *
     * @param responseInvoice
     *            响应实体
     * @return 抵账统计实体
     */
    @SuppressWarnings("AlibabaCollectionInitShouldAssignCapacity")
    private List<TDxRecordInvoiceStatisticsJobEntity>
        buildRecordInvoiceStatisticsList(ResponseInvoice responseInvoice) {
        // 定义返回值
        final List<TDxRecordInvoiceStatisticsJobEntity> recordInvoiceStatisticsList = new ArrayList<>();

        // 明细
        List<InvoiceDetail> invoiceDetailList;

        // 如果为机动车统计销售发票
        if ("03".equals(responseInvoice.getInvoiceType())) {
            invoiceDetailList = motorVehicleDetail(responseInvoice);
        } else {
            // 不为机动车统计销售发票
            invoiceDetailList = responseInvoice.getDetailList();
        }

        // 最终要的结果
        final Map<String, List<InvoiceDetail>> resultMap = new HashMap<>();
        // 按税率分组
        invoiceDetailList.forEach(dataItem -> {
            if (!"原价合计".equals(dataItem.getGoodsName().trim()) && !"折扣额合计".equals(dataItem.getGoodsName().trim())
                && !"(详见销货清单)".equals(dataItem.getGoodsName().trim())&& !"（详见销货清单）".equals(dataItem.getGoodsName().trim()) && StringUtils.isNotEmpty(dataItem.getTaxRate())) {
                if (resultMap.containsKey(CommonUtil.processTaxRate(dataItem.getTaxRate()))) {
                    resultMap.get(CommonUtil.processTaxRate(dataItem.getTaxRate())).add(dataItem);
                } else {
                    final List<InvoiceDetail> list = new ArrayList<>();
                    list.add(dataItem);
                    resultMap.put(CommonUtil.processTaxRate(dataItem.getTaxRate()), list);
                }
            }
        });

        // 循环遍历map获取每组明细，并循环遍历每组里的明细组装抵账统计数据
        for (Map.Entry<String, List<InvoiceDetail>> entry : resultMap.entrySet()) {
            // 获取每组明细
            final List<InvoiceDetail> detailList = entry.getValue();
            // 定义抵账统计实体
            final TDxRecordInvoiceStatisticsJobEntity recordInvoiceStatistics =
                new TDxRecordInvoiceStatisticsJobEntity();
            // 税额
            BigDecimal taxAmount = new BigDecimal("0.0");
            // 金额
            BigDecimal detailAmount = new BigDecimal("0.0");
            // 循环赋值
            for (InvoiceDetail invoiceDetail : detailList) {
                BigDecimal detailTaxAmount;
                try {
                    detailTaxAmount = new BigDecimal(invoiceDetail.getTaxAmount());
                } catch (Exception e) {
                    detailTaxAmount = new BigDecimal(0);
                }
                taxAmount = taxAmount.add(detailTaxAmount);
                detailAmount = detailAmount.add(new BigDecimal(invoiceDetail.getDetailAmount()));

            }
            // 价税合计
            final BigDecimal totalAmount = taxAmount.add(detailAmount);
            // 税率
            try {

                recordInvoiceStatistics.setTaxRate(CommonUtil.processTaxRate(entry.getKey()));
            } catch (Exception e) {
                log.info("类型转换错误:{}", e.getMessage());
                recordInvoiceStatistics.setTaxRate("0");
            }
            // 发票号码
            recordInvoiceStatistics.setInvoiceNo(responseInvoice.getInvoiceNo());
            // 发票代码
            recordInvoiceStatistics.setInvoiceCode(responseInvoice.getInvoiceCode());
            // 税额
            recordInvoiceStatistics.setTaxAmount(taxAmount);
            // 金额
            recordInvoiceStatistics.setDetailAmount(detailAmount);
            // 价税合计
            recordInvoiceStatistics.setTotalAmount(totalAmount);
            // 放入集合
            recordInvoiceStatisticsList.add(recordInvoiceStatistics);
        }
        // 返回
        return recordInvoiceStatisticsList;
    }

    /**
     * 机动车统一销售发票明细 这种发票没有detailList 故明细信息需从主体信息中获取
     *
     * @param responseInvoice
     *            查验响应实体
     * @return 机动车统一销售发票明细
     */
    private List<InvoiceDetail> motorVehicleDetail(ResponseInvoice responseInvoice) {
        final List<InvoiceDetail> invoiceDetailList = new ArrayList<>();
        final InvoiceDetail invoiceDetail = new InvoiceDetail();
        // 税率
        invoiceDetail.setTaxRate(responseInvoice.getTaxRate());
        // 税额
        invoiceDetail.setTaxAmount(responseInvoice.getTaxAmount());
        // 金额
        invoiceDetail.setDetailAmount(responseInvoice.getInvoiceAmount());

        invoiceDetailList.add(invoiceDetail);
        return invoiceDetailList;
    }

    /**
     * 构建抵账主体数据
     *
     * @param responseInvoice
     *            抵账主体数据
     * @return 主体数据
     */
    private InvoiceCollectionInfo buildInvoiceCollectionInfo(ResponseInvoice responseInvoice, String buyerTaxNo) {
        // 定义返回值
        final InvoiceCollectionInfo invoiceCollectionInfo = new InvoiceCollectionInfo();
        // 购方税号
        invoiceCollectionInfo.setGfTaxNo(responseInvoice.getBuyerTaxNo());
        // 购方名称
        invoiceCollectionInfo.setGfName(responseInvoice.getBuyerName());
        // 发票类型
        invoiceCollectionInfo.setInvoiceType(responseInvoice.getInvoiceType());
        // 发票代码
        invoiceCollectionInfo.setInvoiceCode(responseInvoice.getInvoiceCode());
        // 发票号码
        invoiceCollectionInfo.setInvoiceNo(responseInvoice.getInvoiceNo());
        // 价税合计
        invoiceCollectionInfo.setTotalAmount(responseInvoice.getTotalAmount());
        // 金额
        invoiceCollectionInfo.setInvoiceAmount(responseInvoice.getInvoiceAmount());
        // 税额
        try {
            BigDecimal taxAmount = new BigDecimal(responseInvoice.getTaxAmount());
            invoiceCollectionInfo.setTaxAmount(responseInvoice.getTaxAmount());
        } catch (Exception e) {
            invoiceCollectionInfo.setTaxAmount("0");
        }
        // 销方税号
        invoiceCollectionInfo.setXfTaxNo(responseInvoice.getSalerTaxNo());
        // 销方名称
        invoiceCollectionInfo.setXfName(responseInvoice.getSalerName());
        // 销方地址
        invoiceCollectionInfo.setXfAddressAndPhone(responseInvoice.getSalerAddressPhone());
        // 销方银行帐号
        invoiceCollectionInfo.setXfBankAndNo(responseInvoice.getSalerAccount());
        // 购方银行帐号
        invoiceCollectionInfo.setGfBankAndNo(responseInvoice.getBuyerAccount());
        // 购方地址
        invoiceCollectionInfo.setGfAddressAndPhone(responseInvoice.getBuyerAddressPhone());
        // 开票日期
        final DateTime invoiceDateTime =
            DateTimeFormat.forPattern("yyyyMMdd").parseDateTime(responseInvoice.getInvoiceDate());
        invoiceCollectionInfo.setInvoiceDate(invoiceDateTime.toDate());
        // 备注
        invoiceCollectionInfo.setRemark(responseInvoice.getRemark());
        // 校验码
        invoiceCollectionInfo.setCheckCode(responseInvoice.getCheckCode());
        // 有明细
        invoiceCollectionInfo.setDetailYesorno("1");
        // uuid
        invoiceCollectionInfo.setUuid(responseInvoice.getInvoiceCode() + responseInvoice.getInvoiceNo());
        // 更新前的购方税号，放置不一致
        invoiceCollectionInfo.setBuyerTaxNo(buyerTaxNo);
        // 发票状态
        if (!"01".equals(invoiceCollectionInfo.getInvoiceType()) && !"03".equals(invoiceCollectionInfo.getInvoiceType())
            && !"14".equals(invoiceCollectionInfo.getInvoiceType())
            && !"08".equals(invoiceCollectionInfo.getInvoiceType())) {
            if ("N".equals(responseInvoice.getIsCancelled())) {
                invoiceCollectionInfo.setInvoiceStatus("0");
            } else if ("Y".equals(responseInvoice.getIsCancelled())) {
                invoiceCollectionInfo.setInvoiceStatus("2");
            } else {
                invoiceCollectionInfo.setInvoiceStatus(responseInvoice.getIsCancelled());
            }
        }

        // 机器编号
        invoiceCollectionInfo.setMachinecode(responseInvoice.getMachineNo());

        invoiceCollectionInfo.setQsType(responseInvoice.getQsType());
        // 返回
        return invoiceCollectionInfo;
    }

    /**
     * 构建机动车销售明细集
     *
     * @param responseInvoice
     *            查验响应实体
     * @return 机动车销售明细集
     */
    private List<InvoiceCheckVehicleDetailModel> buildVehicleDetailList(ResponseInvoice responseInvoice) {
        final List<InvoiceCheckVehicleDetailModel> vehicleDetailModelList = new ArrayList<>();
        final InvoiceCheckVehicleDetailModel invoiceCheckVehicleDetailModel = new InvoiceCheckVehicleDetailModel();
        invoiceCheckVehicleDetailModel.setUuid(responseInvoice.getInvoiceCode() + responseInvoice.getInvoiceNo());
        invoiceCheckVehicleDetailModel.setBuyerIdNum(responseInvoice.getBuyerIDNum());
        invoiceCheckVehicleDetailModel.setVehicleType(responseInvoice.getVehicleType());
        invoiceCheckVehicleDetailModel.setFactoryModel(responseInvoice.getFactoryModel());
        invoiceCheckVehicleDetailModel.setProductPlace(responseInvoice.getProductPlace());
        invoiceCheckVehicleDetailModel.setCertificate(responseInvoice.getCertificate());
        invoiceCheckVehicleDetailModel.setCertificateImport(responseInvoice.getCertificateImport());
        invoiceCheckVehicleDetailModel.setInspectionNum(responseInvoice.getInspectionNum());
        invoiceCheckVehicleDetailModel.setEngineNo(responseInvoice.getEngineNo());
        invoiceCheckVehicleDetailModel.setVehicleNo(responseInvoice.getVehicleNo());
        invoiceCheckVehicleDetailModel.setTaxRate(responseInvoice.getTaxRate());
        invoiceCheckVehicleDetailModel.setTaxBureauName(responseInvoice.getTaxBureauName());
        invoiceCheckVehicleDetailModel.setTaxBureauCode(responseInvoice.getTaxBureauCode());
        invoiceCheckVehicleDetailModel.setTaxRecords(responseInvoice.getTaxRecords());
        invoiceCheckVehicleDetailModel.setLimitPeople(responseInvoice.getLimitPeople());
        invoiceCheckVehicleDetailModel.setTonnage(responseInvoice.getTonnage());
        invoiceCheckVehicleDetailModel.setDeptId(responseInvoice.getDeptId());
        invoiceCheckVehicleDetailModel.setDeptName(responseInvoice.getDeptName());
        vehicleDetailModelList.add(invoiceCheckVehicleDetailModel);
        return vehicleDetailModelList;
    }
}
