package com.yeejoin.amos.boot.biz.config;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.yeejoin.amos.boot.biz.common.annotation.FillCommonUserField;
import com.yeejoin.amos.boot.biz.common.annotation.PipeLengthField;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @author Dell
 */
@Component
public class MetaHandler implements MetaObjectHandler {

    @Autowired
    private RedisUtils redisUtils;

    protected String getToken() {
        String authToken = RequestContext.getToken();
//		if (authToken == null) {
//			authToken = request.getHeader("X-Access-Token");
//		}
        return authToken;
    }

    /**
     * 新增数据拦截
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        Date currentDate = new Date();
        Object originalObj = metaObject.getOriginalObject();
        Class<?> clazz = originalObj.getClass();
        // 处理 Map 封装的情况（update(entity, wrapper) 方式）
        if (originalObj instanceof Map) {
            Map<?,?> map = (Map<?,?>) originalObj;
            Object et = map.get(Constants.ENTITY);  // MyBatis-Plus 的实体key
            clazz = (et != null) ? et.getClass() : clazz;
        }
        FillCommonUserField annotation = clazz.getAnnotation(FillCommonUserField.class);
        if (annotation == null || annotation.isAutoFill()) {
            autoFillUser(metaObject, metaObject.getOriginalObject());
        }
        PipeLengthField pipeLengthField = clazz.getAnnotation(PipeLengthField.class);
        if(pipeLengthField != null){
            processAutoFill(metaObject, pipeLengthField);
        }
        this.setFieldValByName("createDate", currentDate, metaObject);
    }


    private void processAutoFill(MetaObject metaObject, PipeLengthField pipeLengthField) {
        // 1. 防御性校验
        if (metaObject == null || pipeLengthField == null) {
            return;
        }
        if (StringUtils.isBlank(pipeLengthField.sourceField()) ||
                StringUtils.isBlank(pipeLengthField.targetField())) {
            return;
        }

        // 2. 获取实际要操作的对象（处理Map封装情况）
        Object operationObj = getOperationObject(metaObject);
        if (operationObj == null) {
            return;
        }

        // 3. 重新基于实际对象创建MetaObject
        MetaObject targetMetaObject = metaObject.hasGetter(Constants.ENTITY)
                ? MetaObject.forObject(operationObj, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory())
                : metaObject;

        // 4. 安全取值
        if (!targetMetaObject.hasGetter(pipeLengthField.sourceField())) {
            return;
        }

        Object sourceValue = targetMetaObject.getValue(pipeLengthField.sourceField());
        if (sourceValue == null) {
            return;
        }

        // 5. 转换并设值
        Object convertedValue = convertValue(sourceValue, pipeLengthField);
        this.setFieldValByName(pipeLengthField.targetField(), convertedValue, targetMetaObject);
    }

    /**
     * 处理Map类型的参数封装
     */
    private Object getOperationObject(MetaObject metaObject) {
        Object original = metaObject.getOriginalObject();

        // 处理update(entity, wrapper)产生的Map封装
        if (original instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) original;
            // MyBatis-Plus的标准实体key
            return map.get(Constants.ENTITY) == null ? original : map.get(Constants.ENTITY);
        }
        return original;
    }



    private Object convertValue(Object sourceValue, PipeLengthField pipeLengthField) {
        // 示例：针对pipeLength的特殊处理
        if ("pipeLengthText".equals(pipeLengthField.sourceField())) {
            return Arrays.stream(sourceValue.toString().split("/")).filter(Objects::nonNull)
                    .map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(3, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
        }
        // 可扩展其他转换规则
        return sourceValue;
    }

    private void autoFillUser(MetaObject metaObject, Object entity) {
        //获取用户信息 以及当前用户登录公司部门，角色
        String userId = RequestContext.getExeUserId();
        ReginParams reginParams =
                JSONObject.parseObject(null != redisUtils.get(RedisKey.buildReginKey(userId, getToken())) ?
                        redisUtils.get(RedisKey.buildReginKey(userId, getToken())).toString() : null, ReginParams.class);
        if (ObjectUtils.isEmpty(reginParams)) {
            return;
        }
        AgencyUserModel agencyUserModel = reginParams.getUserModel();

        if (ObjectUtils.isEmpty(reginParams) || ObjectUtils.isEmpty(agencyUserModel)) {
            return;
        }

        // 更新rec字段
        recInfoUpdate(metaObject, agencyUserModel);

        if (isExistField("allotmentTime", entity)) {
            Date currentDate = new Date();
            this.setFieldValByName("recDate", currentDate, metaObject);
        }

        //以下为装备中转移过来的
        if (isExistField("userId", entity) && isStringField(metaObject,"userId")) {
            this.setFieldValByName("userId", String.valueOf(agencyUserModel.getUserId()), metaObject);
        }

        if (isExistField("creatorId", entity)) {
            this.setFieldValByName("creatorId", Long.valueOf(agencyUserModel.getUserId()), metaObject);
        }
        if (isExistField("userName", entity)) {
            this.setFieldValByName("userName", agencyUserModel.getRealName(), metaObject);
        }
//        if (isExistField("companyName", entity)) {
//            this.setFieldValByName("companyName", reginParams.getCompany().getCompanyName(), metaObject);
//        }
        if (isExistField("orgCode", entity) && !isHasValue("orgCode", entity)) {
            this.setFieldValByName("orgCode", reginParams.getCompany().getOrgCode(), metaObject);
        }
        if (isExistField("departmentName", entity)) {
            this.setFieldValByName("departmentName", ObjectUtils.isEmpty(reginParams.getDepartment()) ? "" : reginParams.getDepartment().getDepartmentName(), metaObject);
        }
        if (isExistField("departmentOrgcode", entity)) {
            this.setFieldValByName("departmentOrgcode", ObjectUtils.isEmpty(reginParams.getDepartment()) ? "" : reginParams.getDepartment().getOrgCode(), metaObject);
        }
    }

    private void recInfoUpdate(MetaObject metaObject, AgencyUserModel agencyUserModel) {
        this.setFieldValByName("recUserId", agencyUserModel.getUserId(), metaObject);
        this.setFieldValByName("recUserName", agencyUserModel.getRealName(), metaObject);
        Date currentDate = new Date();
        this.setFieldValByName("recDate", currentDate, metaObject);
        this.setFieldValByName("updateTime", currentDate, metaObject);
    }

    private Boolean isExistField(String field, Object obj) {
        if (obj == null || StringUtils.isEmpty(field)) {
            return null;
        }
        Object o = JSONObject.toJSON(obj);
        JSONObject jsonObj = new JSONObject();
        if (o instanceof JSONObject) {
            jsonObj = (JSONObject) o;
        }
        return jsonObj.containsKey(field);
    }

    private Boolean isHasValue(String field, Object obj) {
        if (obj == null || StringUtils.isEmpty(field)) {
            return false;
        }
        Object o = JSONObject.toJSON(obj);
        JSONObject jsonObj = new JSONObject();
        if (o instanceof JSONObject) {
            jsonObj = (JSONObject) o;
        }
        return StringUtils.isNotEmpty(jsonObj.getString(field));
    }

    private Boolean isStringField(MetaObject metaObject, String fieldName) {
        Class clazz = metaObject.getOriginalObject().getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (fieldName.equals(field.getName()) && ("class java.lang.String").equals(field.getGenericType().toString())) {
                return true;
            }
        }
        return false;
    }


    /**
     * 更新拦截
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        Object originalObj = metaObject.getOriginalObject();
        Class<?> clazz = originalObj.getClass();
        // 处理 Map 封装的情况（update(entity, wrapper) 方式）
        if (originalObj instanceof Map) {
            Map<?,?> map = (Map<?,?>) originalObj;
            Object et = map.get(Constants.ENTITY);  // MyBatis-Plus 的实体key
            clazz = (et != null) ? et.getClass() : clazz;
        }
        FillCommonUserField annotation = clazz.getAnnotation(FillCommonUserField.class);
        if (annotation == null || annotation.isAutoFill()) {
            String userId = RequestContext.getExeUserId();
            ReginParams reginParams =
                    JSONObject.parseObject(null != redisUtils.get(RedisKey.buildReginKey(userId, getToken())) ?
                            redisUtils.get(RedisKey.buildReginKey(userId, getToken())).toString() : null, ReginParams.class);
            if (ObjectUtils.isEmpty(reginParams)) {
                return;
            }
            AgencyUserModel agencyUserModel = reginParams.getUserModel();
            recInfoUpdate(metaObject, agencyUserModel);
        }
        PipeLengthField pipeLengthField = clazz.getAnnotation(PipeLengthField.class);
        if(pipeLengthField != null){
            processAutoFill(metaObject, pipeLengthField);
        }
    }
}