package cn.gov.customs.wxjy.common.importtool.core;

import cn.gov.customs.wxjy.common.importtool.config.ImportConfig;
import cn.gov.customs.wxjy.common.importtool.model.ImportError;
import cn.gov.customs.wxjy.common.importtool.model.ImportResult;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Slf4j
@Component
public class GenericImportService {

	private static final int DEFAULT_BATCH_SIZE = 1000;

	/**
	 * 优化后的通用导入方法
	 */
	public <S, T> ImportResult<T> importData(List<S> sourceData, String uploadType, ImportConfig<S, T> config) {
		// 验证配置
		config.validateConfig();

		if (CollectionUtils.isEmpty(sourceData)) {
			return ImportResult.failure("导入数据不能为空！");
		}

		try {
			// 根据上传类型选择处理策略
			return "1".equals(uploadType)
				? handleCoverImport(sourceData, config)
				: handleUpsertImport(sourceData, config);
		} catch (Exception e) {
			log.error("导入过程发生严重异常", e);
			// 创建包含全局错误的 ImportResult
			List<ImportError> errors = new ArrayList<>();
			errors.add(new ImportError(0, "导入过程发生系统异常：" + e.getMessage()));

			return ImportResult.<T>builder()
				.success(false)
				.successCount(0)
				.totalCount(sourceData.size())
				.newCount(0)
				.updateCount(0)
				.errors(errors)
				.message("导入失败！系统异常：" + e.getMessage())
				.addList(Collections.emptyList())
				.updateList(Collections.emptyList())
				.build();
		}
	}

	/**
	 * 处理覆盖导入（uploadType = 1）
	 */
	private <S, T> ImportResult<T> handleCoverImport(List<S> sourceData, ImportConfig<S, T> config) {
		List<ImportError> errors = new ArrayList<>();
		List<T> processedData = new ArrayList<>();

		// 1. 数据转换和验证
		processAndValidateData(sourceData, processedData, errors, config);

		// 2. 数据预处理（如拆分）
		int originalProcessedCount = processedData.size();
		if (config.getDataPreProcessor() != null) {
			processedData = config.getDataPreProcessor().preProcess(processedData);
			log.info("覆盖导入数据预处理 - 原始数据{}条，预处理后{}条", originalProcessedCount, processedData.size());
		}

		// 3. 预处理：删除旧数据
		config.getDataProcessor().preBatchSave("1");

		// 4. 批量保存新数据
		int actualSavedCount = batchSaveData(processedData, config, "cover import", errors);

		// 5. 计算原始数据的成功数量
		int originalSuccessCount = calculateOriginalSuccessCount(originalProcessedCount, processedData.size(), actualSavedCount, errors);

		// 对于覆盖导入，所有保存的数据都视为新增
		List<T> savedData = actualSavedCount > 0 ? processedData : Collections.emptyList();

		return buildImportResult(errors, originalSuccessCount, sourceData.size(), originalSuccessCount, 0,savedData, Collections.emptyList());
	}

	/**
	 * 处理更新/新增导入（uploadType = 0）
	 */
	private <S, T> ImportResult<T> handleUpsertImport(List<S> sourceData, ImportConfig<S, T> config) {
		List<ImportError> errors = new ArrayList<>();
		List<T> newDataList = new ArrayList<>();
		List<T> updateDataList = new ArrayList<>();

		// 记录原始数据到处理后数据的映射
		Map<Integer, List<T>> originalToProcessedMap = new HashMap<>();

		// 1. 获取已存在数据
		Set<String> existingKeys = config.getDataProcessor().getExistingKeys();
		Map<String, T> existingDataMap = config.getDataProcessor().getExistingDataMap();

		// 2. 预处理已存在数据
		if (config.getDataPreProcessor() != null) {
			config.getDataPreProcessor().preProcessExistingData(config.getDataProcessor());
		}

		// 3. 处理每条数据并记录映射关系
		for (int i = 0; i < sourceData.size(); i++) {
			S sourceItem = sourceData.get(i);
			int rowIndex = i + 1;

			try {
				// 转换数据
				T targetItem = config.getConverter().convert(sourceItem);

				// 验证数据
				String validationError = validateData(targetItem, rowIndex, config);
				if (StringUtil.isNotEmpty(validationError)) {
					errors.add(new ImportError(rowIndex, validationError));
					continue;
				}

				// 判断是新增还是更新
				String uniqueKey = config.getUniqueKeyGenerator().generateKey(targetItem);
				if (existingKeys.contains(uniqueKey)) {
					T existingItem = existingDataMap.get(uniqueKey);
					if (existingItem != null) {
						T updatedItem = updateExistingItem(existingItem, targetItem, config);
						updateDataList.add(updatedItem);
						// 记录映射关系
						originalToProcessedMap.computeIfAbsent(i, k -> new ArrayList<>()).add(updatedItem);
						log.debug("第{}行数据需要更新，唯一键: {}", rowIndex, uniqueKey);
					} else {
						newDataList.add(targetItem);
						// 记录映射关系
						originalToProcessedMap.computeIfAbsent(i, k -> new ArrayList<>()).add(targetItem);
						log.debug("第{}行数据需要新增（键存在但映射为空），唯一键: {}", rowIndex, uniqueKey);
					}
				} else {
					newDataList.add(targetItem);
					// 记录映射关系
					originalToProcessedMap.computeIfAbsent(i, k -> new ArrayList<>()).add(targetItem);
					log.debug("第{}行数据需要新增，唯一键: {}", rowIndex, uniqueKey);
				}

			} catch (Exception e) {
				log.error("数据处理异常，第{}行: {}", rowIndex, e.getMessage(), e);
				errors.add(new ImportError(rowIndex, "数据处理异常: " + e.getMessage()));
			}
		}

		// 记录预处理前的数量
		int originalNewCount = newDataList.size();
		int originalUpdateCount = updateDataList.size();

		// 4. 数据预处理（如拆分）
		if (config.getDataPreProcessor() != null) {
			newDataList = config.getDataPreProcessor().preProcess(newDataList);
			updateDataList = config.getDataPreProcessor().preProcess(updateDataList);
			log.info("数据预处理 - 新增: {}条→{}条, 更新: {}条→{}条",
				originalNewCount, newDataList.size(), originalUpdateCount, updateDataList.size());
		}

		// 5. 分批处理数据
		int actualNewCount = batchSaveData(newDataList, config, "new data", errors);
		int actualUpdateCount = batchUpdateData(updateDataList, config, "update data", errors);

		// 6. 计算原始数据的成功数量
		int originalSuccessNewCount = calculateOriginalSuccessCount(originalNewCount, newDataList.size(), actualNewCount, errors);
		int originalSuccessUpdateCount = calculateOriginalSuccessCount(originalUpdateCount, updateDataList.size(), actualUpdateCount, errors);
		int originalSuccessCount = originalSuccessNewCount + originalSuccessUpdateCount;

		// 最终统计日志
		log.info("最终导入统计 - 原始数据: {}条, 成功: {}条 (新增: {}, 更新: {}), 失败: {}条, 实际处理: {}条 (新增: {}, 更新: {})",
			sourceData.size(), originalSuccessCount, originalSuccessNewCount, originalSuccessUpdateCount,
			errors.size(), (actualNewCount + actualUpdateCount), actualNewCount, actualUpdateCount);

		// 返回实际保存的数据
		List<T> savedNewData = actualNewCount > 0 ? newDataList : Collections.emptyList();
		List<T> savedUpdateData = actualUpdateCount > 0 ? updateDataList : Collections.emptyList();
		return buildImportResult(errors, originalSuccessCount, sourceData.size(), originalSuccessNewCount, originalSuccessUpdateCount,savedNewData,savedUpdateData);
	}

	/**
	 * 计算原始数据的成功数量
	 */
	private int calculateOriginalSuccessCount(int originalCount, int processedCount, int actualSuccessCount, List<ImportError> errors) {
		if (originalCount == 0) {
			return 0;
		}

		if (processedCount == 0) {
			return 0;
		}

		// 如果没有错误，所有原始数据都成功
		boolean hasBatchError = errors.stream().anyMatch(error -> error.getRowIndex() == 0);
		if (!hasBatchError && actualSuccessCount == processedCount) {
			return originalCount;
		}

		// 计算成功率，然后应用到原始数据
		double successRate = (double) actualSuccessCount / processedCount;
		int calculatedSuccess = (int) Math.round(originalCount * successRate);

		// 确保不超过原始数据数量
		return Math.min(calculatedSuccess, originalCount);
	}

	/**
	 * 处理数据和验证（公共方法）
	 */
	private <S, T> void processAndValidateData(List<S> sourceData, List<T> processedData,
											   List<ImportError> errors, ImportConfig<S, T> config) {
		for (int i = 0; i < sourceData.size(); i++) {
			S sourceItem = sourceData.get(i);
			int rowIndex = i + 1;

			try {
				T targetItem = config.getConverter().convert(sourceItem);
				String validationError = validateData(targetItem, rowIndex, config);

				if (StringUtil.isNotEmpty(validationError)) {
					errors.add(new ImportError(rowIndex, validationError));
				} else {
					processedData.add(targetItem);
				}
			} catch (Exception e) {
				log.error("数据处理异常，第{}行: {}", rowIndex, e.getMessage(), e);
				errors.add(new ImportError(rowIndex, "数据处理异常: " + e.getMessage()));
			}
		}
	}

	/**
	 * 验证数据
	 */
	private <T> String validateData(T data, int rowIndex, ImportConfig<?, T> config) {
		if (config.getValidator() != null) {
			return config.getValidator().validate(data, rowIndex);
		}
		return null;
	}

	/**
	 * 批量保存数据
	 */
	private <T> int batchSaveData(List<T> dataList, ImportConfig<?, T> config, String operation, List<ImportError> errors) {
		if (CollectionUtils.isEmpty(dataList)) {
			return 0;
		}

		int batchSize = config.getBatchSize() > 0 ? config.getBatchSize() : DEFAULT_BATCH_SIZE;
		int totalProcessed = 0;

		for (int i = 0; i < dataList.size(); i += batchSize) {
			int end = Math.min(i + batchSize, dataList.size());
			List<T> batchData = dataList.subList(i, end);

			try {
				config.getDataProcessor().batchSave(batchData);
				totalProcessed += batchData.size();
				log.debug("成功保存{}批次: {}-{}, 共{}条", operation, i + 1, end, batchData.size());
			} catch (Exception e) {
				log.error("{}批次保存失败: {}-{}, 错误: {}", operation, i + 1, end, e.getMessage(), e);
				// 记录批次错误
				errors.add(new ImportError(0, operation + "批次保存失败: " + e.getMessage()));
				// 不再继续处理后续批次
				break;
			}
		}

		log.info("{}处理完成，共{}条数据，成功{}条", operation, dataList.size(), totalProcessed);
		return totalProcessed;
	}

	/**
	 * 批量更新数据
	 */
	private <T> int batchUpdateData(List<T> dataList, ImportConfig<?, T> config, String operation, List<ImportError> errors) {
		if (CollectionUtils.isEmpty(dataList)) {
			return 0;
		}

		int batchSize = config.getBatchSize() > 0 ? config.getBatchSize() : DEFAULT_BATCH_SIZE;
		int totalProcessed = 0;

		for (int i = 0; i < dataList.size(); i += batchSize) {
			int end = Math.min(i + batchSize, dataList.size());
			List<T> batchData = dataList.subList(i, end);

			try {
				config.getDataProcessor().batchUpdate(batchData);
				totalProcessed += batchData.size();
				log.debug("成功更新{}批次: {}-{}, 共{}条", operation, i + 1, end, batchData.size());
			} catch (Exception e) {
				log.error("{}批次更新失败: {}-{}, 错误: {}", operation, i + 1, end, e.getMessage(), e);
				// 记录批次错误
				errors.add(new ImportError(0, operation + "批次更新失败: " + e.getMessage()));
				// 不再继续处理后续批次
				break;
			}
		}

		log.info("{}处理完成，共{}条数据，成功{}条", operation, dataList.size(), totalProcessed);
		return totalProcessed;
	}

	/**
	 * 构建导入结果 - 基于原始数据统计
	 */
	private <T> ImportResult<T> buildImportResult(List<ImportError> errors, int successCount,
										   int totalCount, int newCount, int updateCount, List<T> addList, List<T> updateList) {
		String message;
		boolean success;

		// 检查是否有批次级别的错误（行号为0）
		boolean hasBatchError = errors.stream().anyMatch(error -> error.getRowIndex() == 0);

		if (hasBatchError) {
			// 有批次错误，整个导入失败
			String errorMsg = errors.stream()
				.filter(error -> error.getRowIndex() == 0)
				.findFirst()
				.map(ImportError::getErrorMessage)
				.orElse("导入过程发生未知错误");
			message = "导入失败！" + errorMsg;
			success = false;
			// 如果有批次错误，不返回任何数据
			addList = Collections.emptyList();
			updateList = Collections.emptyList();
		} else if (errors.isEmpty() && successCount > 0) {
			// 完全成功
			if (newCount > 0 && updateCount > 0) {
				message = String.format("导入成功！新增%d条，更新%d条，共处理%d条数据", newCount, updateCount, successCount);
			} else if (newCount > 0) {
				message = String.format("导入成功！新增%d条数据", newCount);
			} else {
				message = String.format("导入成功！更新%d条数据", updateCount);
			}
			success = true;
		} else if (successCount > 0) {
			// 部分成功（有行级错误，但有数据成功处理）
			if (newCount > 0 && updateCount > 0) {
				message = String.format("导入完成！成功%d条（新增%d，更新%d），失败%d条",
					successCount, newCount, updateCount, errors.size());
			} else if (newCount > 0) {
				message = String.format("导入完成！成功%d条（新增%d），失败%d条",
					successCount, newCount, errors.size());
			} else if (updateCount > 0) {
				message = String.format("导入完成！成功%d条（更新%d），失败%d条",
					successCount, updateCount, errors.size());
			} else {
				message = String.format("导入完成！成功%d条，失败%d条", successCount, errors.size());
			}
			success = false;
		} else {
			// 完全失败
			if (!errors.isEmpty()) {
				message = String.format("导入失败！共%d条数据全部失败", errors.size());
			} else {
				message = "没有有效数据可导入";
			}
			success = false;
			// 完全失败时，不返回任何数据
			addList = Collections.emptyList();
			updateList = Collections.emptyList();
		}

		return ImportResult.<T>builder()
			.success(success)
			.successCount(successCount)
			.totalCount(totalCount)
			.newCount(newCount)
			.updateCount(updateCount)
			.errors(errors)
			.message(message)
			.addList(addList != null ? addList : Collections.emptyList())
			.updateList(updateList != null ? updateList : Collections.emptyList())
			.build();
	}

	// 保留原有的 updateExistingItem 和 copyNonNullFields 方法
	private <T> T updateExistingItem(T existingItem, T newItem, ImportConfig<?, T> config) {
		try {
			if (config.getUpdater() != null) {
				return config.getUpdater().update(existingItem, newItem);
			}
			return copyNonNullFields(existingItem, newItem, config.getUpdateFields());
		} catch (Exception e) {
			log.error("更新数据项时发生异常: {}", e.getMessage(), e);
			throw new RuntimeException("更新数据失败: " + e.getMessage(), e);
		}
	}

	/**
	 * 复制非空字段（默认更新策略）
	 */
	private <T> T copyNonNullFields(T target, T source, List<String> updateFields) throws Exception {
		Class<?> clazz = target.getClass();

		// 如果指定了更新字段，只更新这些字段
		if (!CollectionUtils.isEmpty(updateFields)) {
			for (String fieldName : updateFields) {
				copyFieldIfNotNull(target, source, fieldName);
			}
		} else {
			// 如果没有指定更新字段，更新所有非空字段
			java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
			for (java.lang.reflect.Field field : fields) {
				// 跳过静态和final字段
				int modifiers = field.getModifiers();
				if (java.lang.reflect.Modifier.isStatic(modifiers) ||
					java.lang.reflect.Modifier.isFinal(modifiers)) {
					continue;
				}
				copyFieldIfNotNull(target, source, field.getName());
			}
		}

		return target;
	}

	/**
	 * 如果源字段不为空，则复制字段值
	 */
	private <T> void copyFieldIfNotNull(T target, T source, String fieldName) throws Exception {
		Class<?> clazz = target.getClass();
		java.lang.reflect.Field field = getDeclaredField(clazz, fieldName);
		if (field == null) {
			return;
		}

		field.setAccessible(true);
		Object sourceValue = field.get(source);

		// 如果源值不为空，则复制到目标
		if (sourceValue != null) {
			// 如果是字符串，检查是否为空字符串
			if (sourceValue instanceof String) {
				String strValue = (String) sourceValue;
				if (!strValue.trim().isEmpty()) {
					field.set(target, sourceValue);
				}
			} else {
				field.set(target, sourceValue);
			}
		}
	}

	/**
	 * 递归获取字段
	 */
	private java.lang.reflect.Field getDeclaredField(Class<?> clazz, String fieldName) {
		for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
			try {
				return superClass.getDeclaredField(fieldName);
			} catch (NoSuchFieldException e) {
				// 继续查找
			}
		}
		return null;
	}
}
