package com.dxhy.erp.service.impl;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dxhy.api.model.config.sys.SysEnterpriseConfigDto;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.ReturnCodeEnum;
import com.dxhy.common.util.pojo.Authorize;
import com.dxhy.common.util.pojo.GlobalInfo;
import com.dxhy.erp.dao.SysEnterpriseConfigErpDao;
import com.dxhy.erp.dao.TDxRecordInvoiceOutDao;
import com.dxhy.erp.entity.TDxRecordInvoiceOut;
import com.dxhy.erp.model.GatherData;
import com.dxhy.erp.model.InvoiceOutReq;
import com.dxhy.erp.model.InvoiceOutResp;
import com.dxhy.erp.model.ReturnStateInfo;
import com.dxhy.erp.model.auth.InterfaceCode;
import com.dxhy.erp.service.TDxRecordInvoiceOutService;
import com.dxhy.erp.utils.CheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Gy Chen
 * @date 2021/3/24
 */
@Service
@Slf4j
public class TDxRecordInvoiceOutServiceImpl extends ServiceImpl<TDxRecordInvoiceOutDao, TDxRecordInvoiceOut>
    implements TDxRecordInvoiceOutService {
    private static final Map<String, Integer> HASH = new HashMap<>();
    @Autowired
    private SysEnterpriseConfigErpDao enterpriseConfigErpDao;
    @Value("${erp.outInvoiceNum:1000}")
    private String outInvoiceNum;

    @Override
    public String getOutInvoice(GlobalInfo globalInfo, Map<String, String> map, HttpServletRequest request,
        HttpServletResponse response, Authorize authorize) {
        ReturnStateInfo run = new ReturnStateInfo();
        String outNum = "";
        List<TDxRecordInvoiceOut> list;
        try {
            InvoiceOutReq data = JSONObject.parseObject(map.get("data"), InvoiceOutReq.class);
            run = getCheckState(data);
            if (run.getReturnCode() != null || run.getReturnMessage() != null) {
                InterfaceCode interfaceCode = new InterfaceCode();
                interfaceCode.setGlobalInfo(globalInfo);
                interfaceCode.setReturnStateInfo(run);
                return JSON.toJSONString(interfaceCode);
            }
            DynamicContextHolder.push(DbConstant.BASICS_READ);
            SysEnterpriseConfigDto deptEntity = enterpriseConfigErpDao.getOrg(data.getBuyerTaxNo());
            String dbName;
            if (deptEntity != null && deptEntity.getDbName() != null) {
                dbName = deptEntity.getDbName();
            } else {
                ReturnStateInfo runInfo = new ReturnStateInfo();
                runInfo.setReturnCode(ReturnCodeEnum.JTSHBF.getFhzDm());
                runInfo.setReturnMessage(ReturnCodeEnum.JTSHBF.getFhzMc(ReturnCodeEnum.JTSHBF.getIndex()));
                InterfaceCode interfaceCode = new InterfaceCode();
                interfaceCode.setGlobalInfo(globalInfo);
                interfaceCode.setReturnStateInfo(runInfo);
                return JSON.toJSONString(interfaceCode);
            }
            Integer total;
            DynamicContextHolder.push(dbName + DbConstant.BUSINESS_READ);
            try {
                total = HASH.get(data.getBatchNo());
                if (StringUtils.isNotBlank(data.getRequestRow())) {
                    outNum = data.getRequestRow();
                } else {
                    outNum = outInvoiceNum;
                }
                if (total == null || total == 0) {

                    total = this.baseMapper.countOutInvoice(data.getBuyerTaxNo(), data.getOutTaxPeriod(),
                        data.getOutReason());
                    HASH.put(data.getBatchNo(), total);
                }
            } catch (Exception e) {
                total =
                    this.baseMapper.countOutInvoice(data.getBuyerTaxNo(), data.getOutTaxPeriod(), data.getOutReason());
                HASH.put(data.getBatchNo(), total);
            }

            if ("1".equals(data.getStatus())) {
                int startRow = data.getStartRow();
                List<InvoiceOutResp> infos = new ArrayList<>();
                boolean continueQuery = true;

                while (continueQuery && infos.size() < Integer.parseInt(outNum) && infos.size() < total
                    && startRow <= total) {
                    list = selectByState(data.getBuyerTaxNo(), data.getOutTaxPeriod(), data.getOutReason(), startRow,
                        1000);
                    startRow += 1000;
                    for (TDxRecordInvoiceOut ss : list) {
                        InvoiceOutResp stateInfo = this.getStateInfo(ss);
                        infos.add(stateInfo);
                        if (infos.size() >= Integer.parseInt(outNum)) {
                            continueQuery = false;
                            break;
                        }
                    }

                }
                GatherData status = new GatherData();
                status.setContentRows(infos.size());
                status.setStartRow(data.getStartRow());
                status.setTotalRows(total);
                status.setInvoices(infos);
                String result = JSON.toJSONString(status);
                run.setReturnCode(ReturnCodeEnum.CLCG.getFhzDm());
                run.setReturnMessage(ReturnCodeEnum.CLCG.getFhzMc(ReturnCodeEnum.CLCG.getIndex()));
                InterfaceCode interfaceCode = new InterfaceCode();
                interfaceCode.setReturnStateInfo(run);
                interfaceCode.setGlobalInfo(globalInfo);
                interfaceCode.setData(Base64.encode(result));
                return JSON.toJSONString(interfaceCode);
            } else if ("0".equals(data.getStatus())) {
                HASH.remove(data.getBatchNo());
                run.setReturnCode(ReturnCodeEnum.CLCG.getFhzDm());
                run.setReturnMessage(ReturnCodeEnum.CLCG.getFhzMc(ReturnCodeEnum.CLCG.getIndex()));
                InterfaceCode interfaceCode = new InterfaceCode();
                interfaceCode.setReturnStateInfo(run);
                interfaceCode.setGlobalInfo(globalInfo);
                return JSON.toJSONString(interfaceCode);

            } else {
                run.setReturnCode(ReturnCodeEnum.CLSB.getFhzDm());
                run.setReturnMessage(ReturnCodeEnum.CLSB.getFhzMc(ReturnCodeEnum.CLSB.getIndex()));
                InterfaceCode interfaceCode = new InterfaceCode();
                interfaceCode.setReturnStateInfo(run);
                interfaceCode.setGlobalInfo(globalInfo);
                return JSON.toJSONString(interfaceCode);
            }
        } catch (Exception e) {
           log.info("业务处理异常：{}", e);
            run.setReturnCode(ReturnCodeEnum.QTYC.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.QTYC.getFhzMc(ReturnCodeEnum.QTYC.getIndex()));
            InterfaceCode interfaceCode = new InterfaceCode();

            try {
                interfaceCode.setReturnStateInfo(run);
                interfaceCode.setGlobalInfo(globalInfo);
            } catch (Exception ignored) {
            }
            return JSON.toJSONString(interfaceCode);
        }
    }

    public InvoiceOutResp getStateInfo(TDxRecordInvoiceOut out) {
        InvoiceOutResp resp = new InvoiceOutResp();
        if(StringUtils.isBlank(out.getInvoiceCode())){
            resp.setInvoiceCode("");
        }else {
            resp.setInvoiceCode(out.getInvoiceCode());
        }

        resp.setInvoiceNo(out.getInvoiceNo());
        try {
            resp.setOutDate(new SimpleDateFormat("yyyy-MM-dd").format(out.getOutDate()));
        } catch (Exception e) {
        }
        resp.setOutStatus(out.getOutStatus());
        resp.setOutInvoiceAmount(out.getOutInvoiceAmout().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        resp.setOutTaxAmount(out.getOutTaxAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        resp.setOutReason(out.getOutReason());
        resp.setOutRemark(out.getOutRemark());
        resp.setOutTaxPeriod(out.getOutBelongDate());
        return resp;
    }

    public List<TDxRecordInvoiceOut> selectByState(String buyerTaxNo, String outTaxPeriod, String outReason,
        Integer start, Integer num) {
        Map<String, Object> map = new HashMap<>(16);
        map.put("buyerTaxNo", buyerTaxNo);
        map.put("outTaxPeriod", outTaxPeriod);
        map.put("outReason", outReason);
        map.put("start", start - 1);
        map.put("num", num);
        return this.baseMapper.selectOutInvoice(map);
    }

    public ReturnStateInfo getCheckState(InvoiceOutReq data) {
        ReturnStateInfo run = new ReturnStateInfo();

        if (CheckUtils.isNullOrEmpty(data.getBuyerTaxNo()) || !(CheckUtils.stringLength(data.getBuyerTaxNo(), 15)
            || CheckUtils.stringLength(data.getBuyerTaxNo(), 18))) {
            run.setReturnCode(ReturnCodeEnum.SHBNWK.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.SHBNWK.getFhzMc(ReturnCodeEnum.SHBNWK.getIndex()));
        }
        if (CheckUtils.isNullOrEmpty(data.getBatchNo()) || (!CheckUtils.stringLength(data.getBatchNo(), 32))) {
            run.setReturnCode(ReturnCodeEnum.PCHBNWK.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.PCHBNWK.getFhzMc(ReturnCodeEnum.PCHBNWK.getIndex()));
        }
        if (CheckUtils.isNullOrEmpty(data.getOutTaxPeriod())) {
            run.setReturnCode(ReturnCodeEnum.ZCSQBKWK.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.ZCSQBKWK.getFhzMc(ReturnCodeEnum.ZCSQBKWK.getIndex()));
        }
        if (CheckUtils.isNullOrEmpty(data.getStatus()) || (!CheckUtils.stringLength(data.getStatus(), 1))) {
            run.setReturnCode(ReturnCodeEnum.ZTBZBNWK.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.ZTBZBNWK.getFhzMc(ReturnCodeEnum.ZTBZBNWK.getIndex()));
        }
        if (!CheckUtils.checkNum(data.getStartRow())) {
            run.setReturnCode(ReturnCodeEnum.KSHSCW.getFhzDm());
            run.setReturnMessage(ReturnCodeEnum.KSHSCW.getFhzMc(ReturnCodeEnum.KSHSCW.getIndex()));
        }
        return run;
    }
}
