package com.dxhy.erp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.JxszcCancelEnum;
import com.dxhy.common.enums.JxszcZtEnum;
import com.dxhy.common.service.impl.MpBaseServiceImpl;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.common.utils.RRException;
import com.dxhy.common.vo.UserInfo;
import com.dxhy.erp.dao.BaseReceiptOutDao;
import com.dxhy.erp.entity.BaseInvoiceEditVO;
import com.dxhy.erp.entity.BaseTDxRecordInvoice;
import com.dxhy.erp.entity.BaseTDxRecordInvoiceOut;
import com.dxhy.erp.model.ErpInvoiceData;
import com.dxhy.erp.model.EsOutPutResp;
import com.dxhy.erp.model.OutPut;
import com.dxhy.erp.service.BaseIReceiptInvoiceService;
import com.dxhy.erp.service.IReceiptOutService;
import com.dxhy.erp.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 * @Author wangzhikun
 * @Date 2022/12/24 2022/12/24
 */
@Service
@Slf4j
public class ReceiptOutServiceImpl extends MpBaseServiceImpl<BaseReceiptOutDao, BaseTDxRecordInvoiceOut>
        implements IReceiptOutService  {
    @Resource
    BaseIReceiptInvoiceService baseIReceiptInvoiceService;
    @Override
    public String transfer(ErpInvoiceData erpInvoiceData, BaseInvoiceEditVO condVO, UserInfo userInfo) {
        OutPut outPut = new OutPut();
        EsOutPutResp es = new EsOutPutResp();
        es.setSAPKEY(erpInvoiceData.getIS_INPUT().getSAPKEY());
        es.setBSKEY(erpInvoiceData.getIS_INPUT().getBSKEY());
        es.setZTYPE("S");
        es.setZMESSAGE("处理成功");
        DynamicContextHolder.push("business"+DbConstant.BUSINESS_READ);

        String idStr = condVO.getPrimaryKey();
        String[] ids = idStr.split(",");

        // first：查询出底账表相关数据
        List<BaseTDxRecordInvoice> invoices = baseIReceiptInvoiceService.selectByUuids(ids);
        if(CollectionUtils.isEmpty(invoices)){
            es.setZTYPE("E");
            es.setZMESSAGE("底账数据不存在");
            outPut.setES_OUTPUT(es);
            return JsonUtils.getInstance().toJsonString(outPut);
        }
        // second：根据uuids查询出转出明细并转为map，key=uuid ，value=转出明细
        List<BaseTDxRecordInvoiceOut> outs = listByUuids(ids);
        Map<String, BaseTDxRecordInvoiceOut> outMap =
                outs.stream().collect(Collectors.toMap(BaseTDxRecordInvoiceOut::getUuid, tri -> tri));

        // third：设置底账表中的 进项税转出 部分相关字段
        List<BaseTDxRecordInvoice> condList = setPartInvoiceByType(invoices, condVO, userInfo);

        List<BaseTDxRecordInvoiceOut> outList = new ArrayList<>();
        // fourth：对比流水明细，区分底账表list中需要update或者insert数据的
        invoices.forEach(invoice -> {
            BaseTDxRecordInvoiceOut e = new BaseTDxRecordInvoiceOut();
            if (outMap.containsKey(invoice.getUuid())) {
                e = outMap.get(invoice.getUuid());
            }
            // 从构建的底账数据中（进项税转出相关字段），更新需要变更的流水字段
            e.setCompany(userInfo.getCompany());
            createInvoiceOut(condVO, userInfo, invoice, e);
            outList.add(e);
        });

        DynamicContextHolder.push("business" + DbConstant.BUSINESS_WRITE);
        excuteTransferWrite(condList, outList);
        outPut.setES_OUTPUT(es);
        return JsonUtils.getInstance().toJsonString(outPut);
    }
    /**
     * 根据uuids查询进项税转出明细
     *
     * @param uuids
     *            请求参数
     * @return 返回结果
     */
    private List<BaseTDxRecordInvoiceOut> listByUuids(String[] uuids) {
        QueryWrapper<BaseTDxRecordInvoiceOut> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(BaseTDxRecordInvoiceOut::getUuid, uuids);
        return super.list(queryWrapper);
    }
    /**
     * 根据转出类型 set 抵账表中进项税转出相关字段 (部分转出 or 全部转出)
     *
     * @param invoices
     *            请求参数
     * @param condVO
     *            请求参数
     * @param userInfo
     *            请求参数
     * @return 返回结果
     */
    private List<BaseTDxRecordInvoice> setPartInvoiceByType(List<BaseTDxRecordInvoice> invoices,
                                                            BaseInvoiceEditVO condVO, UserInfo userInfo) {
        List<BaseTDxRecordInvoice> condList = new ArrayList<>();
        for (BaseTDxRecordInvoice record : invoices) {
            record.setOutBelongDate(condVO.getOutTaxPeriod());
            BaseTDxRecordInvoice condRecord = new BaseTDxRecordInvoice();
            condRecord.setId(record.getId());
            // 转出状态
            condRecord.setOutStatus(condVO.getOutStatus());
            //表示转出来源是sap
            condRecord.setOutResource("1");
            // 转出原因
            condRecord.setOutReason(condVO.getOutReason());
            // 备注
            condRecord.setOutRemark(condVO.getOutRemark());
            // 转出日期
            condRecord.setOutDate(DateUtils.getNow());
            // 转出人
            condRecord.setOutBy(userInfo.getUsername());
            //转出金额取价税合计
            condRecord.setOutInvoiceAmout(record.getTotalAmount());
            // 税款所属期
            condRecord.setOutBelongDate(condVO.getOutTaxPeriod());
            if(record.getTaxAmount().compareTo(new BigDecimal(condVO.getOutTax()))==1){
                condRecord.setOutStatus("2");
                condVO.setOutStatus("2");
            }
            /*全部转出 */
            if (JxszcZtEnum.QBZC.getZcztDm().equals(condVO.getOutStatus())) {
                // 转出金额
                condRecord.setOutInvoiceAmout(record.getInvoiceAmount());
                // 转出税额
                condRecord.setOutTaxAmount(record.getDkTaxAmount());
            }
            /*部分转出 */
            if (JxszcZtEnum.BFZC.getZcztDm().equals(condVO.getOutStatus())) {
                /**
                // 转出金额累加
                BigDecimal oldOutAmount =
                        record.getOutInvoiceAmout() == null ? new BigDecimal(0) : record.getOutInvoiceAmout();

                BigDecimal newOutAmount = oldOutAmount.add(new BigDecimal(condVO.getOutAmount()));
                // -1=小于； 0=等于； 1=大于；
                int compareOut = newOutAmount.compareTo(record.getInvoiceAmount());
                if (compareOut > 0) {
                    throw new RRException("累计转出金额不能大于发票金额");
                }
                 **/
                // 转出金额
                condRecord.setOutInvoiceAmout(record.getInvoiceAmount());

                // 转出税额累加
                BigDecimal oldOutTax = record.getOutTaxAmount() == null ? new BigDecimal(0) : record.getOutTaxAmount();
                BigDecimal newOutTax = oldOutTax.add(new BigDecimal(condVO.getOutTax()));
                int compareTax = newOutTax.compareTo(record.getTaxAmount());
                if (compareTax > 0) {
                    throw new RRException("累计转出税额不能大于发票税额");
                }
                // 转出税额
                condRecord.setOutTaxAmount(newOutTax);

                if ( compareTax == 0) {
                    // 金额税额已经全部转完，设为 全部转出
                    condRecord.setOutStatus(JxszcZtEnum.QBZC.getZcztDm());
                }
            }
            condList.add(condRecord);

        }
        return condList;
    }

    /**
     * 构建进项税转出明细
     *
     * @param condVO
     *            请求参数
     * @param userInfo
     *            请求参数
     * @param invoice
     *            请求参数
     * @param record
     *            请求参数
     */
    private void createInvoiceOut(BaseInvoiceEditVO condVO, UserInfo userInfo, BaseTDxRecordInvoice invoice,
                                  BaseTDxRecordInvoiceOut record) {
        // uuid
        record.setUuid(invoice.getUuid());
        // 发票号码
        record.setInvoiceNo(invoice.getInvoiceNo());
        // 发票代码
        record.setInvoiceCode(invoice.getInvoiceCode());
        record.setOutBelongDate(invoice.getOutBelongDate());
        // 转出状态
        record.setOutStatus(condVO.getOutStatus());

        /* 全部转出 */
        if (JxszcZtEnum.QBZC.getZcztDm().equals(condVO.getOutStatus())) {
            // 转出金额
            record.setOutInvoiceAmout(invoice.getInvoiceAmount());
            // 转出税额
            record.setOutTaxAmount(invoice.getDkTaxAmount());
        }
        /* 部分转出 */
        if (JxszcZtEnum.BFZC.getZcztDm().equals(condVO.getOutStatus())) {
            // 转出金额
            record.setOutInvoiceAmout(invoice.getInvoiceAmount());

            // 转出税额累加
            BigDecimal oldOutTax = record.getOutTaxAmount() == null ? new BigDecimal(0) : record.getOutTaxAmount();
            BigDecimal newOutTax = oldOutTax.add(new BigDecimal(condVO.getOutTax()));
            int compareTax = newOutTax.compareTo(invoice.getTaxAmount());
            if (compareTax > 0) {
                throw new RRException("累计转出税额不能大于发票税额");
            }
            // 转出税额
            record.setOutTaxAmount(newOutTax);

            // 金额税额全部转完，设置状态为 全部转出
            if (compareTax == 0) {
                record.setOutStatus(JxszcZtEnum.QBZC.getZcztDm());
            }
        }

        // 转出日期
        record.setOutDate(DateUtils.getNow());
        // 转出原因
        record.setOutReason(condVO.getOutReason());
        // 备注
        record.setOutRemark(condVO.getOutRemark());
        // 转出人
        record.setOutBy(userInfo.getUsername());
        // 是否取消，默认未取消
        record.setIsCancel(JxszcCancelEnum.WQX.getQxztDm());
    }
    @Transactional(rollbackFor = Exception.class)
    public void excuteTransferWrite(List<BaseTDxRecordInvoice> condList, List<BaseTDxRecordInvoiceOut> outList) {
        // 流水表批量insert or update
        saveOrUpdateBatch(outList);
        // 抵账表批量update
        baseIReceiptInvoiceService.updateBatch(condList);
    }


}
