package com.dhcc.finance.main.service.impl;

import brave.Tracer;
import com.dhcc.common.Shift;
import com.dhcc.common.constant.FinanceStatusCode;
import com.dhcc.common.constant.SysConstants;
import com.dhcc.common.constant.SysStatusCode;
import com.dhcc.common.model.CurrencyMeta;
import com.dhcc.common.model.SysUserInfo;
import com.dhcc.common.model.response.RestfulResponse;
import com.dhcc.common.util.CacheDataUtil;
import com.dhcc.common.util.SnowflakeIdWorker;
import com.dhcc.finance.constant.FinanceDictConsts;
import com.dhcc.finance.main.dao.*;
import com.dhcc.finance.main.domain.*;
import com.dhcc.finance.main.domain.CwGlDetailExample.Criteria;
import com.dhcc.finance.main.model.CwGlDetailLike;
import com.dhcc.finance.main.model.CwGlVoucherAndDetailWeb;
import com.dhcc.finance.main.service.CwGlDetailService;
import com.dhcc.finance.util.FinanceDateUtil;
import com.dhcc.finance.util.MetaDataUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 功能描述：凭证分录信息实现
 * @author dml
 * @date 2019年3月28日 下午7:25:07
 * @修改日志：
 */
@Slf4j
@Service
public class CwGlDetailServiceImpl implements CwGlDetailService{
	
	@Autowired
	private Tracer tracer;
	
	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Autowired
	CwGlDetailMapper cwGlDetailMapper;
	
	@Autowired
	CwGlVouchermaxnoMapper cwGlVouchermaxnoMapper;//最大凭证号

	@Autowired
	CwBdGlorgbookMapper cwBdGlorgbookMapper;//账套表
	
	@Autowired
	CwGlVoucherMapper cwGlVoucherMapper;//凭证信息
	
	@Autowired
	CwBdRecordSerialMapper cwBdRecordSerialMapper;//记录流水凭证表
	/*
	 * (非 Javadoc)  
	 * Title: searchCwGlDetailAllData 
	 * Description:查询凭证分录信息
	 * @param pageNum
	 * @param pageSize
	 * @param navigatePages
	 * @return  
	 * @see com.dhcc.finance.main.service.CwGlDetailService#searchCwGlDetailAllData(int, int, int)    
	 * @author dml
	 * @date 2019年3月28日 下午7:31:25
	 * @修改日志：
	 */
	@Override
	public RestfulResponse<PageInfo<CwGlDetail>, CurrencyMeta> searchCwGlDetailAllData(int pageNum, int pageSize,
			int navigatePages) {
		PageHelper.startPage(pageNum, pageSize);
		CwGlDetailExample cwGlDetailExample = new CwGlDetailExample();
		Criteria createCriteria = cwGlDetailExample.createCriteria();
		createCriteria.andUseStateEqualTo(FinanceDictConsts.Syzt.EFFECTIVE);
		List<CwGlDetail> listCwGlDetail = cwGlDetailMapper.selectByExample(cwGlDetailExample);
		PageInfo<CwGlDetail> pageInfo = new PageInfo<>(listCwGlDetail, navigatePages);
		return new RestfulResponse<PageInfo<CwGlDetail>, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,pageInfo,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	}

	/*
	 * (非 Javadoc)  
	 * Title: addCwGlDetail 
	 * Description:新增凭证分录信息
	 * @param cwGlDetail
	 * @return  
	 * @see com.dhcc.finance.main.service.CwGlDetailService#addCwGlDetail(com.dhcc.finance.main.domain.CwGlDetail)    
	 * @author dml
	 * @date 2019年3月28日 下午7:31:40
	 * @修改日志：
	 */
	@Override
	public RestfulResponse<Object, CurrencyMeta> addCwGlDetail(CwGlDetail cwGlDetail) {
		SysUserInfo sysUserInfo = CacheDataUtil.<SysUserInfo>getCacheBean(stringRedisTemplate, SysConstants.REDIS_KEY_PREFIX.SYS_USER_INFO, SysUserInfo.class);
		if (sysUserInfo != null) {
			cwGlDetail.setCreateUser(sysUserInfo.getUserId());
		}
		cwGlDetail.setCreateTime(new Date());
		cwGlDetail.setUseState(FinanceDictConsts.Syzt.EFFECTIVE);
		cwGlDetail.setPkDetail(SnowflakeIdWorker.getInstance().nextIdString());
		cwGlDetailMapper.insert(cwGlDetail);
		return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	}

	/*
	 * (非 Javadoc)  
	 * Title: updateCwGlDetailByPk 
	 * Description:修改凭证分录信息
	 * @param cwGlDetail
	 * @return  
	 * @see com.dhcc.finance.main.service.CwGlDetailService#updateCwGlDetailByPk(com.dhcc.finance.main.domain.CwGlDetail)    
	 * @author dml
	 * @date 2019年3月28日 下午7:32:00
	 * @修改日志：
	 */
	@Override
	public RestfulResponse<Object, CurrencyMeta> updateCwGlDetailByPk(CwGlDetail cwGlDetail) {
		SysUserInfo sysUserInfo = CacheDataUtil.<SysUserInfo>getCacheBean(stringRedisTemplate, SysConstants.REDIS_KEY_PREFIX.SYS_USER_INFO, SysUserInfo.class);
		if (sysUserInfo != null) {
			cwGlDetail.setUpdateUser(sysUserInfo.getUserId());
		}
		cwGlDetail.setUpdateTime(new Date());
		cwGlDetailMapper.updateByPrimaryKeySelective(cwGlDetail);
		return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	}

	/*
	 * (非 Javadoc)  
	 * Title: deleteCwGlDetailByPk 
	 * Description:逻辑删除凭证分录信息
	 * @param pkDetail
	 * @return  
	 * @see com.dhcc.finance.main.service.CwGlDetailService#deleteCwGlDetailByPk(java.lang.String)    
	 * @author dml
	 * @date 2019年3月28日 下午7:32:12
	 * @修改日志：
	 */
	@Override
	public RestfulResponse<Object, CurrencyMeta> deleteCwGlDetailByPk(String pkDetail) {
		CwGlDetail cwGlDetail = new CwGlDetail();
		SysUserInfo sysUserInfo = CacheDataUtil.<SysUserInfo>getCacheBean(stringRedisTemplate, SysConstants.REDIS_KEY_PREFIX.SYS_USER_INFO, SysUserInfo.class);
		if (sysUserInfo != null) {
			cwGlDetail.setUpdateUser(sysUserInfo.getUserId());
		}
		cwGlDetail.setUpdateTime(new Date());
		cwGlDetail.setUseState(FinanceDictConsts.Syzt.INVALID);
		cwGlDetail.setPkDetail(pkDetail);
		cwGlDetailMapper.updateByPrimaryKeySelective(cwGlDetail);
		return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	}
	
	/*
	 * (非 Javadoc)  
	 * <p>Title: searchCwGlVoucherAndDetailWeb</p>  
	 * <p>Description:  获取恢复分录查询</p>
	 * @param pageNum
	 * @param pageSize
	 * @param navigatePages
	 * @param cwGlVoucherAndDetailWeb
	 * @return  
	 * @see com.dhcc.finance.main.service.CwGlDetailService#searchCwGlVoucherAndDetailWeb(int, int, int, com.dhcc.finance.main.model.CwGlVoucherAndDetailWeb)    
	 * @author huangpeng
	 * @date 2019年12月13日 上午11:08:45
	 * @修改日志：
	 */
	@Override
	public RestfulResponse<PageInfo<CwGlVoucherAndDetailWeb>, CurrencyMeta> searchCwGlVoucherAndDetailWeb(int pageNum,
			int pageSize, int navigatePages, CwGlDetailLike cwGlDetailLike) {
		PageHelper.startPage(pageNum, pageSize);
		List<CwGlVoucherAndDetailWeb> listCwGlDetail = cwGlDetailMapper.searchCwGlVoucherAndDetailWeb(cwGlDetailLike);
		PageInfo<CwGlVoucherAndDetailWeb> pageInfo = new PageInfo<>(listCwGlDetail, navigatePages);
		return new RestfulResponse<PageInfo<CwGlVoucherAndDetailWeb>, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,pageInfo,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	}
	/*
	 * (非 Javadoc)  
	 * <p>Title: updateCwGlVoucherAndDetailWebForBatch</p>  
	 * <p>Description: 批量恢复分录信息</p>
	 * @param cwGlVoucherAndDetailWeb
	 * @return  
	 * @see com.dhcc.finance.main.service.CwGlDetailService#updateCwGlVoucherAndDetailWebForBatch(java.util.List)    
	 * @author huangpeng
	 * @date 2019年12月13日 下午2:57:15
	 * @修改日志：
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public RestfulResponse<Object, CurrencyMeta> updateCwGlVoucherAndDetailWebForBatch(
			List<CwGlVoucherAndDetailWeb> detailList) {
		SysUserInfo sysUserInfo = CacheDataUtil.<SysUserInfo>getCacheBean(stringRedisTemplate, SysConstants.REDIS_KEY_PREFIX.SYS_USER_INFO, SysUserInfo.class);
		if(sysUserInfo==null) {
			return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,SysStatusCode.USER_LOGOUT_ERROR.message(),MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));

		}
		//去除相同凭证主键list
		List<CwGlVoucherAndDetailWeb> result = new ArrayList<>();
		  for (CwGlVoucherAndDetailWeb cwGlVoucherAndDetailWeb : detailList) {
		   boolean b = result.stream().anyMatch(u -> u.getPkVoucher().equals(cwGlVoucherAndDetailWeb.getPkVoucher()));
		   if (!b) {
		    result.add(cwGlVoucherAndDetailWeb);
		   }
		 }
	
		for (CwGlVoucherAndDetailWeb cwGlVoucherAndDetailWeb : result) {
			String pkGlorgbook = cwGlVoucherAndDetailWeb.getPkGlorgbook();//账套主键
			CwBdGlorgbook cwBdGlorgbook = cwBdGlorgbookMapper.selectByPrimaryKey(pkGlorgbook);//账套信息
			String pkCurrperiod = cwBdGlorgbook.getPkCurrperiod();//当前会计期间
			String period = cwGlVoucherAndDetailWeb.getPeriod();//凭证会计期间
			String pkVoucher = cwGlVoucherAndDetailWeb.getPkVoucher();//凭证主键
			
			if(pkCurrperiod.equals(period)) {//如果恢复的时间跟删除的时间在一个会计期间
				CwGlDetail cwGlDetail = new CwGlDetail();
				cwGlDetail.setUpdateTime(new Date());
				cwGlDetail.setUpdateUser(sysUserInfo.getUserId());
				cwGlDetail.setUseState(FinanceDictConsts.Syzt.EFFECTIVE);
				
				CwGlDetailExample cwGlDetailExample = new CwGlDetailExample();
				Criteria createCriteria = cwGlDetailExample.createCriteria();
				createCriteria.andUseStateEqualTo(FinanceDictConsts.Syzt.INVALID);
				createCriteria.andPkVoucherEqualTo(pkVoucher);
				cwGlDetailMapper.updateByExampleSelective(cwGlDetail, cwGlDetailExample);//直接更新使用状态为0的分录
				//更新凭证主表
				List<CwGlDetail> sumDetail = cwGlDetailMapper.selectByPkVoucher(pkVoucher,FinanceDictConsts.Syzt.EFFECTIVE);
				BigDecimal totaldebit = new BigDecimal("0"),totalcredit = new BigDecimal("0");
				for (CwGlDetail cwGlDetail2 : sumDetail) {
					totaldebit = totaldebit.add(cwGlDetail2.getLocaldebitamount());
					totalcredit = totalcredit.add(cwGlDetail2.getLocalcreditamount());
				}
				CwGlVoucher newVoucher = new CwGlVoucher();
				newVoucher.setTotalcredit(totalcredit);
				newVoucher.setTotaldebit(totaldebit);
				newVoucher.setUpdateTime(new Date());
				newVoucher.setUpdateUser(sysUserInfo.getUserId());
				CwGlVoucherExample cwGlVoucherExample = new CwGlVoucherExample();
				com.dhcc.finance.main.domain.CwGlVoucherExample.Criteria createCriteria2 = cwGlVoucherExample.createCriteria();
				createCriteria2.andPkVoucherEqualTo(pkVoucher);
				createCriteria2.andUseStateEqualTo(FinanceDictConsts.Syzt.EFFECTIVE);
				cwGlVoucherMapper.updateByExampleSelective(newVoucher, cwGlVoucherExample);
			}else {
				SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
				List<CwGlDetail> unDetail = cwGlDetailMapper.selectByPkVoucher(pkVoucher, FinanceDictConsts.Syzt.INVALID);//使用状态为0的分录信息
				// 计算借方合计和贷方合计
				BigDecimal totaldebit = new BigDecimal("0"),totalcredit = new BigDecimal("0");
				for (CwGlDetail cwGlDetail : unDetail) {
					totaldebit = totaldebit.add(cwGlDetail.getLocaldebitamount());
					totalcredit = totalcredit.add(cwGlDetail.getLocalcreditamount());
				}
				// 借贷平衡判断
				if (totaldebit.compareTo(totalcredit) != 0) {
					return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.LOAN_NOT_BALANCE.message(),
							MetaDataUtil.getMeta(tracer, FinanceStatusCode.LOAN_NOT_BALANCE));
				}

				// CwGlVouchermaxno voucherMaxno = cwGlVouchermaxnoMapper.selectGetMaxNo(pkGlorgbook, pkCurrperiod);//得到最大凭证号信息
				CwGlVouchermaxno voucherMaxno = cwGlVouchermaxnoMapper.getVoucherMaxNo(pkGlorgbook, pkCurrperiod);//得到最大凭证号信息
				if(voucherMaxno==null) {
					// 如果查询不到则返回
					return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,cwBdGlorgbook.getName()+FinanceStatusCode.MAXNO_INFO_NOTFOUND.message(),
							MetaDataUtil.getMeta(tracer,FinanceStatusCode.MAXNO_INFO_NOTFOUND));
				}
				String voucherno = Integer.valueOf(voucherMaxno.getMaxno())+1+"";
				String newPkVoucher = SnowflakeIdWorker.getInstance().nextIdString();//新增凭证主键
				
				CwGlVoucher cwGlVoucher = cwGlVoucherMapper.selectByPrimaryKey(pkVoucher);//凭证信息
				CwGlVoucher newVoucher = new CwGlVoucher();
				BeanUtils.copyProperties(cwGlVoucher, newVoucher);

				newVoucher.setPkVoucher(newPkVoucher);
				newVoucher.setVoucherno(voucherno);//新凭证号
				newVoucher.setPeriod(pkCurrperiod);
				newVoucher.setVouchertype(FinanceDictConsts.Cwpzzt.YZD);//已制单
				String preDate = FinanceDateUtil.getMonthFirstDayDate(pkCurrperiod);//得到当前会计期间第一天
				//分录实体
				CwGlDetail cwGlDetail = new CwGlDetail();
				try {
					Date date = sdf1.parse(preDate);
					cwGlDetail.setPreparedate(date);
					newVoucher.setPreparedate(date);
				} catch (ParseException e) {
					log.error("日期转换失败>>>>>>>>",e);
					e.printStackTrace();
				}
				newVoucher.setPkPrepared(sysUserInfo.getUserId());
				newVoucher.setIsaudit(FinanceDictConsts.SF.no);
				newVoucher.setIssign(FinanceDictConsts.SF.no);
				newVoucher.setPkAudit(null);
				newVoucher.setPkSign(null);
				newVoucher.setAuditdate(null);
				newVoucher.setSigndate(null);
				newVoucher.setUpdateTime(null);
				newVoucher.setUpdateUser(null);
				newVoucher.setCreateTime(new Date());
				newVoucher.setCreateUser(sysUserInfo.getUserId());
				newVoucher.setTotalcredit(totalcredit);
				newVoucher.setTotaldebit(totaldebit);
				

				cwGlDetail.setUpdateTime(new Date());
				cwGlDetail.setPkVoucher(newPkVoucher);
				cwGlDetail.setUpdateUser(sysUserInfo.getUserId());
				cwGlDetail.setUseState(FinanceDictConsts.Syzt.EFFECTIVE);
				
				CwGlDetailExample cwGlDetailExample = new CwGlDetailExample();
				Criteria createCriteria = cwGlDetailExample.createCriteria();
				createCriteria.andUseStateEqualTo(FinanceDictConsts.Syzt.INVALID);
				createCriteria.andPkVoucherEqualTo(cwGlVoucherAndDetailWeb.getPkVoucher());
				int res1 = cwGlDetailMapper.updateByExampleSelective(cwGlDetail, cwGlDetailExample);//更新使用状态为0的分录
				
				int res2 = cwGlVoucherMapper.insert(newVoucher);//新增凭证主表
				//更新最大凭证号表
				CwGlVouchermaxno cwGlVouchermaxno = new CwGlVouchermaxno();
				cwGlVouchermaxno.setMaxno(voucherno);
				cwGlVouchermaxno.setUpdateUser(sysUserInfo.getUserId());
				cwGlVouchermaxno.setUpdateTime(new Date());
				CwGlVouchermaxnoExample cwGlVouchermaxnoExample = new CwGlVouchermaxnoExample();
				com.dhcc.finance.main.domain.CwGlVouchermaxnoExample.Criteria criteria = cwGlVouchermaxnoExample.createCriteria();
				criteria.andPkGlorgbookEqualTo(pkGlorgbook);
				criteria.andPeriodEqualTo(pkCurrperiod);
				criteria.andUseStateEqualTo(FinanceDictConsts.Syzt.EFFECTIVE);
				int res3 = cwGlVouchermaxnoMapper.updateByExampleSelective(cwGlVouchermaxno, cwGlVouchermaxnoExample);//更新最大凭证号信息

				CwBdRecordSerialExample cwBdRecordSerialExample = new CwBdRecordSerialExample();
				com.dhcc.finance.main.domain.CwBdRecordSerialExample.Criteria createCriteria2 = cwBdRecordSerialExample.createCriteria();
				createCriteria2.andUseStateEqualTo(FinanceDictConsts.Syzt.EFFECTIVE);
				createCriteria2.andPkVoucherLike("%"+pkVoucher+"%");
				List<CwBdRecordSerial> serialVoucher = cwBdRecordSerialMapper.selectByExample(cwBdRecordSerialExample);
				if(serialVoucher.size()>0) {
					String serPkVoucher=serialVoucher.get(0).getPkVoucher()+","+newPkVoucher;//追加流水凭证信息
					Map<String,Object> map =new HashMap<String, Object>();
					map.put("pkVoucher", serPkVoucher);
					map.put("updateTime", new Date());
					map.put("updateUser", sysUserInfo.getUserId());
					map.put("list", serialVoucher);
					cwBdRecordSerialMapper.updateCwBdRecordSerialForRevse(map);//更新流水记录表
				}
				if (res1*res2*res3 == 0) {
					log.info(">>>>更新恢复分录信息失败");
					Shift.fatalThrow(SysStatusCode.OPERATION_FAIL);
				}
			}
		}
		return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,
				SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	}





}
