package com.yifu.cloud.plus.v1.yifu.salary.util;

import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainSelectVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ValidityConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.LocalDateTimeUtils;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TConfigSalary;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TSalaryAccountVo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author hgw
 * @Description: 工资表上传公共类
 */
@Data
@Slf4j
public class SalaryCommonUtil implements Serializable {

	/**
	 * 按类型统一返回String内容
	 *
	 * @param param
	 * @return
	 */
	public static String getStringValByObject(Object param) {
		if (null == param) {
			return null;
		} else if (param instanceof Integer) {
			return Integer.toString(((Integer) param).intValue());
		} else if (param instanceof String) {
			return (String) param;
		} else if (param instanceof Double) {
			return Double.toString(((Double) param).doubleValue());
		} else if (param instanceof Float) {
			return Float.toString(((Float) param).floatValue());
		} else if (param instanceof Long) {
			return Long.toString(((Long) param).longValue());
		} else if (param instanceof Boolean) {
			return Boolean.toString(((Boolean) param).booleanValue());
		} else if (param instanceof Date) {
			return DateUtil.dateToString((Date) param);
		} else if (param instanceof LocalDateTime) {
			return LocalDateTimeUtils.formatTime((LocalDateTime) param, DateUtil.DATETIME_PATTERN_SECOND);
		} else {
			return param.toString();
		}
	}

	/**
	 * 根据属性名获取属性值
	 *
	 * @param fieldName
	 * @param hashMap
	 * @return
	 */
	public static Object getFieldValueByName(String fieldName, Map hashMap) {
		try {
			return hashMap.get(fieldName);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * @param fieldName 字段名
	 * @param o         对象
	 * @return 字段值
	 * @MethodName : getFieldValueByName
	 * @Description : 根据字段名获取字段值
	 */
	public static Object getFieldValueByName(String fieldName, Object o, String dateFormat) {

		Object value = null;
		Field field = null;
		if (o == null) {
			return "";
		}
		field = getFieldByName(fieldName, o.getClass());
		String type = getFieldType(fieldName, o.getClass());
		if (field != null) {
			field.setAccessible(true);
			try {
				if (null != type && type.equals("Date")) {
					Date date = (Date) field.get(o);
					return DateUtil.dateToString(date, dateFormat == null ? "yyyy-MM-dd" : dateFormat);
				} else {
					value = field.get(o);
				}
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				log.error("getFieldValueByName错误：", e);
			}
		} else {
			log.info(o.getClass().getSimpleName() + "类不存在字段名 " + fieldName);
		}

		return value;
	}

	/**
	 * @param fieldName 字段名
	 * @param clazz     包含该字段的类
	 * @return 字段
	 * @MethodName : getFieldByName
	 * @Description : 根据字段名获取字段
	 */
	public static Field getFieldByName(String fieldName, Class<?> clazz) {
		// 拿到本类的所有字段
		Field[] selfFields = clazz.getDeclaredFields();

		// 如果本类中存在该字段，则返回
		for (Field field : selfFields) {
			if (field.getName().equals(fieldName)) {
				return field;
			}
		}
		// 否则，查看父类中是否存在此字段，如果有则返回
		Class<?> superClazz = clazz.getSuperclass();
		if (superClazz != null && superClazz != Object.class) {
			return getFieldByName(fieldName, superClazz);
		}

		// 如果本类和父类都没有，则返回空
		return null;
	}

	/**
	 * @param fieldName 字段名
	 * @param clazz     包含该字段的类
	 * @return 字段
	 * @MethodName : getFieldType
	 * @Description : 根据字段名获取字段类型
	 */
	public static String getFieldType(String fieldName, Class<?> clazz) {
		// 拿到本类的所有字段
		Field[] selfFields = clazz.getDeclaredFields();

		// 如果本类中存在该字段，则返回
		for (Field field : selfFields) {
			if (field.getName().equals(fieldName)) {
				//如果type是类类型，则前面包含"class "，后面跟类名
				String type = field.getGenericType().toString();
				if (type.equals("class java.lang.String")) {
					return "String";
				} else if (type.equals("class java.lang.Integer")) {
					return "Integer";
				} else if (type.equals("class java.lang.Short")) {
					return "Short";
				} else if (type.equals("class java.lang.Double")) {
					return "Double";
				} else if (type.equals("class java.lang.Boolean")) {
					return "Boolean";
				} else if (type.equals("class java.util.Date")) {
					return "Date";
				} else {
					return null;
				}
			}
		}
		// 否则，查看父类中是否存在此字段，如果有则返回
		Class<?> superClazz = clazz.getSuperclass();
		if (superClazz != null && superClazz != Object.class) {
			return getFieldType(fieldName, superClazz);
		}
		// 如果本类和父类都没有，则返回空
		return null;
	}

	/**
	 * 输出错误数据
	 *
	 * @param attr
	 * @param msg
	 * @param i
	 * @return
	 */
	public static String errorInfo(ExcelAttribute attr, String msg, Integer i) {
		if (Common.isNotNull(msg)) {
			return "第" + i + "行：" + attr.name() + msg;
		} else if (Common.isNotNull(attr.errorInfo())) {
			return "第" + i + "行：" + attr.errorInfo();
		}
		return "";
	}

	/**
	 * 实现各种校验方式的错误返回新
	 *
	 * @param c
	 * @param attr
	 * @param i
	 * @return
	 */
	public static String validateUtil(String c, ExcelAttribute attr, int i) {
		//非空校验
		if (attr.isNotEmpty() && Common.isEmpty(c)) {
			return SalaryCommonUtil.errorInfo(attr, "_字段不可为空", i);
		}
		if (Common.isNotNull(c)) {
			//日期格式校验
			if (attr.isDate()) {
				DateUtil.stringToDate(c.trim(), attr.dateFormat());
			}
			//手机号码校验
			if (attr.isPhone() && getMatchRes(c, attr, ValidityConstants.MOBILE_PATTERN)) {
				return errorInfo(attr, "_手机号码有误", i);
			}
			//身份证校验
			if (attr.isIdCard() && getMatchRes(c, attr, ValidityConstants.IDCARD_PATTERN)) {
				return errorInfo(attr, "_身份证格式有误", i);
			}
			//邮箱验证
			if (attr.isEmail() && getMatchRes(c, attr, ValidityConstants.EMAIL_PATTERN)) {
				return errorInfo(attr, "_邮箱格式有误", i);
			}
			//integer 验证
			if (attr.isInteger() && getMatchRes(c, attr, ValidityConstants.INTEGER_PATTERN)) {
				return errorInfo(attr, "_整数格式有误", i);
			}
			//float、double 验证
			if (attr.isFloat() && getMatchRes(c, attr, ValidityConstants.FLOAT_PATTERN)) {
				return errorInfo(attr, "_数字格式有误", i);
			}
			//最大长度校验
			if (attr.maxLength() > 0 && c.length() > attr.maxLength()) {
				return errorInfo(attr, "_超出最大长度", i);
			}
			//最大值校验
			if (Integer.parseInt(attr.max()) > 0) {
				if (Common.isNumber(c)) {
					if (Integer.parseInt(c) > attr.maxLength()) {
						return errorInfo(attr, "_超出最大值", i);
					}
				} else {
					return "第" + i + "行：" + "_必须为数字";
				}
			}
			//最小值校验
			if (attr.min() > 0) {
				if (Common.isNumber(c)) {
					if (Integer.parseInt(c) > attr.maxLength()) {
						return errorInfo(attr, "_小于最小值", i);
					}
				} else {
					return "第" + i + "行：" + "_必须为数字";
				}
			}
		}
		return null;
	}

	/**
	 * 正则匹配返回
	 *
	 * @param c
	 * @param attr
	 * @param pattern
	 * @return
	 * @Author fxj
	 * @Date 2019-08-06
	 **/
	public static boolean getMatchRes(String c, ExcelAttribute attr, String pattern) {
		return !c.matches(Common.isEmpty(attr.pattern()) ? pattern : attr.pattern());
	}

	// 判断一个字符串是否含有数字
	public static boolean HasNumber(String content) {
		boolean flag = false;
		Pattern p = Pattern.compile(".*\\d+.*");
		Matcher m = p.matcher(content);
		if (m.matches()) {
			flag = true;
		}
		return flag;
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param attr
	 * @param fieldType
	 * @param entity
	 * @Description: 总入口：塞属性
	 * @Author: hgw
	 * @Date: 2021/1/11 11:18
	 * @return: void
	 **/
	public static <T> void setFields(Field field, String cellValueStr, ExcelAttribute attr, Class<?> fieldType, T entity) throws IllegalAccessException {
		if (String.class == fieldType) {
			setStringField(field, cellValueStr, entity);
		} else if (BigDecimal.class == fieldType) {
			setBigDecimalField(field, cellValueStr, entity);
		} else if (Date.class == fieldType && Common.isNotNull(cellValueStr.trim())) {
			setDateField(field, cellValueStr, attr, entity);
		} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
			setIntegerField(field, cellValueStr, entity);
		} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
			field.set(entity, Long.valueOf(cellValueStr));
		}
		setOtherField(field, cellValueStr, attr, fieldType, entity);
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param attr
	 * @param fieldType
	 * @param entity
	 * @Description: 判断其他值
	 * @Author: hgw
	 * @Date: 2021/1/11 11:49
	 * @return: void
	 **/
	private static <T> void setOtherField(Field field, String cellValueStr, ExcelAttribute attr, Class<?> fieldType, T entity) throws IllegalAccessException {
		if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
			field.set(entity, Float.valueOf(cellValueStr));
		} else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
			field.set(entity, Short.valueOf(cellValueStr));
		} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
			field.set(entity, Double.valueOf(cellValueStr));
		} else if (Character.TYPE == fieldType) {
			setCharField(field, cellValueStr, entity);
		} else if (LocalDateTime.class == fieldType && Common.isNotNull(cellValueStr.trim())) {
			setLocalDateTimeField(field, cellValueStr, attr, entity);
		} else if (LocalDate.class == fieldType && Common.isNotNull(cellValueStr.trim())) {
			setLocalDateTileField(field, cellValueStr, attr, entity);
		}
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param attr
	 * @param entity
	 * @Description: 判断LocalDate
	 * @Author: hgw
	 * @Date: 2021/1/11 11:49
	 * @return: void
	 **/
	private static <T> void setLocalDateTileField(Field field, String cellValueStr, ExcelAttribute attr, T entity) throws IllegalAccessException {
		field.set(entity, LocalDate.parse(cellValueStr.trim(), Common.isEmpty(attr.dateFormat()) ? DateTimeFormatter.ofPattern(DateUtil.DATETIME_YYYYMM) : DateTimeFormatter.ofPattern(attr.dateFormat())));
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param attr
	 * @param entity
	 * @Description: 判断LocalDateTime
	 * @Author: hgw
	 * @Date: 2021/1/11 11:49
	 * @return: void
	 **/
	private static <T> void setLocalDateTimeField(Field field, String cellValueStr, ExcelAttribute attr, T entity) throws IllegalAccessException {
		field.set(entity, LocalDateTimeUtils.convertDateToLDT(DateUtil.stringToDate(cellValueStr.trim(), Common.isEmpty(attr.dateFormat()) ? DateUtil.DATETIME_PATTERN_SECOND : attr.dateFormat())));
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param entity
	 * @Description: 判断Char
	 * @Author: hgw
	 * @Date: 2021/1/11 11:48
	 * @return: void
	 **/
	private static <T> void setCharField(Field field, String cellValueStr, T entity) throws IllegalAccessException {
		if (cellValueStr != null && cellValueStr.length() > 0) {
			field.set(entity, cellValueStr.charAt(0));
		}
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param entity
	 * @Description: 判断整型
	 * @Author: hgw
	 * @Date: 2021/1/11 11:48
	 * @return: void
	 **/
	private static <T> void setIntegerField(Field field, String cellValueStr, T entity) throws IllegalAccessException {
		if ("否".equals(cellValueStr)) {
			field.set(entity, 0);
		} else if ("是".equals(cellValueStr)) {
			field.set(entity, 1);
		} else {
			field.set(entity, Integer.parseInt(cellValueStr));
		}
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param attr
	 * @param entity
	 * @Description: 判断日期
	 * @Author: hgw
	 * @Date: 2021/1/11 11:48
	 * @return: void
	 **/
	private static <T> void setDateField(Field field, String cellValueStr, ExcelAttribute attr, T entity) throws IllegalAccessException {
		field.set(entity, DateUtil.stringToDate(cellValueStr.trim(), Common.isEmpty(attr.dateFormat()) ? DateUtil.ISO_EXPANDED_DATE_FORMAT : attr.dateFormat()));
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param entity
	 * @Description: 判断金额
	 * @Author: hgw
	 * @Date: 2021/1/11 11:48
	 * @return: void
	 **/
	private static <T> void setBigDecimalField(Field field, String cellValueStr, T entity) throws IllegalAccessException {
		if (cellValueStr.indexOf('%') != -1) {
			cellValueStr = cellValueStr.replace("%", "");
		}
		if (cellValueStr.indexOf(',') != -1) {
			cellValueStr = cellValueStr.replace(",", "");
		}
		field.set(entity, BigDecimal.valueOf(Double.valueOf(cellValueStr)));
	}

	/**
	 * @param field
	 * @param cellValueStr
	 * @param entity
	 * @Description: 判断固定字符串，塞值
	 * @Author: hgw
	 * @Date: 2021/1/11 11:47
	 * @return: void
	 **/
	private static <T> void setStringField(Field field, String cellValueStr, T entity) throws IllegalAccessException {
		if ("否".equals(cellValueStr)) {
			field.set(entity, "0");
		} else if ("是".equals(cellValueStr)) {
			field.set(entity, "1");
		} else if ("暂停发".equals(cellValueStr)) {
			field.set(entity, "1");
		} else if ("立即发".equals(cellValueStr)) {
			field.set(entity, "0");
		} else if ("现金".equals(cellValueStr)) {
			field.set(entity, "0");
		} else if ("银行".equals(cellValueStr)) {
			field.set(entity, "1");
		} else if ("线下".equals(cellValueStr)) {
			field.set(entity, "2");
		} else if ("合并".equals(cellValueStr)) {
			field.set(entity, "0");
		} else if ("单独".equals(cellValueStr)) {
			field.set(entity, "1");
		} else if (SalaryConstants.IS_COMPANY.equals(cellValueStr)) {
			field.set(entity, SalaryConstants.IS_PERSON_TAX_ARR[0]);
		} else if (SalaryConstants.IS_PERSON_OTHER.equals(cellValueStr)) {
			field.set(entity, SalaryConstants.IS_PERSON_TAX_ARR[1]);
		} else if (SalaryConstants.IS_PERSON.equals(cellValueStr)) {
			field.set(entity, SalaryConstants.IS_PERSON_TAX_ARR[2]);
		} else {
			field.set(entity, cellValueStr);
		}
	}

	/**
	 * @param configSalary
	 * @param entity
	 * @Description: 填充配置项属性
	 * @Author: hgw
	 * @Date: 2021/1/11 17:09
	 * @return: void
	 **/
	public static void setConfigSalary(TConfigSalary configSalary, TSalaryAccountVo entity) {
		if (configSalary != null && configSalary.getId() != null) {
			entity.setSalaryMonth(DateUtil.addMonth(configSalary.getSalaryMonth()));
			entity.setDeduSocialMonth(DateUtil.addMonth(configSalary.getSocialMonth()));
			entity.setDeduProvidentMonth(DateUtil.addMonth(configSalary.getFundMonth()));
			entity.setSocialPriority(String.valueOf(configSalary.getSocialPriority()));
			entity.setFundPriority(String.valueOf(configSalary.getFundPriority()));
		}
	}

	/**
	 * @param salaryType
	 * @param dept
	 * @param entity
	 * @param salaryGiveTimeFlag
	 * @Description:
	 * @Author: hgw
	 * @Date: 2021/1/11 17:19
	 * @return: void
	 **/
	public static void setAccountBaseInfo(String salaryType, TSettleDomainSelectVo dept, TSalaryAccountVo entity, boolean salaryGiveTimeFlag) {
		entity.setDistributionFlag(CommonConstants.ZERO_STRING);
		if (Common.isEmpty(entity.getSalaryGiveTime())) {
			if (salaryGiveTimeFlag) {
				entity.setSalaryGiveTime(CommonConstants.ZERO_STRING);
			} else {
				entity.setSalaryGiveTime(CommonConstants.ONE_STRING);
			}
		}
		entity.setDeleteFlag(SalaryConstants.NOT_DELETE);
		entity.setDeptId(dept.getId());
		entity.setDeptNo(dept.getDepartNo());
		entity.setDeptName(dept.getDepartName());
		entity.setUnitId(dept.getCustomerId());
		entity.setUnitName(dept.getCustomerName());
		entity.setUnitNo(dept.getCustomerCode());
		entity.setFormType(salaryType);
	}

	/**
	 * @param strList
	 * @Description: 简单的list转化为String
	 * @Author: hgw
	 * @Date: 2019/9/27 17:19
	 * @return: java.lang.String
	 **/
	public static String listToStrEasy(List<String> strList) {
		StringBuilder result = new StringBuilder();
		if (strList != null && !strList.isEmpty()) {
			for (int i = 0; i < strList.size(); i++) {
				if (i == 0) {
					result.append(strList.get(0));
				} else {
					result.append(",").append(strList.get(i));
				}
			}
		}
		return result.toString();
	}

	/**
	 * 拼成带'的串xml里用$取值
	 *
	 * @param list
	 * @return
	 */
	public static String listForSqlIn(List<String> list) {
		String result = "";
		if (Common.isNotNull(list)) {
			// 去重
			Set<String> set = new HashSet<String>(list);
			for (String str : set) {
				if ("".equals(result)) {
					result = "'" + str + "'";
				} else {
					result += ",'" + str + "'";
				}
			}
		}
		return result;
	}

}
