package com.cf.imes.framework.mybatis.core.handler;

import cn.hutool.core.util.StrUtil;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.mybatis.OAuth2AccessTokenDO;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import com.cf.imes.framework.web.core.util.WebFrameworkUtils;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Objects;


/**
 * 通用参数填充实现类
 *
 * 如果没有显式的对通用参数进行赋值，这里会对通用参数进行填充、赋值
 *
 * @author hexiaowu
 */
public class DefaultDBFieldHandler implements MetaObjectHandler {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private HttpServletRequest request;

    private static final String AUTHORIZATION_BEARER = "Bearer";

    private static final String OAUTH2_ACCESS_TOKEN = "oauth2_access_token:%s";


    @Override
    public void insertFill(MetaObject metaObject) {
        if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
            BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();

            LocalDateTime current = LocalDateTime.now();
            // 创建时间为空，则以当前时间为插入时间
            if (Objects.isNull(baseDO.getCreateTime())) {
                baseDO.setCreateTime(current);
            }
            // 更新时间为空，则以当前时间为更新时间
            if (Objects.isNull(baseDO.getUpdateTime())) {
                baseDO.setUpdateTime(current);
            }

            //Long userId = WebFrameworkUtils.getLoginUserId();
            String loginUserName = WebFrameworkUtils.getLoginUserName();

            // 当前登录用户不为空，创建人为空，则当前登录用户为创建人
            if (Objects.nonNull(loginUserName) && Objects.isNull(baseDO.getCreator())) {
                baseDO.setCreator(loginUserName);
            }
            // 当前登录用户不为空，更新人为空，则当前登录用户为更新人
            if (Objects.nonNull(loginUserName) && Objects.isNull(baseDO.getUpdater())) {
                baseDO.setUpdater(loginUserName);
            }

        }

        // 从请求中获取到 Token
        String authorization = obtainAuthorization(request, "Authorization", "token");

        Long organId = null;

        /**
         *  用户首次密码登陆的时候，不会有token带入，直接捕捉异常抛出即可，组织ID后续会根据用户登录的组织进行填入，
         *  这里的组织ID字段填入即使为空也可，后续的请求中都会带有token，再从缓存中获取到 token 数据，再获取组织ID，填入即可
         */
        try {
            // 获取 token 对应的缓存数据，并得到组织 ID
            OAuth2AccessTokenDO oAuth2AccessTokenDO = get(authorization);
            organId = oAuth2AccessTokenDO.getOrganId();

        }catch (Exception e){

        }
        this.strictInsertFill(metaObject, "organId", Long.class, organId );


    }


    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时间为空，则以当前时间为更新时间
        Object modifyTime = getFieldValByName("updateTime", metaObject);
        if (Objects.isNull(modifyTime)) {
            setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }

        // 当前登录用户不为空，更新人为空，则当前登录用户为更新人
        Object modifier = getFieldValByName("updater", metaObject);
        //Long userId = WebFrameworkUtils.getLoginUserId();
        String loginUserName = WebFrameworkUtils.getLoginUserName();
        if (Objects.nonNull(loginUserName) && Objects.isNull(modifier)) {
            setFieldValByName("updater", loginUserName, metaObject);
        }

        // 从请求中获取到 Token
        String authorization = obtainAuthorization(request, "Authorization", "token");

        Long organId = null;

        /**
         *  用户首次密码登陆的时候，不会有token带入，直接捕捉异常抛出即可，组织ID后续会根据用户登录的组织进行填入，
         *  这里的组织ID字段填入即使为空也可，后续的请求中都会带有token，再从缓存中获取到 token 数据，再获取组织ID，填入即可
         */
        try {
            // 获取 token 对应的缓存数据，并得到组织 ID
            OAuth2AccessTokenDO oAuth2AccessTokenDO = get(authorization);
            organId = oAuth2AccessTokenDO.getOrganId();


        }catch (Exception e){

        }

        this.strictUpdateFill(metaObject, "organId", Long.class, organId );

    }



    // 从请求中获取到 token
    private static String obtainAuthorization(HttpServletRequest request,
                                              String headerName, String parameterName) {
        // 1. 获得 Token。优先级：Header > Parameter
        String token = request.getHeader(headerName);
        if (StrUtil.isEmpty(token)) {
            token = request.getParameter(parameterName);
        }
        if (!StringUtils.hasText(token)) {
            return null;
        }
        // 2. 去除 Token 中带的 Bearer
        int index = token.indexOf(AUTHORIZATION_BEARER + " ");
        return index >= 0 ? token.substring(index + 7).trim() : token;
    }


    // 从缓存中获取到缓存的数据
    private OAuth2AccessTokenDO get(String accessToken) {
        String redisKey = String.format(OAUTH2_ACCESS_TOKEN, accessToken);
        return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), OAuth2AccessTokenDO.class);
    }


}
