package com.jeeplus.psimanage.serialNumTpl.service;

import cn.hutool.extra.spring.SpringUtil;
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.jeeplus.common.TokenProvider;
import com.jeeplus.psimanage.serialNumTpl.domain.PsiSysSerialnumTpl;
import com.jeeplus.psimanage.serialNumTpl.mapper.PsiSerialnumTplMapper;
import com.jeeplus.sys.domain.Office;
import com.jeeplus.sys.feign.IOfficeApi;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.service.dto.UserDTO;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class PsiSerialnumTplService {

    @Resource
    private PsiSerialnumTplMapper psiSerialnumTplMapper;

//    @Resource
//    private OfficeMapper officeMapper;

    public IPage<PsiSysSerialnumTpl> list(Page<PsiSysSerialnumTpl> page, QueryWrapper<PsiSysSerialnumTpl> sysSerialnumTplQueryWrapper) {
        sysSerialnumTplQueryWrapper.eq("del_flag", 0);
        IPage<PsiSysSerialnumTpl> list = psiSerialnumTplMapper.pageList(page, sysSerialnumTplQueryWrapper);
        return list;
    }

    public String remove(String id) {
        psiSerialnumTplMapper.deleteById(id);
        return "操作成功";
    }

    public PsiSysSerialnumTpl findById(String id) {
        PsiSysSerialnumTpl psiSysSerialnumTpl = psiSerialnumTplMapper.selectById(id);
        return psiSysSerialnumTpl;
    }

    public String save(PsiSysSerialnumTpl psiSysSerialnumTpl) {
        //获取当前登录人信息
        UserDTO dto = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken ( ));
//        UserDTO dto = UserUtils.getCurrentUserDTO();
        //新增
        if (StringUtils.isEmpty(psiSysSerialnumTpl.getId())) {
            String id = UUID.randomUUID().toString().replace("-", "");
            psiSysSerialnumTpl.setId(id);
            psiSysSerialnumTpl.setCreateById(dto.getId());
            psiSysSerialnumTpl.setCreateTime(new Date());
            psiSysSerialnumTpl.setUpdateById(dto.getId());
            psiSysSerialnumTpl.setUpdateTime(new Date());
            psiSysSerialnumTpl.setDelFlag(0);
            psiSerialnumTplMapper.insert(psiSysSerialnumTpl);
        }
        //修改
        if (StringUtils.isNotEmpty(psiSysSerialnumTpl.getId())) {
            psiSysSerialnumTpl.setUpdateById(dto.getId());
            psiSysSerialnumTpl.setUpdateTime(new Date());
            psiSerialnumTplMapper.updateById(psiSysSerialnumTpl);
        }
        return "操作完成";
    }

    @Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW)
    public String genSerialNum(String companyId, String bizCode,String currentToken) throws Exception {
//        String currentToken = TokenProvider.getCurrentToken();
        //获取当前登录人信息
        UserDTO dto = SpringUtil.getBean(IUserApi.class).getByToken(currentToken);
//        UserDTO dto = UserUtils.getCurrentUserDTO();
        Office office = SpringUtil.getBean ( IOfficeApi.class ).selectById(companyId);
        if (StringUtils.isBlank(bizCode)){
            throw new Exception("生成编号失败，业务类型不能为空");
        }
        if (office != null) {
            PsiSysSerialnumTpl numTpl = this.querySerialTpl(office, bizCode);
            if (numTpl == null) {
                //查询编号模板   {brspnm}DZ-{year}-{serialNum}
                PsiSysSerialnumTpl serialNumTpl = psiSerialnumTplMapper.queryByComAndBizCode(companyId, bizCode);
                serialNumTpl.setCompanyId(companyId);
                serialNumTpl.setSerialNum(0);
                serialNumTpl.setCreateById(dto.getId());
                serialNumTpl.setId(UUID.randomUUID().toString().replace("-", ""));
                psiSerialnumTplMapper.insert(serialNumTpl);
                numTpl = serialNumTpl;
            }
            if (numTpl == null) {
                throw new Exception("生成编号失败，请先设置相关业务编号模板");
            }
            String year = DateUtils.formatDate(new Date(), "yyyy");
            if (!year.equals(numTpl.getYearBuilt())) {
                psiSerialnumTplMapper.resetSerialNum(numTpl.getId(), numTpl.getYearBuilt(), year);
            }
            Map<String, String> map = new HashMap<>();
            String serialTpl = numTpl.getSerialTpl();
            int i = psiSerialnumTplMapper.updateSerialNum(numTpl);
            if (i != 1) {
                throw new Exception("生成编号失败，请稍后重试");
            }
            String num = String.valueOf(numTpl.getSerialNum() + 1);
            if(!year.equals(numTpl.getYearBuilt())){
                num = "1";
            }
            StringBuffer sb = new StringBuffer();
            for (int x = 0; x < (numTpl.getSerialNumLen() - num.length()); x++) {
                sb.append("0");
            }
            sb.append(num);
            //查询公司简称
            if (serialTpl.contains("spnm")) {
                String companyShortname = SpringUtil.getBean ( IUserApi.class ).getSysParam("company_shortname",currentToken);
//                String companyShortname = UserUtils.getSysParam("company_shortname");
                map.put("spnm", StringUtils.isBlank(companyShortname) ? "" : companyShortname);
            }
            //查询分公司简称
            if (serialTpl.contains("brspnm")) {
                String branchShortname = SpringUtil.getBean ( IUserApi.class ).getSysParam("branch_shortname",currentToken);
//                String branchShortname = UserUtils.getSysParam("branch_shortname");
                map.put("brspnm", StringUtils.isBlank(branchShortname) ? "" : branchShortname);
            }
            //年份
            if (serialTpl.contains("year")) {
                map.put("year", year);
            }
            //月份
            if (serialTpl.contains("month")) {
                int month = new Date().getMonth() + 1;
                map.put("month", month + "");
            }
            //序列号
            if (serialTpl.contains("serialNum")) {
                map.put("serialNum", sb.toString());
            }
            //日期
            if (serialTpl.contains("day")) {
                map.put("day", new Date().getDate() + "");
            }
            String serNum = renderString(serialTpl, map);
            return serNum;
        }
        return "";
    }

    @Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW)
    public String genSerialNumNoSort(String companyId, String bizCode,String currentToken) throws Exception {
//        String currentToken = TokenProvider.getCurrentToken();
        //获取当前登录人信息
        UserDTO dto = SpringUtil.getBean(IUserApi.class).getByToken(currentToken);
//        UserDTO dto = UserUtils.getCurrentUserDTO();
        Office office = SpringUtil.getBean ( IOfficeApi.class ).selectById(companyId);
//        Office office = officeMapper.selectById(companyId);
        if (StringUtils.isBlank(bizCode)){
            throw new Exception("生成编号失败，业务类型不能为空");
        }
        if (office != null) {
            PsiSysSerialnumTpl numTpl = this.querySerialTpl(office, bizCode);
            if (numTpl == null) {
                //查询编号模板   {brspnm}DZ-{year}-{serialNum}
                PsiSysSerialnumTpl serialNumTpl = psiSerialnumTplMapper.queryByComAndBizCode(companyId, bizCode);
                serialNumTpl.setCompanyId(companyId);
                serialNumTpl.setSerialNum(0);
                serialNumTpl.setCreateById(dto.getId());
                serialNumTpl.setId(UUID.randomUUID().toString().replace("-", ""));
                psiSerialnumTplMapper.insert(serialNumTpl);
                numTpl = serialNumTpl;
            }
            if (numTpl == null) {
                throw new Exception("生成编号失败，请先设置相关业务编号模板");
            }
            String year = DateUtils.formatDate(new Date(), "yyyy");
            if (!year.equals(numTpl.getYearBuilt())) {
                psiSerialnumTplMapper.resetSerialNum(numTpl.getId(), numTpl.getYearBuilt(), year);
            }
            Map<String, String> map = new HashMap<>();
            String serialTpl = numTpl.getSerialTpl();
            int i = psiSerialnumTplMapper.updateSerialNum(numTpl);
            if (i != 1) {
                throw new Exception("生成编号失败，请稍后重试");
            }
            String num = String.valueOf(numTpl.getSerialNum() + 1);
            if(!year.equals(numTpl.getYearBuilt())){
                num = "1";
            }
            StringBuffer sb = new StringBuffer();
            sb.append(num);
            //查询公司简称
            if (serialTpl.contains("spnm")) {
                String companyShortname = SpringUtil.getBean ( IUserApi.class ).getSysParam("company_shortname",currentToken);
//                String companyShortname = UserUtils.getSysParam("company_shortname");
                map.put("spnm", StringUtils.isBlank(companyShortname) ? "" : companyShortname);
            }
            //查询分公司简称
            if (serialTpl.contains("brspnm")) {
                String branchShortname = SpringUtil.getBean ( IUserApi.class ).getSysParam("branch_shortname",currentToken);
//                String branchShortname = UserUtils.getSysParam("branch_shortname");
                map.put("brspnm", StringUtils.isBlank(branchShortname) ? "" : branchShortname);
            }
            //年份
            if (serialTpl.contains("year")) {
                map.put("year", year);
            }
            //月份
            if (serialTpl.contains("month")) {
                int month = new Date().getMonth() + 1;
                map.put("month", month + "");
            }
            //序列号
            if (serialTpl.contains("serialNum")) {
                map.put("serialNum", sb.toString());
            }
            //日期
            if (serialTpl.contains("day")) {
                map.put("day", new Date().getDate() + "");
            }
            String serNum = renderString(serialTpl, map);
            return serNum;
        }
        return "";
    }

    @Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW)
    public String genSerialReviewNum(String companyId, String bizCode,String currentToken) throws Exception {
//        String currentToken = TokenProvider.getCurrentToken();
        //获取当前登录人信息
        UserDTO dto = SpringUtil.getBean(IUserApi.class).getByToken(currentToken);
//        UserDTO dto = UserUtils.getCurrentUserDTO();
        Office office = SpringUtil.getBean ( IOfficeApi.class ).selectById(companyId);
//        Office office = officeMapper.selectById(companyId);
        if (StringUtils.isBlank(bizCode)){
            throw new Exception("生成编号失败，业务类型不能为空");
        }
        if (office != null) {
            PsiSysSerialnumTpl numTpl = this.querySerialTpl(office, bizCode);
            if (numTpl == null) {
                //查询编号模板   {brspnm}DZ-{year}-{serialNum}
                PsiSysSerialnumTpl serialNumTpl = psiSerialnumTplMapper.queryByComAndBizCode(companyId, bizCode);
                serialNumTpl.setCompanyId(companyId);
                serialNumTpl.setSerialNum(0);
                serialNumTpl.setCreateById(dto.getId());
                serialNumTpl.setId(UUID.randomUUID().toString().replace("-", ""));
                psiSerialnumTplMapper.insert(serialNumTpl);
                numTpl = serialNumTpl;
            }
            if (numTpl == null) {
                throw new Exception("生成编号失败，请先设置相关业务编号模板");
            }
            String year = DateUtils.formatDate(new Date(), "yyyy");
            if (!year.equals(numTpl.getYearBuilt())) {
                psiSerialnumTplMapper.resetSerialNum(numTpl.getId(), numTpl.getYearBuilt(), year);
            }
            Map<String, String> map = new HashMap<>();
            String serialTpl = numTpl.getSerialTpl();
            int i = psiSerialnumTplMapper.updateSerialNum(numTpl);
            if (i != 1) {
                throw new Exception("生成编号失败，请稍后重试");
            }
            String num = String.valueOf(numTpl.getSerialNum() + 1);
            if(!year.equals(numTpl.getYearBuilt())){
                num = "1";
            }
            StringBuffer sb = new StringBuffer();
//            for (int x = 0; x < (numTpl.getSerialNumLen() - num.length()); x++) {
//                sb.append("0");
//            }
            sb.append(num);
            //查询公司简称
            if (serialTpl.contains("spnm")) {
                String companyShortname = SpringUtil.getBean ( IUserApi.class ).getSysParam("company_shortname",currentToken);
//                String companyShortname = UserUtils.getSysParam("company_shortname");
                map.put("spnm", StringUtils.isBlank(companyShortname) ? "" : companyShortname);
            }
            //查询分公司简称
            if (serialTpl.contains("brspnm")) {
                String branchShortname = SpringUtil.getBean ( IUserApi.class ).getSysParam("branch_shortname",currentToken);
//                String branchShortname = UserUtils.getSysParam("branch_shortname");
                map.put("brspnm", StringUtils.isBlank(branchShortname) ? "" : branchShortname);
            }
            //年份
            if (serialTpl.contains("year")) {
                map.put("year", year);
            }
            //月份
            if (serialTpl.contains("month")) {
                int month = new Date().getMonth() + 1;
                map.put("month", month + "");
            }
            //序列号
            if (serialTpl.contains("serialNum")) {
                map.put("serialNum", sb.toString());
            }
            //日期
            if (serialTpl.contains("day")) {
                map.put("day", new Date().getDate() + "");
            }
            String serNum = renderString(serialTpl, map);
            return serNum;
        }
        return "";
    }

    private PsiSysSerialnumTpl querySerialTpl(Office company, String bizCode) {
        PsiSysSerialnumTpl numTpl = psiSerialnumTplMapper.queryByComAndBizCode(company.getId(), bizCode);
        if (numTpl==null && company.getParentId()!=null && !"0".equals(company.getParentId())){
            Office office = SpringUtil.getBean ( IOfficeApi.class ).selectById(company.getParentId());
//            Office office = officeMapper.selectById(company.getParentId());
            numTpl = this.querySerialTpl(office,bizCode);
        }
        return numTpl;
    }

    /**
     * 根据键值对填充字符串，如("hello {name}",{name:"xiaoming"})
     * 输出：
     * @param content
     * @param map
     * @return
     */
    public static String renderString(String content, Map<String, String> map){
        Set<Map.Entry<String, String>> sets = map.entrySet();
        for(Map.Entry<String, String> entry : sets) {
            String regex = "\\{" + entry.getKey() + "\\}";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(content);
            content = matcher.replaceAll(entry.getValue());
        }
        return content;
    }
}
