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

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.greenplum.utils.SomeUtils;
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 com.huazheng.project.hana.model.Kna1;
import com.huazheng.project.hana.model.Likp;
import com.huazheng.project.hana.model.Lips;
import com.huazheng.project.hana.model.Pa0002;
import com.huazheng.project.hana.model.Vbak;
import com.huazheng.project.hana.model.Vbrk;

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 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);
						}
						String aedat = source.getAedat();
						if ("00000000".equals(aedat)) {
							source.setAedat(null);
						} else {
							Date date = DateUtil.parse(aedat, "yyyyMMdd");
							String format = DateUtil.format(date, "yyyy-MM-dd");
							source.setAedat(format);
						}
						// ===============================
						while (true) {
							try {
								gpMapper.updateAufk(source); // 更新数据到数仓中
								operator = "update";
								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", SomeUtils.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);
						// ===============================
						String aedat = source.getAedat();
						if ("00000000".equals(aedat)) {
							source.setAedat(null);
						} else {
							Date date = DateUtil.parse(aedat, "yyyyMMdd");
							String format = DateUtil.format(date, "yyyy-MM-dd");
							source.setAedat(format);
						}
						String cpudt = source.getCpudt();
						String cputm = source.getCputm();
						if ("00000000".equals(cpudt)) {
							source.setCpudt_cputm(null);
						} else {
							Date date = DateUtil.parse(cpudt+cputm, "yyyyMMddHHmmss");
							source.setCpudt_cputm(date);
						}
						// ===============================
						while (true) {
							try {
								gpMapper.updateBkpf(source); // 更新数据到数仓中
								operator = "update";
								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", SomeUtils.getErrorInfoFromException(e));
		}
	}
	public void selectKna1CheckByUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Kna1:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Kna1:rowids"));
			Kna1 build = Kna1.builder().rowids(rowids).build();
			
			List<Kna1> slist = sapMapper.selectKna1CheckUpdate(build); // 从数仓中查询一组数据
			if (slist.size() == 0) {
				redis1Template.opsForValue().set("huazheng:checkUpdate:Kna1:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}
			
			slist.forEach(target -> { // 遍历要检查的数据，去目标库中查询数据
				Kna1 source = gpMapper.selectKna1(target);
				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);
						// ===============================
						String updat = source.getUpdat();
						if ("00000000".equals(updat)) {
							source.setUpdat(null);
						} else {
							Date date = DateUtil.parse(updat, "yyyyMMdd");
							String format = DateUtil.format(date, "yyyy-MM-dd");
							source.setUpdat(format);
						}
						// ===============================
						while (true) {
							try {
								gpMapper.updateKna1(source); // 更新数据到数仓中
								operator = "update";
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}
				
				redis1Template.opsForValue().set("huazheng:checkUpdate:Kna1:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectKna1checkUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Kna1:rowids", SomeUtils.getErrorInfoFromException(e));
		}
	}
	public void selectLikpCheckUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Likp:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Likp:rowids"));
			Likp build = Likp.builder().rowids(rowids).build();

			List<Likp> slist = sapMapper.selectLikpCheckByUpdate(build); // 从数仓中查询一组数据
			if (slist.size() == 0) { // rowid已完成，则转为由更新时间字段开始同步
				redis1Template.opsForValue().set("huazheng:checkUpdate:Likp:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}

			slist.forEach(source -> { // 遍历要检查的数据
				Likp target = gpMapper.selectLikp(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);
						// ===============================
						String wadat_ist = source.getWadat_ist();
						String lfuhr = source.getLfuhr();
						if ("00000000".equals(wadat_ist)) {
							source.setWadat_ist2lfuhr(null);
						} else {
							Date date = DateUtil.parse(wadat_ist+lfuhr, "yyyyMMddHHmmss");
							source.setWadat_ist2lfuhr(date);
						}
						source.setErdat1(SomeUtils.caDate(source.getErdat())); // 日期00000000格式转换,已处理异常
						source.setWadat_ist1(SomeUtils.caDate(source.getWadat_ist())); // 日期00000000格式转换,已处理异常
						// ===============================
						while (true) {
							try {
								gpMapper.updateLikp(source); // 更新数据到数仓中
								operator = "update";
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}

				redis1Template.opsForValue().set("huazheng:checkUpdate:Likp:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectLikpcheckUpdate --> rowNum:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Likp:rowids", SomeUtils.getErrorInfoFromException(e));
		}
	}
	public void selectLipsCheckUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Lips:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Lips:rowids"));
			Lips build = Lips.builder().rowids(rowids).build();

			List<Lips> slist = sapMapper.selectLipsCheckByUpdate(build); // 从数仓中查询一组数据
			if (slist.size() == 0) { // rowid已完成，则转为由更新时间字段开始同步
				redis1Template.opsForValue().set("huazheng:checkUpdate:Lips:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}

			slist.forEach(source -> { // 遍历要检查的数据
				Lips target = gpMapper.selectLips(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.getErzet() != null) {
							String erdat2 = new StringBuffer(source.getErdat()).insert(4, "-").insert(7, "-").toString();
							String erzet2 = new StringBuffer(source.getErzet()).insert(2, ":").insert(5, ":").toString();
							String dateStr = erdat2 + " " + erzet2;
							Date date = DateUtil.parse(dateStr);
							source.setErdat1(date);
							source.setErdat2(date);
						}
						// ===============================
						while (true) {
							try {
								gpMapper.updateLips(source); // 更新数据到数仓中
								operator = "update";
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}

				redis1Template.opsForValue().set("huazheng:checkUpdate:Lips:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectLipscheckUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Lips:rowids", SomeUtils.getErrorInfoFromException(e));
		}
	}
	public void selectPa0002CheckUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Pa0002:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Pa0002:rowids"));
			Pa0002 build = Pa0002.builder().rowids(rowids).build();

			List<Pa0002> slist = sapMapper.selectPa0002CheckByUpdate(build); // 从数仓中查询一组数据
			if (slist.size() == 0) { // rowid已完成，则转为由更新时间字段开始同步
				redis1Template.opsForValue().set("huazheng:checkUpdate:Pa0002:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}

			slist.forEach(source -> { // 遍历要检查的数据
				Pa0002 target = gpMapper.selectPa0002(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.getEndda() != null) {
							String erdat2 = new StringBuffer(source.getEndda()).insert(4, "-").insert(7, "-").toString();
							Date date = DateUtil.parse(erdat2);
							source.setEndda1(date);
						}
						source.setYeWuYMC(source.getNachn() + source.getVorna());
						// ===============================
						while (true) {
							try {
								gpMapper.updatePa0002(source); // 更新数据到数仓中
								operator = "update";
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}

				redis1Template.opsForValue().set("huazheng:checkUpdate:Pa0002:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectPa0002checkUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Pa0002:rowids", SomeUtils.getErrorInfoFromException(e));
		}
	}
	public void selectVbakCheckUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Vbak:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Vbak:rowids"));
			Vbak build = Vbak.builder().rowids(rowids).build();

			List<Vbak> slist = sapMapper.selectVbakCheckByUpdate(build); // 从数仓中查询一组数据
			if (slist.size() == 0) {
				redis1Template.opsForValue().set("huazheng:checkUpdate:Vbak:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}

			slist.forEach(source -> { // 遍历要检查的数据
				Vbak target = gpMapper.selectVbak(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);
						// ===============================
						source.setAudat1(SomeUtils.caDate(source.getAudat())); // 日期00000000格式转换,已处理异常
						// ===============================
						while (true) {
							try {
								gpMapper.updateVbak(source); // 更新数据到数仓中
								operator = "update";
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}

				redis1Template.opsForValue().set("huazheng:checkUpdate:Vbak:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectVbakcheckUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Vbak:rowids", SomeUtils.getErrorInfoFromException(e));
		}
	}
	public void selectVbrkCheckUpdate() {
		try {
			ValueOperations<String, String> opsForValue = redis1Template.opsForValue();
			opsForValue.setIfAbsent("huazheng:checkUpdate:Vbrk:rowids", "0");
			Long rowids = Long.parseLong(opsForValue.get("huazheng:checkUpdate:Vbrk:rowids"));
			Vbrk build = Vbrk.builder().rowids(rowids).build();

			List<Vbrk> slist = sapMapper.selectVbrkCheckByUpdate(build); // 从数仓中查询一组数据
			if (slist.size() == 0) { // rowid已完成，则转为由更新时间字段开始同步
				redis1Template.opsForValue().set("huazheng:checkUpdate:Vbrk:rowids", "0"); // 计数器复位
				ThreadUtil.sleep(1000); // 没有数据了，休眠一下
			}
			
			slist.forEach(source -> { // 遍历要检查的数据
				Vbrk target = gpMapper.selectVbrk(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.getFkdat() != null) {
							String erdat2 = new StringBuffer(source.getFkdat()).insert(4, "-").insert(7, "-").toString();
							Date date = DateUtil.parse(erdat2);
							source.setFkdat1(date);
						}
						// ===============================
						while (true) {
							try {
								gpMapper.updateVbrk(source); // 更新数据到数仓中
								operator = "update";
								break;
							} catch (RuntimeException e) {
								log.error(e.getMessage());ThreadUtil.safeSleep(500);
							}
						}
						ThreadUtil.safeSleep(500);
					}
				}

				redis1Template.opsForValue().set("huazheng:checkUpdate:Vbrk:rowids", srowids.toString());
				if (!operator.equals("none")) {
					log.info(String.format("selectVbrkcheckUpdate --> rowids:%s, operator:%s", srowids.toString(), operator));
				}
			});
		} catch (Exception e) {
			redis1Template.opsForValue().set("huazheng:checkUpdateError:Vbrk:rowids", SomeUtils.getErrorInfoFromException(e));
		}
	}
	
}
