package com.huazheng.project.greenplum.service.impl;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import com.huazheng.project.greenplum.mapper.GPMapper;
import com.huazheng.project.hana.mapper.SapMapper;
import com.huazheng.project.hana.model.Afko;
import com.huazheng.project.hana.model.Afpo;
import com.huazheng.project.hana.model.Aufk;
import com.huazheng.project.hana.model.Bkpf;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.log4j.Log4j2;

@Log4j2
@Service
public class CheckUpdateServiceImpl {

	@Autowired
	private RedisTemplate<String, String> redis1Template;
	
	@Autowired
	private GPMapper gpMapper;
	
	@Autowired
	private SapMapper sapMapper;
	
	public String getErrorInfoFromException(Exception e) {
		try {
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			e.printStackTrace(pw);
			return "\r\n" + sw.toString() + "\r\n";
		} catch (Exception e2) {
			return "bad getErrorInfoFromException";
		}
	}
	
	public void selectAufkCheckByUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Aufk:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Aufk:rowids"));
			Aufk build = Aufk.builder().rowids(rowids).build();
			
			List<Aufk> slist = sapMapper.selectAufkCheckByUpdate(build); // 从源库中按更新时间查询,只更新今天的数据
			if (slist.size() == 0) {
				redis1Template.opsForValue().set("huazheng:checkUpdate:Aufk:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}
			
			slist.forEach(source -> { // 遍历源库中的数据，去目标库中查询数据
				Aufk target = gpMapper.selectAufk(source);
				String operator = "none";
				Long srowids = source.getRowids();
				if (target != null) {
					source.setRowids(null);
					String shash = SecureUtil.md5(JSONUtil.toJsonStr(source)); // 源库中数据的hash结果
					String thash = target.getHashResult(); // 数仓中数据的hash结果
					if (!shash.equals(thash)) { // 如果hash结果不一致
						source.setHashResult(shash);
						// ===============================
						if (source.getErdat() != null && source.getErfzeit() != null) {
							String erdat2 = new StringBuffer(source.getErdat()).insert(4, "-").insert(7, "-").toString();
							String erzet2 = new StringBuffer(source.getErfzeit()).insert(2, ":").insert(5, ":").toString();
							String dateStr = erdat2 + " " + erzet2;
							Date date = DateUtil.parse(dateStr);
							source.setErdat1(date);
							source.setErdat2(date);
						}
						// ===============================
						while (true) {
							try {
								gpMapper.updateAufk(source); // 更新数据到数仓中
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						
						// 级联更新业务
						Afko sAfko = sapMapper.cascadeAfkoByAufk(source); // 级联查询源库afko表
						Afko tAfko = gpMapper.selectAfko(sAfko); // 查询目标库中afko表
						cascadeAfkoCheckByUpdate(sAfko, tAfko); // 级联更新afko表
						
						// 级联更新业务
						Afpo sAfpo = sapMapper.cascadeAfpoByAufk(source); // 级联查询源库afko表
						Afpo tAfpo = gpMapper.selectAfpo(sAfpo); // 查询目标库中afko表
						cascadeAfpoCheckByUpdate(sAfpo, tAfpo); // 级联更新afko表
						
						ThreadUtil.safeSleep(500);
					}
				}
				
				redis1Template.opsForValue().set("huazheng:checkUpdate:Aufk:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectAufkcheckUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Aufk:rowids", getErrorInfoFromException(e));
		}
	}
	
	// 所属selectAufkCheckByUpdate的级联
	private void cascadeAfkoCheckByUpdate(Afko source, Afko target) {
		if (target != null) { // 目标库有数据
			String shash = SecureUtil.md5(JSONUtil.toJsonStr(source)); // 源库中数据的hash结果
			String thash = target.getHashResult(); // 数仓中数据的hash结果
			if (!shash.equals(thash)) { // 如果hash结果不一致
				source.setHashResult(shash);
				// ===============================
				if (source.getGltrp() != null) {
					String erdat2 = new StringBuffer(source.getGltrp()).insert(4, "-").insert(7, "-").toString();
					Date date = DateUtil.parse(erdat2);
					source.setGltrp1(date);
				}
				if (source.getGstrp() != null) {
					String erdat2 = new StringBuffer(source.getGstrp()).insert(4, "-").insert(7, "-").toString();
					Date date = DateUtil.parse(erdat2);
					source.setGstrp1(date);
				}
				// ===============================
				while (true) {
					try {
						gpMapper.updateAfko(source); // 更新数据到数仓中
						break;
					} catch (RuntimeException e) {
						log.error(e.getMessage());ThreadUtil.safeSleep(500);
					}
				}
				ThreadUtil.safeSleep(500);
			}
		}
	}

	// 所属selectAufkCheckByUpdate的级联
	private void cascadeAfpoCheckByUpdate(Afpo source, Afpo target) {
		if (target != null) {
			String shash = SecureUtil.md5(JSONUtil.toJsonStr(source)); // 源库中数据的hash结果
			String thash = target.getHashResult(); // 数仓中数据的hash结果
			if (!shash.equals(thash)) { // 如果hash结果不一致
				source.setHashResult(shash);
				// ===============================
				// ===============================
				while (true) {
					try {
						gpMapper.updateAfpo(source); // 更新数据到数仓中
						break;
					} catch (RuntimeException e) {
						log.error(e.getMessage());ThreadUtil.safeSleep(500);
					}
				}
				ThreadUtil.safeSleep(500);
			}
		}
	}
	
	public void selectBkpfCheckByUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Bkpf:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Bkpf:rowids"));
			Bkpf build = Bkpf.builder().rowids(rowids).build();
			
			List<Bkpf> slist = sapMapper.selectBkpfCheckByUpdate(build); // 从源库中按更新时间查询,只更新今天的数据
			if (slist.size() == 0) {
				redis1Template.opsForValue().set("huazheng:checkUpdate:Bkpf:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}
			
			slist.forEach(source -> { // 遍历源库中的数据，去目标库中查询数据
				Bkpf target = gpMapper.selectBkpf(source);
				String operator = "none";
				Long srowids = source.getRowids();
				if (target != null) {
					source.setRowids(null);
					String shash = SecureUtil.md5(JSONUtil.toJsonStr(source)); // 源库中数据的hash结果
					String thash = target.getHashResult(); // 数仓中数据的hash结果
					if (!shash.equals(thash)) { // 如果hash结果不一致
						source.setHashResult(shash);
						while (true) {
							try {
								gpMapper.updateBkpf(source); // 更新数据到数仓中
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}
				redis1Template.opsForValue().set("huazheng:checkUpdate:Bkpf:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectBkpfcheckUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Bkpf:rowids", getErrorInfoFromException(e));
		}
	}
	
}
