package cn.superdesk.uniorder.dubbo.provider.thirdpart.qchjc.accounting;

import cn.hutool.core.date.DateUtil;
import cn.superdesk.uniorder.common.enums.accounting.supplier.AccountingOrderSupplierAccountingStatusEnum;
import cn.superdesk.uniorder.common.enums.thirdpart.qchjc.QchjcStorageStatusEnum;
import cn.superdesk.uniorder.common.exception.OpenApiException;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.security.dto.LoginSysUser;
import cn.superdesk.uniorder.dao.entity.accounting.unified.supplier.AccountingUnifiedSupplier;
import cn.superdesk.uniorder.dao.entity.invoice.common.InvoiceBankInfo;
import cn.superdesk.uniorder.dao.entity.invoice.supplier.InvoiceApplySupplier;
import cn.superdesk.uniorder.dao.entity.invoice.supplier.InvoiceApplySupplierExample;
import cn.superdesk.uniorder.dao.entity.thirdpart.qchjc.accounting.QchjcAccountingUnifiedSupplierEntity;
import cn.superdesk.uniorder.dao.entity.thirdpart.qchjc.invoice.QchjcInvoiceApplySupplierEntity;
import cn.superdesk.uniorder.dao.mapper.invoice.supplier.InvoiceApplySupplierMapper;
import cn.superdesk.uniorder.dto.param.accounting.qchjc.QchjcSupplierAccountingListRequest;
import cn.superdesk.uniorder.dto.param.invoice.common.InvoiceBankInfoQueryCriteria;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderForm;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderItem;
import cn.superdesk.uniorder.dto.param.thirdpart.qchjc.accounting.QchjcSupplierStorageParam;
import cn.superdesk.uniorder.dto.param.thirdpart.qchjc.invoice.QchjcSupplierInoviceApplyParam;
import cn.superdesk.uniorder.dto.vo.organisation.UnifiedSupplierVo;
import cn.superdesk.uniorder.dto.vo.thirdpart.qchjc.accounting.QchjcAccountingUnifiedSupplierVo;
import cn.superdesk.uniorder.dubbo.facade.accounting.supplier.DubboAccountingUnifiedSupplierFieldAccountingStatusService;
import cn.superdesk.uniorder.dubbo.facade.invoice.supplier.DubboInvoiceApplySupplierFieldMakeInvoiceStatusService;
import cn.superdesk.uniorder.dubbo.facade.invoice.supplier.DubboInvoiceApplySupplierService;
import cn.superdesk.uniorder.dubbo.facade.thirdpart.qchjc.accounting.DubboQchjcSupplierStatementService;
import cn.superdesk.uniorder.service.accounting.unified.supplier.AccountingUnifiedSupplierService;
import cn.superdesk.uniorder.service.accounting.unified.supplier.AccountingUnifiedSupplierServiceOpCreateDimGoods;
import cn.superdesk.uniorder.service.invoice.common.InvoiceBankInfoService;
import cn.superdesk.uniorder.service.thirdpart.qchjc.account.QchjcSupplierJdOrderService;
import cn.superdesk.uniorder.service.thirdpart.qchjc.account.QchjcSupplierStatementService;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author xc
 * @description
 * @date 2022/4/1 18:34
 */
@Service(version = "1.0.0", retries = -1, timeout = 10000)
@Slf4j
public class DubboQchjcSupplierStatementServiceImpl implements DubboQchjcSupplierStatementService {
    @Reference(version = "1.0.0", timeout = 30000, retries = -1)
    private DubboInvoiceApplySupplierService dubboInvoiceApplySupplierService;
    @Reference(version = "1.0.0", timeout = 30000, retries = -1)
    private DubboAccountingUnifiedSupplierFieldAccountingStatusService dubboAccountingUnifiedSupplierFieldAccountingStatusService;
    @Autowired
    private QchjcSupplierStatementService qchjcSupplierStatementService;
    @Autowired
    private QchjcSupplierJdOrderService qchjcSupplierJdOrderService;

    @Autowired
    private AccountingUnifiedSupplierServiceOpCreateDimGoods accountingUnifiedSupplierServiceOpCreateDimGoods;
    @Autowired
    private InvoiceBankInfoService invoiceBankInfoService;
    @Autowired
    private AccountingUnifiedSupplierService accountingUnifiedSupplierService;
    @Autowired
    private InvoiceApplySupplierMapper invoiceApplySupplierMapper;

    @Reference(version = "1.0.0", timeout = 300000, retries = -1)
    private DubboInvoiceApplySupplierFieldMakeInvoiceStatusService dubboInvoiceApplySupplierFieldMakeInvoiceStatusService;

    private final ExecutorService executorService = Executors.newFixedThreadPool(1);

    /**
     * 集采-接收供应商对账单
     *
     * @return
     */
    @Override
    public void receive(String data) {
        qchjcSupplierStatementService.receive(data);
    }

    /**
     * 集采-获取待入库状态供应商对账单集合
     *
     * @return
     */
    @Override
    public QchjcAccountingUnifiedSupplierVo getTodoList(Long id) {
        return qchjcSupplierStatementService.getTodoList(id);
    }

    @Override
    public void updateByPrimaryKeySelective(QchjcAccountingUnifiedSupplierEntity qchjcAccountingUnifiedSupplierEntity) {
        qchjcSupplierStatementService.updateByPrimaryKeySelective(qchjcAccountingUnifiedSupplierEntity);
    }

    @Override
    public QchjcAccountingUnifiedSupplierEntity selectByPrimaryKey(Long id) {
        return qchjcSupplierStatementService.selectByPrimaryKey(id);
    }

    @Override
    public void syncStatus(String toJSONString) throws OpenApiException {
        qchjcSupplierStatementService.syncStatus(toJSONString);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doSave(Long id) {

        QchjcAccountingUnifiedSupplierEntity qchjcAccountingUnifiedSupplierEntity = qchjcSupplierStatementService.selectByPrimaryKey(id);
        try {
            //service层保存商品明细，返回创建对账单参数
            QchjcSupplierStorageParam param = qchjcSupplierStatementService.doSaveDetail(id);
            if (param != null) {
                //如果已经存在对账单，且是已取消状态，则删掉这条记录
                AccountingUnifiedSupplier byAccountingOrderSn = accountingUnifiedSupplierService.findByAccountingOrderSn(param.getFormParam().getJcAccountingOrderSn());
                if (byAccountingOrderSn != null) {
                    if (byAccountingOrderSn.getAccountingStatus().equals(AccountingOrderSupplierAccountingStatusEnum.已取消.getKey())) {
                        accountingUnifiedSupplierService.deleteObj(byAccountingOrderSn.getId());
                    } else {
                        throw new OpenApiException(500, "该对账单已存在，请勿重复入库");
                    }
                }
                //创建对账单
                R<AccountingUnifiedSupplier> accountingUnifiedSupplierR = accountingUnifiedSupplierServiceOpCreateDimGoods.opCreateAccountingDimGoodsPreProcess(param.getFormParam(), param.getLoginUser());
//                List<AccountingUnifiedSupplierXGoods> processAccountingUnifiedSupplierXGoodsList = new ArrayList<>();
//                for (AccountingUnifiedSupplierXGoodsParam accountingUnifiedSupplierXGoodsParam : param.getXGoodsList()) {
//                    AccountingUnifiedSupplierXGoods xGoods = new AccountingUnifiedSupplierXGoods();
//                    xGoods.setDimCreateBy(AccountingOrderDimCreateByEnum.商品.getKey());
//                    xGoods.setAccountingOrderId(accountingUnifiedSupplierR.getData().getId());
//                    xGoods.setAccountingOrderSn(accountingUnifiedSupplierR.getData().getAccountingOrderSn());
//                    xGoods.setUnifiedOrderId(accountingUnifiedSupplierXGoodsParam.getUnifiedOrderId());
//                    xGoods.setOrderSn(accountingUnifiedSupplierXGoodsParam.getOrderSn());
//                    xGoods.setUnifiedOrderGoodsId(accountingUnifiedSupplierXGoodsParam.getUnifiedOrderGoodsId());
//                    xGoods.setCreateTime(DateUtil.date());
//                    xGoods.setCreateUserId(1L);
//                    xGoods.setUpdateUserId(1L);
//                    xGoods.setUpdateTime(DateUtil.date());
//                    processAccountingUnifiedSupplierXGoodsList.add(xGoods);
//                }
//                int ret = accountingUnifiedSupplierXGoodsService.insertBatch(processAccountingUnifiedSupplierXGoodsList);

                //提交对账
                dubboAccountingUnifiedSupplierFieldAccountingStatusService.opConfirm(accountingUnifiedSupplierR.getData(), param.getLoginUser());

                //发票单入库
                putSupplierInvoiceApplyIntoStorage(qchjcAccountingUnifiedSupplierEntity, accountingUnifiedSupplierR, param.getLoginUser());
                //入库全部成功，更新对账单中间表的入库状态
                qchjcAccountingUnifiedSupplierEntity.setStorageStatus(QchjcStorageStatusEnum.SUCCESS.getStatus());
                qchjcAccountingUnifiedSupplierEntity.setStorageReason("入库成功");
                qchjcAccountingUnifiedSupplierEntity.setStorageTime(DateUtil.date());
                qchjcAccountingUnifiedSupplierEntity.setUpdateUserId("system");
                qchjcAccountingUnifiedSupplierEntity.setUpdateTime(DateUtil.date());
                qchjcAccountingUnifiedSupplierEntity.setUpdateUserName("系统入库");
                qchjcSupplierStatementService.updateByPrimaryKeySelective(qchjcAccountingUnifiedSupplierEntity);
            }
        } catch (DuplicateKeyException e) {
            log.error("供应商对账单入库异常 ============== vo: {}, msg: {}", JSON.toJSONString(qchjcAccountingUnifiedSupplierEntity), e.getMessage());
            String prompt = handleDuplicateKeyException(e);
            executorService.execute(() -> qchjcSupplierStatementService.recordFailLog(qchjcAccountingUnifiedSupplierEntity, prompt));
            throw new RuntimeException(e);
        } catch (Exception e) {
            log.error("供应商对账单入库异常 ============== vo: {}, msg: {}", JSON.toJSONString(qchjcAccountingUnifiedSupplierEntity), e.getMessage());
            executorService.execute(() -> qchjcSupplierStatementService.recordFailLog(qchjcAccountingUnifiedSupplierEntity, JSON.toJSONString(e)));
            throw new RuntimeException(e);
        }

    }

    /**
     * 处理入库异常，返回友好提示：DuplicateKeyException
     *
     * @param e
     * @return
     */
    private String handleDuplicateKeyException(DuplicateKeyException e) {
        String localizedMessage = e.getCause().getLocalizedMessage();
        //"Duplicate entry 'GYS21001715' for key 'sn'"
        String trim = localizedMessage.split("Duplicate entry")[1].split("for key")[0].trim();
        return "集采对账单明细参数：" + trim + "重复，请检查";
    }

    void putSupplierInvoiceApplyIntoStorage(QchjcAccountingUnifiedSupplierEntity qchjcAccountingUnifiedSupplierEntity, R<AccountingUnifiedSupplier> accountingUnifiedSupplierR, LoginSysUser loginUser) {
        //查询对账单对应的发票单
        List<QchjcInvoiceApplySupplierEntity> qchjcInvoiceApplySupplierEntities = qchjcSupplierStatementService.selectSupplierInvoiceByAccountingOrderSn(qchjcAccountingUnifiedSupplierEntity.getAccountingOrderSn());
        /**
         * step_3 调用一键分票,发票单入库
         */
        AccountingUnifiedSupplier accountingUnifiedSupplier = accountingUnifiedSupplierR.getData();
        List<InvoiceBankInfo> query = invoiceBankInfoService.query(new InvoiceBankInfoQueryCriteria(), loginUser);
        InvoiceBankInfo invoiceBankInfo = query.get(0);//获取默认或id最小的抬头信息

        //开票申请容器，全部入库后调用确认开票接口
        List<InvoiceApplySupplier> invoiceApplySupplierList = new ArrayList<>();
        for (QchjcInvoiceApplySupplierEntity qchjcInvoiceApplySupplierEntity : qchjcInvoiceApplySupplierEntities) {
            QchjcSupplierInoviceApplyParam param = qchjcSupplierStatementService.assembleSupplierInvoiceApplyParam(qchjcInvoiceApplySupplierEntity, accountingUnifiedSupplier, invoiceBankInfo, qchjcAccountingUnifiedSupplierEntity);
            //调用一键分票
            InvoiceApplySupplier invoiceApplySupplier = dubboInvoiceApplySupplierService.opInvoiceApply(param.getForm(), param.getInvoiceLoginUser());
            invoiceApplySupplierList.add(invoiceApplySupplier);
            //保存开票申请编号等信息
            qchjcInvoiceApplySupplierEntity.setInvoiceApplySn(invoiceApplySupplier.getInvoiceApplySn());//开票申请编号
            qchjcInvoiceApplySupplierEntity.setUnifiedApplyAmount(invoiceApplySupplier.getInvoiceApplyAmount());//结算中心开票申请金额
            qchjcInvoiceApplySupplierEntity.setUnifiedOrderCount(invoiceApplySupplier.getGoodsQuantity());//结算中心开票申请订单数量(实际是商品明细数量)
            qchjcInvoiceApplySupplierEntity.setUnifiedRebateAmount(qchjcInvoiceApplySupplierEntity.getRebateAmount());//结算中心开票申请返点金额,实际和集采传过来的一致
            qchjcSupplierStatementService.saveSupplierInvoiceApplyByPrimaryKeySelective(qchjcInvoiceApplySupplierEntity);
        }
        //确认开票表单参数
        InvoiceApplySupplierOpCommonDimAccountingOrderForm form = new InvoiceApplySupplierOpCommonDimAccountingOrderForm();
        form.setAccountingOrderSn(accountingUnifiedSupplier.getAccountingOrderSn());
        form.setAccountingOrderId(accountingUnifiedSupplier.getId());
        form.setOutSaleId(accountingUnifiedSupplier.getSaleId());
        form.setOutSaleName(accountingUnifiedSupplier.getSaleName());
        List<InvoiceApplySupplierOpCommonDimAccountingOrderItem> itemList = invoiceApplySupplierList.stream().map(invoiceApplySupplier -> {
            InvoiceApplySupplierOpCommonDimAccountingOrderItem item = new InvoiceApplySupplierOpCommonDimAccountingOrderItem();
            item.setInvoiceApplyId(invoiceApplySupplier.getId());
            item.setInvoiceApplySn(invoiceApplySupplier.getInvoiceApplySn());
            return item;
        }).collect(Collectors.toList());
        form.setInvoiceApplySupplierList(itemList);
        //调用确认开票接口
        dubboInvoiceApplySupplierFieldMakeInvoiceStatusService.opComplete(invoiceApplySupplierList, form, loginUser);

        //把集采发票号写到结算中心开票申请表中
        List<QchjcInvoiceApplySupplierEntity> res = qchjcSupplierStatementService.selectSupplierInvoiceByAccountingOrderSn(qchjcAccountingUnifiedSupplierEntity.getAccountingOrderSn());
        for (QchjcInvoiceApplySupplierEntity qchjcInvoiceApplySupplierEntity : res) {
            String invoiceNumber = qchjcInvoiceApplySupplierEntity.getInvoiceNumber();
            if (StringUtils.isNotBlank(invoiceNumber)) {
                InvoiceApplySupplierExample invoiceApplySupplierExample = new InvoiceApplySupplierExample();
                invoiceApplySupplierExample.createCriteria().andInvoiceApplySnEqualTo(qchjcInvoiceApplySupplierEntity.getInvoiceApplySn());
                List<InvoiceApplySupplier> resList = invoiceApplySupplierMapper.selectByExample(invoiceApplySupplierExample);
                if (CollectionUtils.isNotEmpty(resList)) {
                    InvoiceApplySupplier invoiceApplySupplier = resList.get(0);
                    invoiceApplySupplier.setInvoiceNumber(invoiceNumber);
                    invoiceApplySupplierMapper.updateByPrimaryKeySelective(invoiceApplySupplier);
                }
            }
        }

    }

    @Override
    public R<List<QchjcAccountingUnifiedSupplierVo>> queryQchjcSupplierStatementList(QchjcSupplierAccountingListRequest request) {
        return qchjcSupplierStatementService.queryQchjcSupplierStatementList(request);
    }

    @Override
    public R<String> remark(Long id, String remark, String token) {

        return qchjcSupplierStatementService.remark(id, remark, token);
    }

    @Override
    public R<QchjcAccountingUnifiedSupplierVo> getQchjcSupplierStatement(Long id) {

        return qchjcSupplierStatementService.getQchjcSupplierStatementById(id);
    }

    @Override
    public List<Long> getTodoIdList() {
        return qchjcSupplierStatementService.getTodoIdList();

    }

    @Override
    public R<List<UnifiedSupplierVo>> getSupplierList() {
        return qchjcSupplierStatementService.getSupplierList();
    }

    @Override
    public void receiveJdOrder(String toJSONString) throws OpenApiException {
        qchjcSupplierJdOrderService.receiveJdOrder(toJSONString);
    }

    @Override
    public void fix(Integer limit, String supplierAccountingOrderSn) {
        qchjcSupplierJdOrderService.fix(limit,supplierAccountingOrderSn);
    }
}
