/**
 * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.modules.serialnum.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.jeeplus.common.utils.DateUtils;
import com.jeeplus.common.utils.IdGen;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.modules.serialnum.exception.SerialGenException;
import com.jeeplus.modules.sys.entity.Office;
import com.jeeplus.modules.sys.entity.User;
import com.jeeplus.modules.sys.service.OfficeService;
import com.jeeplus.modules.sys.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.jeeplus.common.persistence.Page;
import com.jeeplus.common.service.CrudService;
import com.jeeplus.modules.serialnum.entity.SerialNumTpl;
import com.jeeplus.modules.serialnum.dao.SerialNumTplDao;

/**
 * 编号模板Service
 * @author ppt
 * @version 2018-05-16
 */
@Service
@Transactional(readOnly = true)
public class SerialNumTplService extends CrudService<SerialNumTplDao, SerialNumTpl> {

    @Autowired
    private OfficeService officeService;

	public SerialNumTpl get(String id) {
		return super.get(id);
	}
	
	public List<SerialNumTpl> findList(SerialNumTpl serialNumTpl) {
		return super.findList(serialNumTpl);
	}
	
	public Page<SerialNumTpl> findPage(Page<SerialNumTpl> page, SerialNumTpl serialNumTpl) {
        String branchOffice = UserUtils.getSelectOffice().getBranchOffice();
        if(StringUtils.isNotBlank(branchOffice)){
            Office office = officeService.get(branchOffice);
            serialNumTpl.setCompany(office);
        }else {
            serialNumTpl.setCompany(UserUtils.getSelectCompany());
        }
		return super.findPage(page, serialNumTpl);
	}
	
	@Transactional(readOnly = false)
	public void save(SerialNumTpl serialNumTpl) {
	    if (StringUtils.isBlank(serialNumTpl.getYearBuilt())) {
            serialNumTpl.setYearBuilt(DateUtils.formatDate(new Date(), "yyyy"));
        }
		super.save(serialNumTpl);
	}

	@Transactional(readOnly = false)
	public int edit(SerialNumTpl serialNumTpl) {
        serialNumTpl.preUpdate();
        return dao.update(serialNumTpl);
    }
	
	@Transactional(readOnly = false)
	public void delete(SerialNumTpl serialNumTpl) {
		super.delete(serialNumTpl);
	}

	@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW)
	public String genSerialNum(Office company, String bizCode) throws SerialGenException {
        long ts0 = System.currentTimeMillis();
		try {
            String branchOffice = UserUtils.getSelectOffice().getBranchOffice();
            if(StringUtils.isNotBlank(branchOffice)){
                company = officeService.get(branchOffice);
            }
            if (company==null||StringUtils.isBlank(company.getId())){
                throw new Exception("生成编号失败，公司信息不能为空");
            }
            Office office = officeService.get(company.getId());
            if (StringUtils.isBlank(bizCode)){
                throw new Exception("生成编号失败，业务类型不能为空");
            }

			SerialNumTpl numTpl = this.querySerialTpl(office, bizCode);
			if (numTpl==null){
                SerialNumTpl serialNumTpl = dao.queryByComAndBizCode("0", bizCode);
                serialNumTpl.setCompany(company);
                serialNumTpl.setSerialNum(0);
                serialNumTpl.setId("");
                serialNumTpl.setCreateBy(new User(UserUtils.getSelectCompany().getMaster()));
                serialNumTpl.setId(IdGen.uuid());
                dao.insert(serialNumTpl);
                numTpl = serialNumTpl;
            }
			if (numTpl==null){
                throw new Exception("生成编号失败，请先设置相关业务编号模板");
            }
            if ("0".equals(office.getParent().getId()))office.setParent(null);
            String year = DateUtils.formatDate(new Date(), "yyyy");
			if(!year.equals(numTpl.getYearBuilt())){
				//新年，重置SerialNum
				dao.resetSerialNum(numTpl.getId(),numTpl.getYearBuilt(),year);
			}
            Map<String, String> map = new HashMap<>();
			String serialTpl = numTpl.getSerialTpl();
			int i =dao.updateSerialNum(numTpl);
            long t2 = System.currentTimeMillis();
            logger.info("生成{}编号耗时：{}ms",bizCode,System.currentTimeMillis()-ts0);
            if (i!=1){
                throw new Exception("生成编号失败，请稍后重试");
            }
			numTpl=dao.get(numTpl.getId());
			String num = String.valueOf(numTpl.getSerialNum());
			StringBuffer sb = new StringBuffer();
			for(int x = 0; x < (numTpl.getSerialNumLen() - num.length()); x++) {
                sb.append("0");
            }
			sb.append(num);
            /*map.put("spnm",office.getParent()==null?(office.getSimpleName()==null?"":office.getSimpleName()):(office.getParent().getSimpleName()==null?"":office.getParent().getSimpleName()));*/
            String companyShortname = UserUtils.getSysParam("company_shortname", UserUtils.getUser());
            map.put("spnm",StringUtils.isBlank(companyShortname)?"":companyShortname);
            /*map.put("brspnm",office.getBranchSimpleName()==null?"":office.getBranchSimpleName());*/
            String branchShortname = UserUtils.getSysParam("branch_shortname", UserUtils.getUser());
            map.put("brspnm", StringUtils.isBlank(branchShortname)?"":branchShortname);
			map.put("year",year);
			map.put("serialNum",sb.toString());
			String serNum = StringUtils.renderString(serialTpl, map);
			return serNum;
		} catch (Exception e) {
			throw  new SerialGenException(e.getMessage());
		}finally {
		    logger.info("生成{}模板耗时：{}ms",bizCode,System.currentTimeMillis()-ts0);
        }
	}

    private SerialNumTpl querySerialTpl(Office company, String bizCode) {
        SerialNumTpl numTpl = dao.queryByComAndBizCode(company.getId(), bizCode);
        if (numTpl==null&&company.getParent()!=null&&company.getParent().getId()!=null&&!"0".equals(company.getParent().getId())){
            numTpl = this.querySerialTpl(company.getParent(),bizCode);
        }
        return numTpl;
    }

}