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.dao.entity.accounting.score.customer.AccountingScoreCustomer;
import cn.superdesk.uniorder.dao.entity.thirdpart.qchjc.accounting.QchjcAccountingScoreCustomerEntity;
import cn.superdesk.uniorder.dto.param.accounting.qchjc.QchjcCustomerAccountingListRequest;
import cn.superdesk.uniorder.dto.param.thirdpart.qchjc.accounting.QchjcCustomerStorageParam;
import cn.superdesk.uniorder.dto.vo._function.select.SelectOptionVirt;
import cn.superdesk.uniorder.dto.vo.thirdpart.qchjc.accounting.QchjcCustomerStatementVo;
import cn.superdesk.uniorder.dubbo.facade.accounting.customer.DubboAccountingScoreCustomerService;
import cn.superdesk.uniorder.dubbo.facade.thirdpart.qchjc.accounting.DubboQchjcCustomerStatementService;
import cn.superdesk.uniorder.service.thirdpart.qchjc.account.QchjcCustomerStatementService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author xc
 * @description
 * @date 2022/4/1 10:25
 */
@Service(version = "1.0.0", retries = -1, timeout = 10000)
@Slf4j
public class DubboQchjcCustomerStatementServiceImpl implements DubboQchjcCustomerStatementService {

    @Autowired
    private QchjcCustomerStatementService qchjcCustomerStatementService;

    @Reference(version = "1.0.0", timeout = 30000, retries = -1)
    private DubboAccountingScoreCustomerService dubboAccountingScoreCustomerService;

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

    /**
     * 接收采购单位对账单
     *
     * @param data
     */
    @Override
    public void receive(String data) {
        qchjcCustomerStatementService.receive(data);
    }

    /**
     * 查询所有待入库状态对账单
     *
     * @return
     */
    @Override
    public QchjcCustomerStatementVo getTodoList(Long id) {
        return qchjcCustomerStatementService.getTodoList(id);
    }

    @Override
    public void updateByPrimaryKeySelective(QchjcAccountingScoreCustomerEntity qchjcAccountingScoreCustomerEntity) {
        qchjcCustomerStatementService.updateByPrimaryKeySelective(qchjcAccountingScoreCustomerEntity);
    }

    @Override
    public QchjcAccountingScoreCustomerEntity selectByAccountingOrderSn(String accountingOrderSn) {
        return qchjcCustomerStatementService.selectByAccountingOrderSn(accountingOrderSn);

    }

    @Override
    public QchjcAccountingScoreCustomerEntity selectByPrimaryKey(Long id) {
        return qchjcCustomerStatementService.selectByPrimaryKey(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doSave(Long id) {
        QchjcAccountingScoreCustomerEntity qchjcAccountingScoreCustomerEntity = qchjcCustomerStatementService.selectByPrimaryKey(id);
        try {
            //service层保存账单明细返回创建对账单的参数
            QchjcCustomerStorageParam param = qchjcCustomerStatementService.doSaveDetail(id);
            if (param != null) {
                //如果已经存在对账单，且是已取消状态，则删掉这条记录
                AccountingScoreCustomer byAccountingOrderSn = dubboAccountingScoreCustomerService.findByAccountingOrderSn(param.getAccountingOrderScoreCustomerCreateParam().getJcAccountingOrderSn());
                if (byAccountingOrderSn != null) {
                    if (byAccountingOrderSn.getAccountingStatus().equals(AccountingOrderSupplierAccountingStatusEnum.已取消.getKey())) {
                        dubboAccountingScoreCustomerService.deleteObj(byAccountingOrderSn.getId());
                    }else {
                        throw new OpenApiException(500, "该对账单已存在，请勿重复入库");
                    }
                }
                //创建对账单后，把统一订单的id更新到集采中间表
                AccountingScoreCustomer scoreAccountingCustomer = dubboAccountingScoreCustomerService
                        .createScoreAccountingCustomer(param.getResultListCredit(),
                                param.getAccountingOrderScoreCustomerCreateParam(),
                                param.getLoginSysUser()
                        );
                //确认对账
                dubboAccountingScoreCustomerService.opConfirmAccounting(scoreAccountingCustomer.getId(), param.getLoginSysUser());

                qchjcAccountingScoreCustomerEntity.setUnifiedId(scoreAccountingCustomer.getId());
                qchjcCustomerStatementService.updateByPrimaryKeySelective(qchjcAccountingScoreCustomerEntity);


                //入库发票单
                qchjcCustomerStatementService.putInvoiceApplyIntoStorage(id, scoreAccountingCustomer);

                /**
                 * 入库成功后中间表更新入库状态
                 */
                qchjcAccountingScoreCustomerEntity.setStorageStatus(QchjcStorageStatusEnum.SUCCESS.getStatus());
                qchjcAccountingScoreCustomerEntity.setStorageTime(DateUtil.date());
                qchjcAccountingScoreCustomerEntity.setStorageReason("入库成功");
                qchjcAccountingScoreCustomerEntity.setUpdateUserId("system");
                qchjcAccountingScoreCustomerEntity.setUpdateTime(DateUtil.date());
                qchjcAccountingScoreCustomerEntity.setUpdateUserName("系统入库");
                qchjcCustomerStatementService.updateByPrimaryKeySelective(qchjcAccountingScoreCustomerEntity);
            }
        }catch (DuplicateKeyException e){
            log.error("采购单位对账单入库异常 ============== vo: {}, msg: {}", JSON.toJSONString(qchjcAccountingScoreCustomerEntity.getAccountingOrderSn()), e.getMessage());
            String prompt = handleDuplicateKeyException(e);
            executorService.execute(() -> qchjcCustomerStatementService.recordFailLog(qchjcAccountingScoreCustomerEntity, prompt));
            throw new RuntimeException(e);
        } catch (Exception e) {
            log.error("采购单位对账单入库异常 ============== vo: {}, msg: {}", JSON.toJSONString(qchjcAccountingScoreCustomerEntity.getAccountingOrderSn()), e.getMessage());
            executorService.execute(() -> qchjcCustomerStatementService.recordFailLog(qchjcAccountingScoreCustomerEntity, 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 + "重复，请检查";
    }

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

    @Override
    public R<List<QchjcCustomerStatementVo>> queryQchjcCustomerStatementList(QchjcCustomerAccountingListRequest request) {
        return qchjcCustomerStatementService.queryQchjcCustomerStatementList(request);
    }

    @Override
    public R<String> updateRemark(Long id, String remark, String token) {
        return qchjcCustomerStatementService.updateRemark(id, remark, token);
    }

    @Override
    public R<QchjcCustomerStatementVo> queryQchjcCustomerStatementVoById(Long id) {

        return qchjcCustomerStatementService.queryQchjcCustomerStatementVoById(id);
    }

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

    @Override
    public R<List<SelectOptionVirt>> queryCustomerList() {
        return qchjcCustomerStatementService.queryCustomerList();
    }
}
