package com.dxhy.base.service.tdxrecordinvoice;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dxhy.api.model.config.Tax;
import com.dxhy.base.dao.BaseTDxRecordInvoiceDao;
import com.dxhy.base.dao.BaseTDxTaxCurrentDao;
import com.dxhy.base.dao.BaseYqsqDao;
import com.dxhy.base.entity.BaseTDxDkCount;
import com.dxhy.base.entity.BaseTDxRecordInvoice;
import com.dxhy.base.entity.BaseTDxTaxCurrent;
import com.dxhy.base.model.BaseYqsqRespVO;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.YqsqztEnum;
import com.dxhy.common.service.impl.MpBaseServiceImpl;
import com.dxhy.common.util.AmountFormatUtil;
import com.dxhy.common.util.InvoiceUtil;
import com.dxhy.common.util.MathUtil;
import com.dxhy.common.utils.DateUtils;
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.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * 逾期申请业务实现类
 *
 * @author zhanghong
 * @date 2019年5月8日
 */

@SuppressWarnings({"AlibabaLowerCamelCaseVariableNaming", "AlibabaUndefineMagicConstant", "AlibabaMethodTooLong"})
@Service("baseIYqsqService")
@Slf4j
public class BaseYqsqServiceImpl extends MpBaseServiceImpl<BaseYqsqDao, BaseYqsqRespVO> implements BaseIYqsqService {

    @Resource
    private BaseTDxRecordInvoiceDao baseTDxRecordInvoiceDao;

    @Resource
    private BaseTDxTaxCurrentDao baseTDxTaxCurrentDao;
    private static final Pattern PATTERN_DATE = Pattern.compile(
        "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$");
    private static final Pattern PATTERN_AMOUNT = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$");

    /**
     * @param pramsMap
     *            请求参数集合
     * @return 请求参数
     */
    @Override
    public String selectByYqsqlb(Map<String, Object> pramsMap) {

        JSONObject json = new JSONObject();
        Map<String, Object> reqMap = new HashMap<>(16);

        List<Tax> taxList = (List<Tax>)pramsMap.get("taxList");
        List<String> orgList = new ArrayList<>();
        for (Tax tax : taxList) {
            String upgradeStatus = tax.getUpgradeStatus();
            if ("1".equals(upgradeStatus)) {
                orgList.add(tax.getTaxno());
            }
        }
        reqMap.put("gfsh", pramsMap.get("gfsh"));
        String datalist = (String)pramsMap.get("datalist");
        JSONObject listjson = JSONObject.parseObject(datalist);
        // 首先把字符串转成 JSONArray 对象
        JSONArray jsonArray = JSONArray.parseArray(listjson.getString("datalist"));
        StringBuilder sb = new StringBuilder();
        List<Object> returnList = new ArrayList<>();
        int cgsl = 0;
        int sbsl = 0;
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String fpdm = jsonObject.getString("fpdm");
            String fphm = jsonObject.getString("fphm");
            String je = jsonObject.getString("je");
            String kprq = jsonObject.getString("kprq");
            String se = jsonObject.getString("se");
            String xfsh = jsonObject.getString("xfsh");
            String gfsbh = jsonObject.getString("gfsh");
            String gfmc = jsonObject.getString("gfmc");
            if (StringUtils.isBlank(fpdm)) {
                sb.append("第").append(i + 1).append("条数据发票代码为空 \n ");
                sbsl = sbsl + 1;
                continue;
            } else {
                if (fpdm.length() == 10 || fpdm.length() == 12) {
                    InvoiceUtil invoiceUtil = new InvoiceUtil(fpdm);
                    String invoiceType = invoiceUtil.getFplxdm();
                    pramsMap.put("invoiceType", invoiceType);
                    if (!"01".equals(invoiceType) && !"03".equals(invoiceType) && !"14".equals(invoiceType)) {
                        sb.append("第").append(i + 1).append("条数据发票类型不符 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }
                } else {
                    sb.append("第").append(i + 1).append("条数据发票代码格式错误 \n ");
                    sbsl = sbsl + 1;
                    continue;
                }
            }
            if (StringUtils.isBlank(fphm)) {
                sb.append("第").append(i + 1).append("条数据发票号码为空 \n ");
                sbsl = sbsl + 1;
                continue;
            } else {
                if (fphm.length() != 8) {
                    sb.append("第").append(i + 1).append("条数据发票号码格式错误 \n ");
                    sbsl = sbsl + 1;
                    continue;
                }
            }
            if (StringUtils.isBlank(je)) {
                sb.append("第").append(i + 1).append("条数据金额为空 \n ");
                sbsl = sbsl + 1;
                continue;
            } else {
                // 判断小数点后2位的数字的正则表达式

                Matcher match = PATTERN_AMOUNT.matcher(je);
                if (!match.matches()) {
                    sb.append("第").append(i + 1).append("条金额格式错误 \n ");
                    sbsl = sbsl + 1;
                    continue;
                }
            }
            if (StringUtils.isBlank(kprq)) {
                sb.append("第").append(i + 1).append("条数据开票日期为空 \n ");
                sbsl = sbsl + 1;
                continue;
            } else {
                // 判断日期
                // yyyy-mm-dd
                // 的正则表达式（能够区分真实日期，区分闰年）
                Matcher match = PATTERN_DATE.matcher(kprq);
                if (!match.matches()) {
                    sb.append("第").append(i + 1).append("条数据开票日期格式错误 \n ");
                    sbsl = sbsl + 1;
                    continue;
                }
            }
            if (StringUtils.isBlank(se)) {
                sb.append("第").append(i + 1).append("条数据税额为空 \n ");
                sbsl = sbsl + 1;
                continue;
            } else {
                // 判断小数点后2位的数字的正则表达式
                Matcher match = PATTERN_AMOUNT.matcher(se);
                if (!match.matches()) {
                    sb.append("第").append(i + 1).append("条税额格式错误 \n ");
                    sbsl = sbsl + 1;
                    continue;
                }
            }
            if (StringUtils.isBlank(xfsh)) {
                sb.append("第").append(i + 1).append("条数据销方税号为空 \n ");
                sbsl = sbsl + 1;
                continue;
            }
            if (StringUtils.isBlank(gfsbh)) {
                sb.append("第").append(i + 1).append("条数据购方税号为空 \n ");
                sbsl = sbsl + 1;
                continue;
            }
            if (StringUtils.isBlank(gfmc)) {
                sb.append("第").append(i + 1).append("条数据购方名称为空 \n ");
                sbsl = sbsl + 1;
                continue;
            }
            if (!orgList.contains(gfsbh)) {
                sb.append("第").append(i + 1).append("条数据该发票税号").append(gfsbh).append("不属于升级地区 \n ");
                sbsl = sbsl + 1;
                continue;
            }

            InvoiceUtil invoiceUtil = new InvoiceUtil(fpdm);
            String invoiceType = invoiceUtil.getFplxdm();
            if (!"01".equals(invoiceType) && !"03".equals(invoiceType) && !"14".equals(invoiceType)) {
                sb.append("第").append(i + 1).append("条数据发票类型不符 \n ");
                sbsl = sbsl + 1;
                continue;
            }
            Map<String, Object> curMap = new HashMap<>(4);
            List<String> shList = new ArrayList<>();
            shList.add(gfsbh);
            curMap.put("gfsh", shList);
            List<BaseTDxDkCount> curList = baseTDxRecordInvoiceDao.selectDksh(curMap);
            BaseTDxDkCount cur = curList.get(0);
            String skssq = cur.getSkssq();
            String year = skssq.substring(0, 4);
            String mon = skssq.substring(4);
            LocalDate localDate = LocalDate.of(Integer.parseInt(year), Integer.parseInt(mon), 1);
            LocalDate localDate1 = localDate.plusMonths(1);
            LocalDate localDate2 = LocalDate.now();
            if (!"0".equals(cur.getTjStatus()) && !"3".equals(cur.getTjStatus()) && !localDate2.isBefore(localDate1)) {
                sb.append("第").append(i + 1).append("条数据该税号已申请抵扣统计 \n ");
                sbsl = sbsl + 1;
                continue;
            }

            reqMap.put("fpdm", fpdm);
            reqMap.put("fphm", fphm);
            reqMap.put("je", je);
            reqMap.put("kprq", kprq);
            reqMap.put("se", se);
            reqMap.put("xfsh", xfsh);
            DynamicContextHolder.push(pramsMap.get("dbName") + DbConstant.BUSINESS_READ);
            QueryWrapper<BaseTDxRecordInvoice> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("uuid", fpdm + fphm);
            // 根据uuid查询底账是否有数据
            List<BaseTDxRecordInvoice> list = baseTDxRecordInvoiceDao.selectList(queryWrapper);
            // 根据查询条件查询底账信息是否有相符数据
            List<BaseYqsqRespVO> resultList = super.baseMapper.selectByYqsqlb(reqMap);
            QueryWrapper<BaseTDxTaxCurrent> currentWrapper = new QueryWrapper<>();
            currentWrapper.eq("taxno", gfsbh);
            DynamicContextHolder.push(pramsMap.get("dbName") + DbConstant.BUSINESS_READ);
            BaseTDxTaxCurrent current = baseTDxTaxCurrentDao.selectOne(currentWrapper);
            Date startDate = DateUtils.strToDatePeriod(current.getSelectStartDate());
            Date date = DateUtils.strToDate(kprq);
            if (date.compareTo(startDate) >= 0) {
                sb.append("第").append(i + 1).append("条数据开票日期未逾期不符合申请条件 \n ");
                sbsl = sbsl + 1;
                continue;
            }
            if (list != null && list.size() > 0) {
                if (!"0".equals(list.get(0).getYqsqStatus()) && list.get(0).getYqsqStatus() != null
                    && !"5".equals(list.get(0).getYqsqStatus())) {
                    if (current.getCurrentTaxPeriod().equals(list.get(0).getYqCurrentPeriod())) {
                        sb.append("第").append(i + 1).append("条数据本属期已经逾期申请过 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }

                }
                if (!"0".equals(list.get(0).getBdkStatus()) && !"5".equals(list.get(0).getBdkStatus())) {
                    sb.append("第").append(i + 1).append("条数据已申请不认证 \n ");
                    sbsl = sbsl + 1;
                    continue;
                }
                if (resultList == null || resultList.size() == 0) {
                    String invoiceDate = DateUtils.dateToStr(list.get(0).getInvoiceDate());
                    if (!kprq.equals(invoiceDate)) {
                        sb.append("第").append(i + 1).append("条数据开票日期与底账数据不一致 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }
                    je = MathUtil.round(je);
                    if (!je.equals(MathUtil.round(list.get(0).getInvoiceAmount().toPlainString()))) {
                        sb.append("第").append(i + 1).append("条数据金额与底账数据不一致 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }
                    if (!gfsbh.equals(list.get(0).getGfTaxNo())) {
                        sb.append("第").append(i + 1).append("条数据购方税号与底账数据不一致 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }
                    if (!xfsh.equals(list.get(0).getXfTaxNo())) {
                        sb.append("第").append(i + 1).append("条数据销方税号与底账数据不一致 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }
                    se = MathUtil.round(se);
                    if (!se.equals(MathUtil.round(list.get(0).getTaxAmount().toPlainString()))) {
                        sb.append("第").append(i + 1).append("条数据税额与底账数据不一致 \n ");
                        sbsl = sbsl + 1;
                        continue;
                    }
                }
            }

            if (resultList != null && resultList.size() > 0) {

                for (BaseYqsqRespVO baseYqsqRespVO : resultList) {

                    if ("0".equals(baseYqsqRespVO.getRzzt()) && "0".equals(baseYqsqRespVO.getFpzt())) {
                        DynamicContextHolder.push(pramsMap.get("dbName") + DbConstant.BUSINESS_WRITE);
                        String uuid = baseYqsqRespVO.getFpdm() + baseYqsqRespVO.getFphm();
                        Map<String, Object> map = new HashMap<>(3);
                        map.put("uuid", uuid);
                        map.put("skssq", current.getCurrentTaxPeriod());
                        super.baseMapper.updateByUuid(map);

                        returnList.add(baseYqsqRespVO);
                        cgsl = cgsl + 1;
                    } else if (!"0".equals(baseYqsqRespVO.getRzzt())) {
                        sb.append("第").append(i + 1).append("条数据认证状态不符合申请条件 \n ");
                        sbsl = sbsl + 1;
                    } else if (!"0".equals(baseYqsqRespVO.getFpzt())) {
                        sb.append("第").append(i + 1).append("条数据发票状态不符合申请条件 \n ");
                        sbsl = sbsl + 1;
                    } else {
                        sb.append("第").append(i + 1).append("条数据不符合申请条件 \n ");
                        sbsl = sbsl + 1;
                    }
                }
            }

            if (list == null || list.size() == 0) {
                DynamicContextHolder.push(pramsMap.get("dbName") + DbConstant.BUSINESS_WRITE);
                reqMap.put("gfsbh", gfsbh);
                reqMap.put("uuid", fpdm + fphm);
                reqMap.put("skssq", current.getCurrentTaxPeriod());
                BaseTDxRecordInvoice recordInvoice = new BaseTDxRecordInvoice();
                recordInvoice.setUuid(fpdm + fphm);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    recordInvoice.setInvoiceDate(sdf.parse(kprq));
                } catch (ParseException e) {
                   log.info("业务处理异常：{}", e);
                }
                recordInvoice.setInvoiceCode(fpdm);
                recordInvoice.setInvoiceNo(fphm);
                recordInvoice.setInvoiceAmount(new BigDecimal(je));
                recordInvoice.setTaxAmount(new BigDecimal(se));
                recordInvoice.setXfTaxNo(xfsh);
                recordInvoice.setGfTaxNo(gfsbh);
                recordInvoice.setGfName(gfmc);
                recordInvoice.setRzlx("5");
                recordInvoice.setYqsqStatus("1");
                recordInvoice.setYqCurrentPeriod(current.getCurrentTaxPeriod());
                recordInvoice.setCreateDate(new Date());
                recordInvoice.setYqsqDate(new Date());
                recordInvoice.setSourceSystem("2");
                recordInvoice.setInvoiceStatus("0");
                recordInvoice.setInvoiceType(invoiceType);
                recordInvoice.setCompany((String)pramsMap.get("company"));
                baseTDxRecordInvoiceDao.insert(recordInvoice);
                Map<String, Object> insertMap = new HashMap<>(16);
                insertMap.put("gfsh", pramsMap.get("gfsh"));
                insertMap.put("fpdm", fpdm);
                insertMap.put("fphm", fphm);
                returnList.add(super.baseMapper.selectByYqsqlb(insertMap).get(0));
                cgsl = cgsl + 1;
            }
        }
        json.put("cgsl", cgsl);
        json.put("sbsl", sbsl);
        json.put("message", sb.toString());
        json.put("datalist", returnList);

        return super.responseResult(json);
    }

    @Override
    public String selectByCxtj(Map<String, Object> pramsMap, int curr, int size) {
        String[] titlelist = {"序号", "发票代码", "发票号码", "开票日期", "购方名称", "购方税号", "销方税号", "金额", "税额", "审核状态", "审核时间", "录入时间"};
        String[] titleprop = {"xh", "fpdm", "fphm", "kprq", "gfmc", "gfsh", "xfsh", "je", "se", "shzt", "shsj", "lrsj"};

        // 需要设置返回列表标题时调用
        JSONObject json = super.setTitleList(titlelist, titleprop);
        DynamicContextHolder.push(pramsMap.get("dbName") + DbConstant.BUSINESS_READ);

        // 设置记录总数
        if (curr == 1) {
            BaseYqsqRespVO baseYqsqRespVO = super.baseMapper.selectHjByCxtj(pramsMap);
            String hjje = "0.00";
            String hjse = "0.00";
            String total = "0";
            if (baseYqsqRespVO != null) {
                total = baseYqsqRespVO.getXh();
                if (!"0".equals(total)) {
                    hjje = MathUtil.add(hjje, MathUtil.round(baseYqsqRespVO.getJe()));
                    hjse = MathUtil.add(hjse, MathUtil.round(baseYqsqRespVO.getSe()));
                }
            }
            json.put("total", AmountFormatUtil.fmtMicrometer(total));
            json.put("hjje", AmountFormatUtil.fmtMicrometer(hjje));
            json.put("hjse", AmountFormatUtil.fmtMicrometer(hjse));
        }
        PageHelper.startPage(curr, size);
        List<BaseYqsqRespVO> pageList = super.baseMapper.selectByCxtj(pramsMap);
        PageInfo<BaseYqsqRespVO> pageInfo = new PageInfo<>(pageList);
        // 用于页面展示
        List<BaseYqsqRespVO> resultList = pageInfo.getList();
        if (resultList != null && resultList.size() > 0) {
            int start = new Long(pageInfo.getStartRow()).intValue();

            for (int i = 0; i < resultList.size(); i++) {
                // 页面展示需要信息
                resultList.get(i).setXh(String.valueOf(start + i));
                resultList.get(i).setJe(AmountFormatUtil.fmtMicrometer(MathUtil.round(resultList.get(i).getJe())));
                resultList.get(i).setSe(AmountFormatUtil.fmtMicrometer(MathUtil.round(resultList.get(i).getSe())));
                resultList.get(i).setShzt(SHZT_MAP.get(resultList.get(i).getShzt()));
            }
        }
        json.put("total", pageInfo.getTotal());
        json.put("datalist", resultList);
        return super.responseResult(json);
    }

    /**
     * 审核状态统一放入map集合中
     */
    public static final Map<String, String> SHZT_MAP = new LinkedHashMap<String, String>() {

        private static final long serialVersionUID = 1L;

        {
            for (YqsqztEnum en : YqsqztEnum.values()) {
                this.put(en.getShztDm(), en.getShztMc(en.getIndex()));
            }
        }
    };

}
