package com.jianshui.invoice.utils;

import com.alibaba.fastjson.JSONObject;
import com.jianshui.common.core.domain.entity.Companyservice;
import com.jianshui.common.core.domain.entity.CompanyserviceDetail;
import com.jianshui.common.enums.ErrorCode;
import com.jianshui.common.exception.jianshui.JianshuiBillInfoCalucateException;
import com.jianshui.common.exception.jianshui.JianshuiParamErrorException;
import com.jianshui.common.exception.jianshui.JianshuiServiceException;
import com.jianshui.common.utils.StringUtils;
import com.jianshui.common.utils.ValidateUtils;
import com.jianshui.common.utils.bean.BeanUtils;
import com.jianshui.common.utils.spring.SpringUtils;
import com.jianshui.common.utils.uuid.IdUtils;
import com.jianshui.invoice.domain.BillDetail;
import com.jianshui.invoice.domain.BillInfo;
import com.jianshui.invoice.domain.dto.validator.AddBillinfoValidateDTO;
import com.jianshui.invoice.domain.dto.validator.AddDetailValidateDTO;
import com.jianshui.invoice.mapper.BillInfoMapper;
import com.jianshui.system.service.ISysConfigService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description 发票订单工具类
 * @Author 巩权林
 * @Date 2022-03-21 16:58
 **/
public class BillInfoUtils {


    /**
     * billInfo预处理
     *
     * @param billInfo
     * @param companyservice
     * @return
     */
    public static BillInfo processBillInfo(BillInfo billInfo, Companyservice companyservice) throws InstantiationException, IllegalAccessException {
        BillInfoMapper billInfoMapper = SpringUtils.getBean(BillInfoMapper.class);

        // 预处理billInfo
        billInfo = BillInfoUtils.preprocessing(billInfo, companyservice);

        // 查询订单是否已经存在
        String orderno = billInfo.getOutTradeOrderno();
        if (StringUtils.isEmpty(orderno)) {
            throw new JianshuiParamErrorException(ErrorCode.ORDER_FPQQLSH_NOT_EMPTY, companyservice, "invoice");
        }

        BillInfo queryResult = billInfoMapper.selectBySystemOrderNo(companyservice.getCompanyid(), orderno);
        if (queryResult != null) {
            throw new JianshuiParamErrorException(ErrorCode.ORDER_EXISTS, companyservice, "invoice");
        }

        // 校验
        BillInfoUtils.validate(AddBillinfoValidateDTO.class, billInfo, companyservice, "invoice");

        // 预处理detail
        billInfo = BillInfoUtils.preprocessBillDetail(billInfo, companyservice);
        List<BillDetail> detailList = billInfo.getBillDetailList();

        // 如果数量大于8个，就是清单
        if (detailList.size() > 8) {
            billInfo.setQdbz("1");
        } else {
            billInfo.setQdbz("0");
        }

        BigDecimal taxamt = new BigDecimal(0);
        BigDecimal taxfreeamt = new BigDecimal(0);
        BigDecimal tax = new BigDecimal(0);

        // 开始处理含税金额、不含税金额、税额
        for (int i = 0; i < detailList.size(); i++) {
            BillDetail detail = detailList.get(i);
            if (detail.getTaxamt() == null) {
                String errorMsg = StringUtils.format("发票第{}条明细，含税金额为空，无法开票", i);
                throw new JianshuiBillInfoCalucateException(errorMsg, companyservice, JSONObject.toJSONString(billInfo));
            }

            if (detail.getTaxfreeamt() == null) {
                String errorMsg = StringUtils.format("发票第{}条明细，不含税金额为空，无法开票", i);
                throw new JianshuiBillInfoCalucateException(errorMsg, companyservice, JSONObject.toJSONString(billInfo));
            }

            if (detail.getTax() == null) {
                String errorMsg = StringUtils.format("发票第{}条明细，税额为空，无法开票", i);
                throw new JianshuiBillInfoCalucateException(errorMsg, companyservice, JSONObject.toJSONString(billInfo));
            }

            detailList.get(i).setIndex((long) (i + 1));
            taxamt = taxamt.add(detail.getTaxamt());
            tax = tax.add(detail.getTax());
            taxfreeamt = taxfreeamt.add(detail.getTaxfreeamt());
        }
        billInfo.setTax(tax);
        billInfo.setTaxamt(taxamt);
        billInfo.setTaxfreeamt(taxfreeamt);
        billInfo.setCompanyId(companyservice.getCompanyid());

        // 保存billInfo
        if (billInfoMapper.insertBillInfo(billInfo) <= 0) {
            throw new JianshuiParamErrorException("保存单据信息失败，请联系管理员！", companyservice, "invoice");
        }

        List<BillDetail> details = billInfo.getBillDetailList();
        for (BillDetail detail : details) {
            detail.setBillInfoId(billInfo.getId());
        }

        try {
            billInfoMapper.batchBillDetail(detailList);
        } catch (Exception e) {
            billInfoMapper.deleteBillInfoById(billInfo.getId());
            throw e;
        }

        return billInfo;
    }


    /**
     * 验证billInfo
     *
     * @param validateBillInfoClazz 要校验的目标bill类型
     * @param billInfo              原始billinfo
     * @param <T>
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> void validate(Class<T> validateBillInfoClazz, BillInfo billInfo, Companyservice companyservice, String serviceKey) throws IllegalAccessException, InstantiationException {
        T validateBillInfo = validateBillInfoClazz.newInstance();
        BeanUtils.copyProperties(billInfo, validateBillInfo);
        ValidateUtils.validate(validateBillInfo, companyservice, serviceKey);
    }

    /**
     * 预处理billInfo
     *
     * @param billInfo
     * @return
     */
    public static BillInfo preprocessing(BillInfo billInfo, Companyservice companyservice) throws InstantiationException, IllegalAccessException {
        // 生成系统单号
        billInfo.setSystemOrderno(IdUtils.randomSystemOrderno());

        // 设置发票流水号
        billInfo.setFpqqlsh(billInfo.getSystemOrderno());

        // 获取分机号和终端号，如果都不存在，则去取系统默认的
        if (StringUtils.isEmpty(billInfo.getFjh()) && StringUtils.isEmpty(billInfo.getTerminalNumber())) {
            List<CompanyserviceDetail> detailList = companyservice.getCompanyserviceDetailList();
            if (detailList != null) {
                CompanyserviceDetail detail = null;
                for (CompanyserviceDetail t : detailList) {
                    if (t.getIsDefault() == 1) {
                        detail = t;
                        break;
                    }
                }
                // if (detail == null) {
                //     throw new JianshuiServiceException("销方信息终端号没配置，请联系管理员！");
                // }

                if (detail != null) {
                    // 如果分机号为空
                    if (StringUtils.isEmpty(billInfo.getFjh())) {
                        billInfo.setFjh(detail.getFjh());
                    }

                    // 如果终端号为空
                    if (StringUtils.isEmpty(billInfo.getTerminalNumber())) {
                        billInfo.setTerminalNumber(detail.getTerminalNumber());
                    }
                }
            }
        }


        // 配置销方信息
        if (StringUtils.isEmpty(billInfo.getSellerTaxnum())) {
            billInfo.setSellerTaxnum(companyservice.getSellertax());
        }
        if (StringUtils.isEmpty(billInfo.getSellerName())) {
            billInfo.setSellerName(companyservice.getSellername());
        }
        if (StringUtils.isEmpty(billInfo.getSellerAddress())) {
            billInfo.setSellerAddress(companyservice.getSelleraddress());
        }
        if (StringUtils.isEmpty(billInfo.getSellerTelephone())) {
            billInfo.setSellerTelephone(companyservice.getSellerphone());
        }
        if (StringUtils.isEmpty(billInfo.getSellerBank())) {
            billInfo.setSellerBank(companyservice.getSellerbank());
        }
        if (StringUtils.isEmpty(billInfo.getSellerAccount())) {
            billInfo.setSellerAccount(companyservice.getSelleraccount());
        }

        // 开票日期
        Date kprq = billInfo.getInvoicedTime();
        if (kprq == null) {
            billInfo.setInvoicedTime(new Date());
        }

        return billInfo;
    }

    /**
     * 预处理billDetail
     *
     * @param billInfo
     * @param companyservice
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static BillInfo preprocessBillDetail(BillInfo billInfo, Companyservice companyservice) throws InstantiationException, IllegalAccessException {

        // if (billInfo.getId() == null) {
        //     throw new JianshuiParamErrorException("发票id不能为空！");
        // }

        // 处理发票详情
        if (billInfo.getBillDetailList().size() <= 0) {
            throw new JianshuiParamErrorException("发票详情不能为空！", companyservice, "invoice");
        }

        List<BillDetail> detailList = new ArrayList<>();
        List<BillDetail> originDetail = billInfo.getBillDetailList();

        for (int i = 0; i < originDetail.size(); i++) {
            BillDetail tempDetail = originDetail.get(i);
            // tempDetail.setBillInfoId(billInfo.getId());
            try {
                tempDetail = BillDetailUtils.preprocessing(tempDetail, companyservice);
                BillDetailUtils.validate(AddDetailValidateDTO.class, tempDetail, companyservice, "invoice");
            } catch (JianshuiParamErrorException e) {
                throw new JianshuiParamErrorException("第" + (i + 1 )+ "行明细：" + e.getMessage(), companyservice, "invoice");
            }

            detailList.add(tempDetail);
        }

        billInfo.setBillDetailList(detailList);
        return billInfo;
    }
}
