package com.dxhy.extend.service.caution;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dxhy.api.model.config.Tax;
import com.dxhy.api.model.config.UserInfo;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.constant.DictConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.FpztEnum;
import com.dxhy.common.enums.RzztEnum;
import com.dxhy.common.service.DictdetaServcice;
import com.dxhy.common.service.TabulateRedisService;
import com.dxhy.common.service.impl.MpBaseServiceImpl;
import com.dxhy.common.util.AmountFormatUtil;
import com.dxhy.common.util.MathUtil;
import com.dxhy.common.util.UserInfoUtil;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.extend.dao.ExtTdxRecordInvoiceDao;
import com.dxhy.extend.entity.ExtTdxRecordInvoice;
import com.dxhy.extend.model.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author peipei.li
 * @date 2019-04-26 预警模块，抵账表操作service
 */
@SuppressWarnings("AlibabaUndefineMagicConstant")
@Service("cautionExpirationService")
@Slf4j
public class ExtCautionExpirationServiceImpl extends MpBaseServiceImpl<ExtTdxRecordInvoiceDao, ExtTdxRecordInvoice>
    implements IExtCautionExpirationService {
    @Resource
    private TabulateRedisService tabulateRedisService;
    @Resource
    private DictdetaServcice dictdetaServcice;

    /**
     * 逾期预警list
     *
     * @param reqVO
     *            查询条件
     * @param userInfo
     *            用户信息
     * @return 返回
     *
     */
    @Override
    public String listExpiration(ExtCautionExpirationReqVO reqVO, UserInfo userInfo) {
        DynamicContextHolder.push(reqVO.getUserInfo().getDbName() + DbConstant.BUSINESS_READ);
        String company = reqVO.getCompany();
        String menuId = reqVO.getMenuId();
        JSONObject json = tabulateRedisService.getTabulateMenu(company, menuId);

        Map<String, Object> pramsMap = new HashMap<>(16);
        List<String> gfshList = new ArrayList<>();
        // 购方税号
        if (StringUtils.isNotBlank(reqVO.getGfsh()) && !"99".equals(reqVO.getGfsh())) {
            gfshList.add(reqVO.getGfsh());
        } else {
            gfshList = UserInfoUtil.getGfshAll(reqVO.getUserInfo().getOrg());
        }
        pramsMap.put("gfsh", gfshList);
        pramsMap.put("month", reqVO.getMonth());
        pramsMap.put("company", reqVO.getCompany());
        // 分页
        PageHelper.startPage(reqVO.getCurr(), reqVO.getSize());
        List<ExtRecordInvoiceModel> pageList = super.baseMapper.queryInvoice(pramsMap);
        PageInfo<ExtRecordInvoiceModel> pageInfo = new PageInfo<>(pageList);

        // 查询结果封装为view
        List<ExtCautionExpirationRespVO> voList = new ArrayList<>();
        int index = 1;
        for (ExtRecordInvoiceModel record : pageList) {
            ExtCautionExpirationRespVO vo = convertToExpirationView(record, userInfo);
            // 序号计算 = (当前页-1)*每页条数+1
            vo.setXh((reqVO.getCurr() - 1) * reqVO.getSize() + index);
            index++;
            voList.add(vo);
        }

        // 设置记录总数
        json.put("total", pageInfo.getTotal());
        json.put("datalist", voList);

        // 合计金额 and 合计税额
        querySumForInvoice(json, pramsMap);

        return super.responseResult(json);
    }

    /**
     * 逾期预警列表 entity 转 vo
     *
     * @param record
     *            抵账信息
     * @param userInfo
     *            用户信息
     * @return 返回
     */
    private ExtCautionExpirationRespVO convertToExpirationView(ExtRecordInvoiceModel record, UserInfo userInfo) {
        ExtCautionExpirationRespVO vo = new ExtCautionExpirationRespVO();
        // uuid 作为主键
        vo.setId(record.getInvoiceCode() + record.getInvoiceNo());
        // 认证截止日期 = 开票日期+360天
        vo.setCertEndDate(record.getCutApproveDate());
        // 发票号码
        vo.setInvoiceNo(record.getInvoiceNo());
        // 发票代码
        vo.setInvoiceCode(record.getInvoiceCode());
        // 开票日期
        vo.setInvoiceDate(record.getInvoiceDate());
        // 购方名称
        vo.setBuyerName(record.getGfName());
        // 销方名称
        vo.setSellerName(record.getXfName());
        // 未税金额 = 金额
        vo.setNoTaxAmount(AmountFormatUtil.fmtMicrometer(MathUtil.round(record.getInvoiceAmount())));
        // 税额
        vo.setTaxAmount(AmountFormatUtil.fmtMicrometer(MathUtil.round(record.getTaxAmount())));
        // 发票类型
        vo.setInvoiceType(record.getInvoiceType());
        if (StringUtils.isNotBlank(record.getDkAmount())) {
            vo.setDkAmount(MathUtil.round(record.getDkAmount()));
        } else {
            vo.setDkAmount(MathUtil.round(record.getTaxAmount()));
        }
        // 判断是否升级企业
        List<Tax> orgList = userInfo.getOrg();
        for (Tax tax : orgList) {
            if (record.getGfTaxNo().equals(tax.getTaxno())) {
                vo.setUpgradeStatus(tax.getUpgradeStatus());
            }
        }
        return vo;
    }

    /**
     * 异常发票预警list
     *
     * @param reqVO
     *            查询条件
     * @return 返回
     */
    @Override
    public String listAnomalyInvoice(ExtCautionAbnormalReqVO reqVO) {
        DynamicContextHolder.push(reqVO.getUserInfo().getDbName() + DbConstant.BUSINESS_READ);

        String company = reqVO.getCompany();
        String menuId = reqVO.getMenuId();
        JSONObject json = tabulateRedisService.getTabulateMenu(company, menuId);
        // 分页参数
        Page<ExtTdxRecordInvoice> page = new Page<>(reqVO.getCurr(), reqVO.getSize());
        // 查询参数
        QueryWrapper<ExtTdxRecordInvoice> queryWrapper = createAnomalyQueryWrapper(reqVO);
        // 执行查询
        IPage<ExtTdxRecordInvoice> pageInfo = super.page(page, queryWrapper);

        // 查询结果封装为view
        List<ExtCautionAbnormalRespVO> voList = new ArrayList<>();
        int index = 1;
        // 发票状态码map
        Map<String, String> invoiceStatusMap = FpztEnum.getEnumMap();
        for (ExtTdxRecordInvoice record : pageInfo.getRecords()) {
            ExtCautionAbnormalRespVO vo = convertToAbnormalView(record, invoiceStatusMap);
            // 序号计算 = (当前页-1)*每页条数+1
            vo.setXh((page.getCurrent() - 1) * page.getSize() + index);
            index++;
            voList.add(vo);
        }

        // 设置记录总数
        json.put("total", pageInfo.getTotal());
        json.put("datalist", voList);

        // 合计金额 and 合计税额
        querySumForInvoice(json, queryWrapper);

        return super.responseResult(json);

    }

    /**
     * 异常发票预警查询条件构建
     *
     * @param reqVO
     *            查询条件
     * @return 返回
     */

    private QueryWrapper<ExtTdxRecordInvoice> createAnomalyQueryWrapper(ExtCautionAbnormalReqVO reqVO) {
        QueryWrapper<ExtTdxRecordInvoice> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExtTdxRecordInvoice::getCompany, reqVO.getCompany());
        queryWrapper.lambda()
            // 认证状态为未认证
            .eq(ExtTdxRecordInvoice::getRzhYesorno, RzztEnum.WRZ.getRzztDm())
            // 发票状态为异常的发票
            .ne(ExtTdxRecordInvoice::getInvoiceStatus, FpztEnum.ZC.getFpztDm());

        // 购方税号
        if (StringUtils.isNotBlank(reqVO.getGfsh()) && !"99".equals(reqVO.getGfsh())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getGfTaxNo, reqVO.getGfsh());
        } else {
            List<String> allTaxNo = UserInfoUtil.getGfshAll(reqVO.getUserInfo().getOrg());
            queryWrapper.lambda().in(ExtTdxRecordInvoice::getGfTaxNo, allTaxNo);
        }
        // 发票代码
        if (StringUtils.isNotBlank(reqVO.getInvoiceCode())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceCode, reqVO.getInvoiceCode());
        }
        // 发票号码
        if (StringUtils.isNotBlank(reqVO.getInvoiceNo())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceNo, reqVO.getInvoiceNo());
        }
        // 数电号码
        if (StringUtils.isNotBlank(reqVO.getEleInvoiceNo())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getEleInvoiceNo, reqVO.getEleInvoiceNo());
        }
        // 发票状态
        if (StringUtils.isNotBlank(reqVO.getInvoiceStatus()) && !"99".equals(reqVO.getInvoiceStatus())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceStatus, reqVO.getInvoiceStatus());
        }
        //发票来源
        if (StringUtils.isNotBlank(reqVO.getInvoiceSource()) && !"99".equals(reqVO.getInvoiceSource())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceSource, reqVO.getInvoiceSource());
        }
        //发票类型
        //如果是14
        if("14".equals(reqVO.getInvoiceType())){
            queryWrapper.lambda().and(
                    txf->txf.eq(ExtTdxRecordInvoice::getInvoiceType,"14").
                            or(lqTxf->lqTxf.eq(ExtTdxRecordInvoice::getInvoiceType,"32").eq(ExtTdxRecordInvoice::getLqTdyslxdm, "08"))
            );
            //and (t.invoice_type = '14' or (t.invoice_type = '32' and t.lq_tdyslxDm='08') )
        }
        if("32".equals(reqVO.getInvoiceType())){
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceType,reqVO.getInvoiceType()).ne(ExtTdxRecordInvoice::getLqTdyslxdm, "08");
            //and t.invoice_type = #{invoiceType} and t.lq_tdyslxDm!='08'
        }
        if(!"14".equals(reqVO.getInvoiceType())&&!"32".equals(reqVO.getInvoiceType())&&!"99".equals(reqVO.getInvoiceType())){
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceType,reqVO.getInvoiceType());
            //and t.invoice_type = #{invoiceType}
        }


        // 异常开始时间
        if (reqVO.getYcStartDate() != null && reqVO.getYcEndDate() != null) {
            queryWrapper.lambda().between(ExtTdxRecordInvoice::getStatusUpdateDate,
                DateUtils.strToDateLong(DateUtils.getMorning(reqVO.getYcStartDate())),
                DateUtils.strToDateLong(DateUtils.getNight(reqVO.getYcEndDate())));
        }
        // 异常日期倒序
        queryWrapper.lambda().orderByDesc(ExtTdxRecordInvoice::getStatusUpdateDate)
            .orderByDesc(ExtTdxRecordInvoice::getInvoiceDate);
        return queryWrapper;
    }

    /**
     * 异常发票list pojo转vo
     *
     * @param record
     *            查询条件
     * @param invoiceStatusMap
     *            状态
     * @return 返回
     */
    private ExtCautionAbnormalRespVO convertToAbnormalView(ExtTdxRecordInvoice record,
        Map<String, String> invoiceStatusMap) {
        ExtCautionAbnormalRespVO vo = new ExtCautionAbnormalRespVO();
        // uuid 作为主键
        vo.setId(record.getUuid());
        // 异常日期 取状态修改时间
        vo.setYcDate(DateUtils.dateToStr(record.getStatusUpdateDate()));
        // 发票号码
        vo.setInvoiceNo(record.getInvoiceNo());
        //数电号码
        vo.setEleInvoiceNo(record.getEleInvoiceNo());
        // 发票代码
        vo.setInvoiceCode(record.getInvoiceCode());
        // 开票日期
        vo.setInvoiceDate(DateUtils.dateToStr(record.getInvoiceDate()));
        // 发票状态
//        vo.setInvoiceStatusName(invoiceStatusMap.get(record.getInvoiceStatus()));
        vo.setInvoiceStatusName(dictdetaServcice.queryDictName(DictConstant.INVOICE_STATUS,record.getInvoiceStatus()));
        // 购方名称
        vo.setBuyerName(record.getGfName());
        // 销方名称
        vo.setSellerName(record.getXfName());
        // 金额
        if(ObjectUtil.isNotEmpty(record.getInvoiceAmount())){
            vo.setAmount(MathUtil.round(record.getInvoiceAmount().toPlainString()));
        }
        if(ObjectUtil.isNotEmpty(record.getTaxAmount())){
            // 税额
            vo.setTaxAmount(MathUtil.round(record.getTaxAmount().toPlainString()));
        }

        // 发票类型
        vo.setInvoiceType(record.getInvoiceType());
        return vo;
    }

    /**
     * 普票跨年度预警list
     *
     * @param reqVO
     *            查询条件
     * @return 返回
     */
    @Override
    public String listMaximalInvoice(ExtCautionMaximalReqVO reqVO) {
        DynamicContextHolder.push(reqVO.getUserInfo().getDbName() + DbConstant.BUSINESS_READ);

        String company = reqVO.getCompany();
        String menuId = reqVO.getMenuId();
        JSONObject json = tabulateRedisService.getTabulateMenu(company, menuId);
        // 分页参数
        Page<ExtTdxRecordInvoice> page = new Page<>(reqVO.getCurr(), reqVO.getSize());
        // 查询参数
        QueryWrapper<ExtTdxRecordInvoice> queryWrapper = createMaximalQueryWrapper(reqVO);
        // 执行查询
        IPage<ExtTdxRecordInvoice> pageInfo = super.page(page, queryWrapper);

        // 查询结果封装为view
        List<ExtCautionMaximalRespVO> voList = new ArrayList<>();
        int index = 1;
        for (ExtTdxRecordInvoice record : pageInfo.getRecords()) {
            ExtCautionMaximalRespVO vo = convertToMaximalView(record);
            // 序号计算 = (当前页-1)*每页条数+1
            vo.setXh((page.getCurrent() - 1) * page.getSize() + index);
            index++;
            voList.add(vo);
        }
        // 设置记录总数
        json.put("total", pageInfo.getTotal());
        // 设置记录总数
        json.put("datalist", voList);
        // 合计金额and税额，查询并设置
        if (reqVO.getCurr() == 1) {
            querySumForInvoice(json, queryWrapper);
        }

        return super.responseResult(json);
    }

    /**
     * @param result
     *            返回
     * @param pramsMap
     *            查询条件
     */
    private void querySumForInvoice(JSONObject result, Map<String, Object> pramsMap) {
        // 合计金额 and 合计税额
        ExtReportStatisticsModel sumList = baseMapper.selectInvoiceCount(pramsMap);
        if (sumList.getTotalCount() != 0) {
            result.put("sumInvoiceAmount",
                AmountFormatUtil.fmtMicrometer(MathUtil.round(sumList.getTotalAmount().toPlainString())));
            result.put("sumTaxAmount",
                AmountFormatUtil.fmtMicrometer(MathUtil.round(sumList.getTotalTax().toPlainString())));
            result.put("total", AmountFormatUtil.fmtMicrometer(String.valueOf(sumList.getTotalCount())));
        } else {
            result.put("sumInvoiceAmount", "0");
            result.put("sumTaxAmount", "0");
            result.put("total", "0");
        }
    }

    /**
     * @param result
     *            返回
     * @param queryWrapper
     *            查询条件
     */
    private void querySumForInvoice(JSONObject result, QueryWrapper<ExtTdxRecordInvoice> queryWrapper) {
        // 合计金额 and 合计税额
        List<ExtTdxRecordInvoice> sumList = super.list(queryWrapper);
        BigDecimal sumInvoiceAmount = new BigDecimal(0);
        BigDecimal sumTaxAmount = new BigDecimal(0);
        for (ExtTdxRecordInvoice record : sumList) {
            if(ObjectUtil.isNotEmpty(record.getInvoiceAmount())){
                sumInvoiceAmount = sumInvoiceAmount.add(record.getInvoiceAmount());
            }
            if(ObjectUtil.isNotEmpty(record.getTaxAmount())){
                sumTaxAmount = sumTaxAmount.add(record.getTaxAmount());
            }
        }
        result.put("sumInvoiceAmount",
            AmountFormatUtil.fmtMicrometer(MathUtil.round(sumInvoiceAmount.toPlainString())));
        result.put("sumTaxAmount", AmountFormatUtil.fmtMicrometer(MathUtil.round(sumTaxAmount.toPlainString())));
    }

    /**
     * 普票跨年度预警查询条件构建 方便查询，查询条件 签收日期是今年（取今年第一天到今年最后一天）， 开票日期为去年（取去年第一天到去年最后一天）的发票
     *
     * @param reqVO
     *            查询条件
     * @return 返回
     */

    private QueryWrapper<ExtTdxRecordInvoice> createMaximalQueryWrapper(ExtCautionMaximalReqVO reqVO) {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        // 今年第一天
        Date currYearFirst = DateUtils.getYearFirst(currentYear);
        log.debug("今年第一天：" + DateUtils.getMorning(DateUtils.strToDate(DateUtils.dateToStrLong(currYearFirst))));

        // 今年最后一天
        Date currYearLast = DateUtils.getYearLast(currentYear);
        log.debug("今年最后一天：" + DateUtils.getNight(DateUtils.strToDate(DateUtils.dateToStrLong(currYearLast))));

        int prevYear = currentYear - 1;
        // 去年第一天
        Date prevYearFirst = DateUtils.getYearFirst(prevYear);
        log.debug("去年第一天：" + DateUtils.getMorning(DateUtils.strToDate(DateUtils.dateToStrLong(prevYearFirst))));
        // 去年最后一天
        Date prevYearLast = DateUtils.getYearLast(prevYear);
        log.debug("去年最后一天：" + DateUtils.getNight(DateUtils.strToDate(DateUtils.dateToStrLong(prevYearLast))));

        QueryWrapper<ExtTdxRecordInvoice> queryWrapper = new QueryWrapper<>();
        // 签收日期是今年
        queryWrapper.lambda().ge(ExtTdxRecordInvoice::getQsDate, currYearFirst)
            .le(ExtTdxRecordInvoice::getQsDate, currYearLast)
            // 开票日期为去年
            .ge(ExtTdxRecordInvoice::getInvoiceDate, prevYearFirst)
            .le(ExtTdxRecordInvoice::getInvoiceDate, prevYearLast);

        // 购方税号
        if (StringUtils.isNotBlank(reqVO.getGfsh()) && !"99".equals(reqVO.getGfsh())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getGfTaxNo, reqVO.getGfsh());
        } else {
            List<String> allTaxNo = UserInfoUtil.getGfshAll(reqVO.getUserInfo().getOrg());
            queryWrapper.lambda().in(ExtTdxRecordInvoice::getGfTaxNo, allTaxNo);
        }
        // 发票号码
        if (StringUtils.isNotBlank(reqVO.getInvoiceNo())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getInvoiceNo, reqVO.getInvoiceNo());
        }
        // 数电号码
        if (StringUtils.isNotBlank(reqVO.getEleInvoiceNo())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getEleInvoiceNo, reqVO.getEleInvoiceNo());
        }
        if (StringUtils.isNotBlank(reqVO.getCompany())) {
            queryWrapper.lambda().eq(ExtTdxRecordInvoice::getCompany, reqVO.getCompany());
        }
        // 前端只展示04，10，11的发票
        List<String> invoiceTypeList = new ArrayList<>();
        invoiceTypeList.add("04");
        invoiceTypeList.add("10");
        invoiceTypeList.add("11");
        invoiceTypeList.add("15");
        invoiceTypeList.add("32");
        invoiceTypeList.add("186");
        queryWrapper.lambda().in(ExtTdxRecordInvoice::getInvoiceType, invoiceTypeList);
        // 签收日期倒序
        queryWrapper.lambda().orderByDesc(ExtTdxRecordInvoice::getQsDate)
            .orderByDesc(ExtTdxRecordInvoice::getInvoiceDate);
        return queryWrapper;
    }

    /**
     * 普票跨年度预警 pojo转vo
     *
     * @param record
     *            抵账
     * @return 返回
     */
    private ExtCautionMaximalRespVO convertToMaximalView(ExtTdxRecordInvoice record) {
        ExtCautionMaximalRespVO vo = new ExtCautionMaximalRespVO();
        // uuid 作为主键
        vo.setId(record.getUuid());
        // 签收日期
        vo.setQsDate(DateUtils.dateToStr(record.getQsDate()));
        // 签收结果
//        vo.setQsStatusName(FpqsjgEnum.getSmbEnumMap().get(record.getQsStatus()));
        vo.setQsStatusName(dictdetaServcice.queryDictName(DictConstant.QS_RESULTS,record.getQsStatus()));
        // 签收人
        vo.setQsUserName(record.getQsName());
        // 发票号码
        vo.setInvoiceNo(record.getInvoiceNo());
        // 发票代码
        vo.setInvoiceCode(record.getInvoiceCode());
        //数电号码
        vo.setEleInvoiceNo(record.getEleInvoiceNo());
        // 开票日期
        vo.setInvoiceDate(DateUtils.dateToStr(record.getInvoiceDate()));
        // 购方名称
        vo.setBuyerName(record.getGfName());
        // 销方名称
        vo.setSellerName(record.getXfName());
        // 未税金额
        if(ObjectUtil.isNotEmpty(record.getInvoiceAmount())){
            vo.setNoTaxAmount(AmountFormatUtil.fmtMicrometer(MathUtil.round(record.getInvoiceAmount().toPlainString())));
        }
        // 税额
        if(ObjectUtil.isNotEmpty(record.getTaxAmount())){
            vo.setTaxAmount(AmountFormatUtil.fmtMicrometer(MathUtil.round(record.getTaxAmount().toPlainString())));
        }
        // 发票类型
        vo.setInvoiceType(record.getInvoiceType());
        return vo;
    }
}
