package com.dji.sample.component;

import cn.hutool.Hutool;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.dji.sample.common.error.CommonErrorEnum;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.util.JwtUtil;
import com.dji.sample.component.mqtt.config.MqttPropertyConfiguration;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.configuration.CustomConfiguration;
import com.dji.sample.manage.log.util.ReqUtils;
import com.dji.sample.manage.model.entity.UserEntity;
import com.dji.sample.manage.service.IUserService;
import com.dji.sample.manage.service.IWhiteListService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {

    public static final String PARAM_TOKEN = "x-auth-token";

    public static final String TOKEN_CLAIM = "customClaim";

    public static final String SIGN = "sign";

    public static final String KEY = "key";

    public static final String USER_CODE = "userCode";

    @Autowired
    private IWhiteListService whiteListService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // The options method is passed directly.
        if (HttpMethod.OPTIONS.matches(request.getMethod())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }

        boolean result = checkToken(request,response);
        if(!result) {
            result = checkIP(request,response);
        }
        return result;

    }

    private boolean checkIP(HttpServletRequest request, HttpServletResponse response) {
        String uri = request.getRequestURI();
        String ip = ReqUtils.getClientIp();
        log.info("====================客户端请求信息：request uri: {}, IP: {}", uri, ip);
        boolean check = RedisOpsUtils.checkExist(ip);
        if (!check) {
            check = whiteListService.selIp(ip);
            if (check) {
                RedisOpsUtils.set(ip, ip);
                RedisOpsUtils.setWithExpire(ip, ip, RedisConst.WHITELIST_ALIVE_SECOND);
            }
        }
        if(check) {
            response.setStatus(HttpStatus.OK.value());
        } else {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            log.error(CommonErrorEnum.IP_INVALID.getMessage());
        }
        return check;
    }

    private boolean checkToken(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader(PARAM_TOKEN);
        if (!StringUtils.hasText(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            log.error(CommonErrorEnum.NO_TOKEN.getMessage());
            return false;
        }

        // Check if the current token is valid.
        Optional<CustomClaim> customClaimOpt = JwtUtil.parseToken(token);
        if (customClaimOpt.isEmpty()) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }

        // Put the custom data from the token into the request.
        request.setAttribute(TOKEN_CLAIM, customClaimOpt.get());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // Delete the custom data in the request after the request ends.
        request.removeAttribute(TOKEN_CLAIM);
    }

    private static String extractDateTime(String inputString,String userCode) {
        // Step 1: Define the pattern
        Pattern pattern = Pattern.compile(userCode+"(\\d+)"+userCode);
        // Step 2: Create a matcher for the input string
        Matcher matcher = pattern.matcher(inputString);
        // Step 3: Check if the pattern matches
        if (matcher.find()) {
            // Step 4: Extract the number
            String number = matcher.group(1); // group(1) refers to the first capturing group
            return number;
        } else {
            return null;
        }
    }

    private static LocalDateTime parseTimestamp(String timestampString) {
        // Convert the timestamp to LocalDateTime
        long timestamp = Long.parseLong(timestampString);
        return LocalDateTime.ofInstant(
                Instant.ofEpochSecond(timestamp),
                ZoneId.systemDefault()
        );
    }

    public static void main(String[] args) {
        String username = "apminPC";
        String client_id = "e534550a85d94faba22e8040e76514bc";
        String workspace_id = "e3dea0f5-37f2-4d79-a3q8-490af3228070";
        String workspace_name = "测试";
        Long timestamp = Long.parseLong("1722932935");
        String dataInput  = client_id+timestamp+username+workspace_id+workspace_name;
        String generatedHash = DigestUtil.sha256Hex(dataInput.toUpperCase()+"7e92430eb1f949e9a750fadf68777c44");
        //String ac =DigestUtil.sha256Hex("adminPC"+aa+CustomConfiguration.signKey);
        System.out.println("base:"+generatedHash);

        //System.out.println("mq:"+mqttPropertyConfiguration.mqttConnectOptions().getUserName());
        //System.out.println(DigestUtil.sha256Hex("apminapmin1722844106apmin7e92430eb1f949e9a750fadf68777c44"));
    }
}
