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

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.apache.commons.lang3.StringUtils;
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 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.finance.main.dao.CwBdGlorgbookMapper;
import com.dhcc.finance.main.dao.CwHsGlorgbookMapper;
import com.dhcc.finance.main.dao.CwHsOutcwBalanceMapper;
import com.dhcc.finance.main.dao.CwHsOutcwVoucherMapper;
import com.dhcc.finance.main.dao.CwHsOutcwVouchersMapper;
import com.dhcc.finance.main.dao.CwHsOutcwZqxxMapper;
import com.dhcc.finance.main.dao.CwTjkOutcwVoucherMapper;
import com.dhcc.finance.main.dao.Oracle.TjkOutcwBalanceMapper;
import com.dhcc.finance.main.dao.Oracle.TjkOutcwVoucherMapper;
import com.dhcc.finance.main.dao.Oracle.TjkOutcwVouchersMapper;
import com.dhcc.finance.main.dao.Oracle.TjkOutcwZqxxMapper;
import com.dhcc.finance.main.domain.CwBdGlorgbook;
import com.dhcc.finance.main.domain.CwHsGlorgbook;
import com.dhcc.finance.main.domain.CwHsOutcwBalance;
import com.dhcc.finance.main.domain.CwHsOutcwVoucher;
import com.dhcc.finance.main.domain.CwHsOutcwVouchers;
import com.dhcc.finance.main.domain.CwHsOutcwZqxx;
import com.dhcc.finance.main.service.CwTjkOutcwVoucherService;
import com.dhcc.finance.util.FinanceDateUtil;
import com.dhcc.finance.util.MetaDataUtil;

import brave.Tracer;
@Service
public class CwTjkOutcwVoucherServiceImpl implements CwTjkOutcwVoucherService{
	@Autowired
	private Tracer tracer;
	@Autowired
	CwTjkOutcwVoucherMapper cwTjkOutcwVoucherMapper;
	
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	// 初始化数据
	private static final int SIZE = 500;//每次最大插入500条
	
	@Autowired
	TjkOutcwBalanceMapper  tjkOutcwBalanceMapper;// 估值余额表
	
	@Autowired
	TjkOutcwVoucherMapper tjkOutcwVoucherMapper;// 估值凭证表
	
	@Autowired
	TjkOutcwVouchersMapper tjkOutcwVouchersMapper;// 估值分录表
	
	@Autowired
	TjkOutcwZqxxMapper tjkOutcwZqxxMapper;// 估值证券信息表
	
	@Autowired
	CwHsOutcwBalanceMapper cwHsOutcwBalanceMapper;// 财务对应估值余额表
	
	@Autowired
	CwHsOutcwVoucherMapper cwHsOutcwVoucherMapper;// 财务对应估值凭证表
	
	@Autowired
	CwHsOutcwVouchersMapper cwHsOutcwVouchersMapper;// 财务对应估值分录表
	
	@Autowired
	CwHsOutcwZqxxMapper cwHsOutcwZqxxMapper;// 财务对应估值证券信息表
	
	@Autowired
	CwHsGlorgbookMapper cwHsGlorgbookMapper;// 	财务估值账套对照表
	
	@Autowired
	CwBdGlorgbookMapper cwBdGlorgbookMapper;
	
//	 @Autowired
//	 private CuratorFramework curatorFramework;

	 //@Value("${curator.lockPath}")
	// private String lockPath;// 锁路径
	 
	 
	// private static RedisTemplate<String, Object> redisTemplate;
//	  @Resource
//	  RedisTemplate<String, Object> redisTemplate;

	 
	 
	 
	/*
	 * (非 Javadoc)  
	 * <p>Title: importCwTjkOutcwVoucherWebInfo</p>  
	 * <p>Description:  凭证数据导入</p>
	 * @return  
	 * @see com.dhcc.finance.main.service.CwTjkOutcwVoucherService#importCwTjkOutcwVoucherWebInfo()    
	 * @author huangpeng
	 * @date 2019年7月23日 下午5:23:32
	 * @修改日志：
	 */
	@Override
  //  @Transactional(rollbackFor = Exception.class)
	public RestfulResponse<Object, CurrencyMeta> insertVoucherAndDetailInfo(List<CwHsGlorgbook> list, String beginDate, String endDate,Boolean isCheck){
	    // 方法中会先删除数据后新增，同时操作会出现锁表情况，所以加锁
	    // 加锁，先判断缓存中状态是否为0，为1，则不执行，为0执行方法，执行时将缓存中状态为1，执行结束后状态为0 ，
	    if("1".equals(stringRedisTemplate.opsForValue().get("state"))) {
            return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.SYNCHRONIZATION_FAIL.message(),
                    MetaDataUtil.getMeta(tracer, FinanceStatusCode.SYNCHRONIZATION_FAIL));
        }
	    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,FinanceStatusCode.USER_INFO_NOTFOUND.message(),
                    MetaDataUtil.getMeta(tracer, FinanceStatusCode.USER_INFO_NOTFOUND));
        }
        for (CwHsGlorgbook cwHsGlorgbook : list) {
            List<String> ztList =new ArrayList<String>();//由于DfCompany中含有逗号隔开的编号，所以需要处理
            if(StringUtils.contains(cwHsGlorgbook.getDfCompany(), ",")) {
                String[] split = cwHsGlorgbook.getDfCompany().split(",");
                for (String string : split) {
                    ztList.add(string);
                }
            }else {
                ztList.add(cwHsGlorgbook.getDfCompany());
            }
            Map<String, Object> map = new HashMap<>();
            map.put("ztList", ztList);
            map.put("list", list);
            map.put("beginDate", beginDate);
            map.put("endDate", endDate);
            map.put("glorgbookCode", cwHsGlorgbook.getGlorgbookCode());
            map.put("userId", sysUserInfo.getUserId());
            CwBdGlorgbook cwBdGlorgbook = cwBdGlorgbookMapper.selectByPrimaryKey(cwHsGlorgbook.getGlorgbookCode());
            if (cwBdGlorgbook == null) {
                return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.GLORGBOOK_MISMATCH.message(),
                        MetaDataUtil.getMeta(tracer, FinanceStatusCode.GLORGBOOK_MISMATCH));
            }
            // 是否需要校验已经迁移过
            if (!isCheck) {
                long countExistThisBatch = cwTjkOutcwVoucherMapper.countExistThisBatch(cwBdGlorgbook.getPkGlorgbook(), cwBdGlorgbook.getPkCurrperiod(), beginDate, endDate);
                if (countExistThisBatch != 0) {
                    return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.BATCHNO_ISEXIST.message(),SysConstants.CODE.FAIL,
                            MetaDataUtil.getMeta(tracer, FinanceStatusCode.BATCHNO_ISEXIST));
                }
            }
            
            // 导入估值系统数据
            boolean initData = initData(map);
            if (!initData) {
                return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.VALUATION_IMPORT_FAILED.message(),MetaDataUtil.getMeta(tracer,FinanceStatusCode.VALUATION_IMPORT_FAILED));
            }
            String zqnms= cwHsOutcwZqxxMapper.selectZqnmInfo();
            if(StringUtils.isNotBlank(zqnms)) {
                return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.ZQDM_NOT_SYNCHRONIZATION.message()+","+zqnms,
                        MetaDataUtil.getMeta(tracer, FinanceStatusCode.ZQDM_NOT_SYNCHRONIZATION));
            }
            //校验：从表的科目是否都在科目关系表存在
            String res = cwTjkOutcwVoucherMapper.selectExistSubjectCount(map);
            if(StringUtils.isNotBlank(res)) {
                return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.SUBJECT_NOT_EXISTS.message()+","+res,
                        MetaDataUtil.getMeta(tracer, FinanceStatusCode.SUBJECT_NOT_EXISTS));
                }
            // 查询科目是否末级
            String selectIsFinalstage = cwTjkOutcwVoucherMapper.selectIsFinalstage(map);
            if(StringUtils.isNotBlank(selectIsFinalstage)) {
                return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.IS_NOT_FINALSTAGE.message()+","+selectIsFinalstage,
                        MetaDataUtil.getMeta(tracer, FinanceStatusCode.IS_NOT_FINALSTAGE));
                }
            // 如果在该账套的当前期间内,就直接用估值系统日期，不在用当前启用期间
            if (!beginDate.startsWith(cwBdGlorgbook.getPkCurrperiod())  || !endDate.startsWith(cwBdGlorgbook.getPkCurrperiod())) {
                map.put("newPreparedate", FinanceDateUtil.getMonthFirstDayDate(cwBdGlorgbook.getPkCurrperiod()));
            }
            map.put("period", cwBdGlorgbook.getPkCurrperiod());
            // 先删除辅助再删分录再删凭证，先插入凭证再插入分录再插入辅助 ，顺序不能乱
            cwTjkOutcwVoucherMapper.deleteForFreevalue(map);
            cwTjkOutcwVoucherMapper.deleteForDetail(map);
            cwTjkOutcwVoucherMapper.deleteForVoucher(map);
            
            cwTjkOutcwVoucherMapper.insertVoucherMainInfo(map);//导入主表
            cwTjkOutcwVoucherMapper.insertDetailSideInfo(map);//导入从表
            cwTjkOutcwVoucherMapper.insertForFreevalue(map);//导入辅助项
            // 做记录
            CwHsGlorgbook newData = new CwHsGlorgbook();
            newData.setId(cwHsGlorgbook.getId());
            newData.setStartDate(beginDate);
            newData.setEndDate(endDate);
            newData.setInputMan(sysUserInfo.getUserId());
            newData.setInputTime(new Date());
            newData.setLastDate(endDate);
            cwHsGlorgbookMapper.updateByPrimaryKeySelective(newData);
        }
        return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
    }
	/**
	 * 功能描述：初始化数据
	 * @param map
	 * @return boolean
	 * @author dml
	 * @date 2019年10月16日 下午9:18:37
	 * @修改日志：
	 */
	private boolean initData(Map<String, Object> map) {
		List<CwHsOutcwVoucher> CwHsOutcwVoucherList = tjkOutcwVoucherMapper.selectAllData(map);
		if (CwHsOutcwVoucherList.size() == 0) {// 如果没有凭证则不需导入
			return false;
		}
		//先删除数据
		cwHsOutcwBalanceMapper.deleteOutcwBalance(map);
		cwHsOutcwVoucherMapper.deleteOutcwVoucher(map);
		cwHsOutcwVouchersMapper.deleteOutcwVouchers(map);
		
		// cwHsOutcwZqxxMapper.deleteCwHsOutcwZqxx();
		

		// 再插入数据
		// 先查询oracle中数据再插入mysql
		List<CwHsOutcwBalance> CwHsOutcwBalanceList = tjkOutcwBalanceMapper.selectAllData(map);
		for (int i = 0; i <= CwHsOutcwBalanceList.size()/SIZE && i*SIZE<CwHsOutcwBalanceList.size(); i++) {
			List<CwHsOutcwBalance> subList = new ArrayList<>();
			if (SIZE*(1+i)<CwHsOutcwBalanceList.size()) {
				subList = CwHsOutcwBalanceList.subList(i*SIZE, SIZE*(1+i));
			}else {
				subList = CwHsOutcwBalanceList.subList(i*SIZE, CwHsOutcwBalanceList.size());
			}
			cwHsOutcwBalanceMapper.insertBeatch(subList);
		}
		

		for (int i = 0; i <= CwHsOutcwVoucherList.size()/SIZE && i*SIZE<CwHsOutcwVoucherList.size(); i++) {
			List<CwHsOutcwVoucher> subList = new ArrayList<>();
			if (SIZE*(1+i)<CwHsOutcwVoucherList.size()) {
				subList = CwHsOutcwVoucherList.subList(i*SIZE, SIZE*(1+i));
			}else {
				subList = CwHsOutcwVoucherList.subList(i*SIZE, CwHsOutcwVoucherList.size());
			}
			cwHsOutcwVoucherMapper.insertBeatch(subList);
		}
		
		List<CwHsOutcwVouchers> CwHsOutcwVouchersList = tjkOutcwVouchersMapper.selectAllData(map);
		for (int i = 0; i <= CwHsOutcwVouchersList.size()/SIZE && i*SIZE<CwHsOutcwVouchersList.size(); i++) {
			List<CwHsOutcwVouchers> subList = new ArrayList<>();
			if (SIZE*(1+i)<CwHsOutcwVouchersList.size()) {
				subList = CwHsOutcwVouchersList.subList(i*SIZE, SIZE*(1+i));
			}else {
				subList = CwHsOutcwVouchersList.subList(i*SIZE, CwHsOutcwVouchersList.size());
			}
			cwHsOutcwVouchersMapper.insertBeatch(subList);
		}
//		List<CwHsOutcwZqxx> CwHsOutcwZqxxList = tjkOutcwZqxxMapper.selectAllData();
//        for (int i = 0; i <= CwHsOutcwZqxxList.size()/SIZE && i*SIZE<CwHsOutcwZqxxList.size(); i++) {
//            List<CwHsOutcwZqxx> subList = new ArrayList<>();
//            if (SIZE*(1+i)<CwHsOutcwZqxxList.size()) {
//                subList = CwHsOutcwZqxxList.subList(i*SIZE, SIZE*(1+i));
//            }else {
//                subList = CwHsOutcwZqxxList.subList(i*SIZE, CwHsOutcwZqxxList.size());
//            }
//            cwHsOutcwZqxxMapper.insertBeatch(subList);
//        }

		return true;
	}
	
	/**
     * 功能描述：同步证券代码信息
     * @return RestfulResponse<Object,CurrencyMeta>
     * @author likai
     * @date 2020年7月22日 下午2:55:25
     * @修改日志：
     */
    @Transactional(rollbackFor = Exception.class)
	public RestfulResponse<Object, CurrencyMeta> insertCwHsOutcwZqxx(){
      
       if(stringRedisTemplate.opsForValue().get("state") == null || "".equals(stringRedisTemplate.opsForValue().get("state"))) {
           stringRedisTemplate.opsForValue().set("state", "1");
           try {
               cwHsOutcwZqxxMapper.deleteCwHsOutcwZqxx();
               List<CwHsOutcwZqxx> CwHsOutcwZqxxList = tjkOutcwZqxxMapper.selectAllData();
               for (int i = 0; i <= CwHsOutcwZqxxList.size()/SIZE && i*SIZE<CwHsOutcwZqxxList.size(); i++) {
                   List<CwHsOutcwZqxx> subList = new ArrayList<>();
                   if (SIZE*(1+i)<CwHsOutcwZqxxList.size()) {
                       subList = CwHsOutcwZqxxList.subList(i*SIZE, SIZE*(1+i));
                   }else {
                       subList = CwHsOutcwZqxxList.subList(i*SIZE, CwHsOutcwZqxxList.size());
                   }
                   cwHsOutcwZqxxMapper.insertBeatch(subList);
               }
           }catch(Exception e) {
               return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,
                       SysStatusCode.SERVER_UNKNOWN_ERROR.message(),
                       MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
           } finally {
               stringRedisTemplate.delete("state");
           }           
	   } else {
           return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,FinanceStatusCode.SYNCHRONIZATION_FAIL.message()
                   ,MetaDataUtil.getMeta(tracer,FinanceStatusCode.SYNCHRONIZATION_FAIL));
	   }
        return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,MetaDataUtil.getMeta(tracer,SysStatusCode.OPERATION_SUCCESS));
	    
	}

}
