package cn.kk.spring_simple_operation.utils;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * SQL生成器工具类
 * 通过反射读取实体类注解，自动生成INSERT语句
 */
public class SqlGenerator {

	/**
	 * 生成INSERT SQL语句
	 *
	 * @param entity 实体对象
	 * @return 完整的INSERT SQL语句
	 */
	public static String generateInsertSql(Object entity) {
		Class<?> clazz = entity.getClass();

		// 获取表名
		String tableName = getTableName(clazz);

		// 获取所有字段信息
		List<FieldInfo> fieldInfos = getFieldInfos(clazz);

		// 字段名
		List<String> columnNames = new ArrayList<>();
		List<Object> values = new ArrayList<>();

		for (FieldInfo fieldInfo : fieldInfos) {
			Object fieldValue = getFieldValue(entity, fieldInfo.getField());
			if (Objects.nonNull(fieldValue)) {
				columnNames.add(fieldInfo.getColumnName());
				values.add(fieldValue);
			}
			else if ("id".equals(fieldInfo.getColumnName())) {
				columnNames.add(fieldInfo.getColumnName());
				values.add(IdWorker.getId());
			}
		}

		return generateSqlWithValues(tableName, columnNames, values);
	}

	/**
	 * 生成UPDATE SQL语句
	 *
	 * @param entity 实体对象
	 * @return 完整的UPDATE SQL语句
	 */
	public static String generateUpdateSql(Object entity) {
		Class<?> clazz = entity.getClass();

		// 获取表名
		String tableName = getTableName(clazz);

		// 获取所有字段信息
		List<FieldInfo> fieldInfos = getFieldInfos(clazz);

		// 存储id值
		Object idValue = null;
		// SET子句的字段和值
		List<String> setClauses = new ArrayList<>();

		for (FieldInfo fieldInfo : fieldInfos) {
			Object fieldValue = getFieldValue(entity, fieldInfo.getField());

			// 判断是否为id字段
			if ("id".equals(fieldInfo.getColumnName())) {
				idValue = fieldValue;
				continue;
			}

			// 跳过null值字段
			if (Objects.isNull(fieldValue)) {
				continue;
			}

			setClauses.add(fieldInfo.getColumnName() + " = " + formatValue(fieldValue));
		}

		// 校验id是否存在
		if (Objects.isNull(idValue)) {
			throw new RuntimeException("UPDATE语句必须指定id值");
		}

		// 构建UPDATE SQL
		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE ").append(tableName).append(" SET ");
		sql.append(String.join(", ", setClauses));
		sql.append(" WHERE id = ").append(formatValue(idValue));
		sql.append(";\n");

		return sql.toString();
	}

	/**
	 * 生成带实际值的SQL（用于展示）
	 */
	private static String generateSqlWithValues(String tableName, List<String> columnNames, List<Object> values) {
		StringBuilder sql = new StringBuilder();
		sql.append("INSERT INTO ").append(tableName).append("(");
		sql.append(String.join(", ", columnNames));
		sql.append(") VALUES (");

		List<String> formattedValues = new ArrayList<>();
		for (Object value : values) {
			formattedValues.add(formatValue(value));
		}
		sql.append(String.join(", ", formattedValues));
		sql.append(");\n");

		return sql.toString();
	}

	/**
	 * 格式化值为SQL字符串
	 */
	private static String formatValue(Object value) {
		if (value == null) {
			return "NULL";
		}
		if (value instanceof String) {
			return "'" + value + "'";
		}
		return value.toString();
	}

	/**
	 * 获取表名
	 */
	private static String getTableName(Class<?> clazz) {
		TableName tableName = clazz.getAnnotation(TableName.class);
		if (tableName != null) {
			return tableName.value();
		}
		// 默认使用类名转下划线
		return camelToUnderline(clazz.getSimpleName());
	}

	/**
	 * 获取所有字段信息
	 */
	private static List<FieldInfo> getFieldInfos(Class<?> clazz) {
		List<FieldInfo> fieldInfos = new ArrayList<>();
		Field[] fields = clazz.getDeclaredFields();

		for (Field field : fields) {
			// 跳过静态字段
			if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			String columnName = null;

			// 优先读取 @TableField 注解
			TableField tableField = field.getAnnotation(TableField.class);
			if (tableField != null) {
				columnName = tableField.value();
			}

			// 如果没有 @TableField，尝试 @TableId
			if (columnName == null || columnName.isEmpty()) {
				TableId tableId = field.getAnnotation(TableId.class);
				if (tableId != null) {
					columnName = tableId.value();
				}
			}

			//// 如果没有注解，使用字段名转下划线
			//if (columnName == null || columnName.isEmpty()) {
			//	columnName = camelToUnderline(field.getName());
			//}

			if (Objects.isNull(columnName)) {
				continue;
			}
			field.setAccessible(true);
			fieldInfos.add(new FieldInfo(field, columnName));
		}

		return fieldInfos;
	}

	/**
	 * 获取字段值
	 */
	private static Object getFieldValue(Object entity, Field field) {
		try {
			return field.get(entity);
		} catch (IllegalAccessException e) {
			throw new RuntimeException("获取字段值失败: " + field.getName(), e);
		}
	}

	/**
	 * 驼峰命名转下划线命名
	 */
	private static String camelToUnderline(String camel) {
		StringBuilder result = new StringBuilder();
		for (char c : camel.toCharArray()) {
			if (Character.isUpperCase(c)) {
				if (result.length() > 0) {
					result.append("_");
				}
				result.append(Character.toLowerCase(c));
			}
			else {
				result.append(c);
			}
		}
		return result.toString();
	}

	/**
	 * 字段信息内部类
	 */
	private static class FieldInfo {
		private final Field  field;
		private final String columnName;

		public FieldInfo(Field field, String columnName) {
			this.field = field;
			this.columnName = columnName;
		}

		public Field getField() {
			return field;
		}

		public String getColumnName() {
			return columnName;
		}
	}

}
