package com.yifu.cloud.plus.v1.ekp.config;

import com.google.common.collect.Range;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Component
public class OTAStrategyShardingAlgorithm implements StandardShardingAlgorithm<LocalDateTime> {

	private static final DateTimeFormatter yyyy = DateTimeFormatter.ofPattern("yyyy");

	/**
	 * 数据插入
	 * @param collection
	 * @param preciseShardingValue
	 * @Author hyc
	 * @Date 2022-07-21
	 * @return
	 */
	@Override
	public String doSharding(Collection<String> collection, PreciseShardingValue<LocalDateTime> preciseShardingValue) {

		LocalDateTime value = preciseShardingValue.getValue();
		String tableSuffix = value.format(yyyy);
		String logicTableName = preciseShardingValue.getLogicTableName();
		String table = logicTableName.concat("_").concat(tableSuffix);
		return collection.stream().filter(s -> s.equals(table)).findFirst().orElseThrow(() -> new RuntimeException("逻辑分表不存在"));
	}

	/**
	 * 【范围】数据查询
	 * @param collection
	 * @param rangeShardingValue
	 * @Author hyc
	 * @Date 2022-07-21
	 * @return
	 */
	@Override
	public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<LocalDateTime> rangeShardingValue) {
		// 逻辑表名
		String logicTableName = rangeShardingValue.getLogicTableName();

		// 范围参数
		Range<LocalDateTime> valueRange = rangeShardingValue.getValueRange();
		Set<String> queryRangeTables = extracted(logicTableName, valueRange.lowerEndpoint(), valueRange.upperEndpoint());
		ArrayList<String> tables = new ArrayList<>(collection);
		tables.retainAll(queryRangeTables);
		return tables;
	}

	/**
	 * 根据范围计算表名
	 * @param logicTableName 逻辑表明
	 * @param lowerEndpoint 范围起点
	 * @param upperEndpoint 范围终端
	 * @Author hyc
	 * @Date 2022-07-21
	 * @return 物理表名集合
	 */
	private Set<String> extracted(String logicTableName, LocalDateTime lowerEndpoint, LocalDateTime upperEndpoint) {
		Set<String> rangeTable = new HashSet<>();
		while (lowerEndpoint.isBefore(upperEndpoint)) {
			String str = getTableNameByDate(lowerEndpoint, logicTableName);
			rangeTable.add(str);
			lowerEndpoint = lowerEndpoint.plusYears(1);
		}
		// 获取物理表明
		String tableName = getTableNameByDate(upperEndpoint, logicTableName);
		rangeTable.add(tableName);
		return rangeTable;
	}

	/**
	 * 根据日期获取表明
	 * @param dateTime 日期
	 * @param logicTableName 逻辑表名
	 * @Author hyc
	 * @Date 2022-07-21
	 * @return 物理表名
	 */
	private String getTableNameByDate(LocalDateTime dateTime, String logicTableName) {
		String tableSuffix = dateTime.format(yyyy);
		return logicTableName.concat("_").concat(tableSuffix);
	}

	@Override
	public Properties getProps() {
		return null;
	}

	@Override
	public void init(Properties properties) {

	}
}
