package com.xhpc.evcs.api;

import com.xhpc.evcs.domain.AuthSecretToken;
import com.xhpc.evcs.domain.XhpcInternetUser;
import com.xhpc.evcs.dto.CommonResponse;
import com.xhpc.evcs.dto.TokenRequest;
import com.xhpc.evcs.dto.TokenResponse;
import com.xhpc.evcs.encryption.EvcsConst;
import com.xhpc.evcs.jpa.AuthSecretTokenRepository;
import com.xhpc.evcs.jpa.XhpcInternetUserRepository;
import com.xhpc.evcs.utils.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

import static com.xhpc.common.data.redis.StaticBeanUtil.REDIS;

@Slf4j
@RestController()
public class QueryTokenController {

    @Autowired
    private AuthSecretTokenRepository authSecretTokenRepository;
    @Autowired
    private XhpcInternetUserRepository xhpcInternetUserRepository;

    /**
     * 用于平台之间认证Token的申请
     * @param encout
     * @param tokenRequest
     * @return
     * @throws IOException
     */
    @PostMapping("/v1/query_token")
    public CommonResponse queryToken(@RequestHeader(value = "enc.out", defaultValue = "true") String encout,
                                     @RequestBody TokenRequest tokenRequest) throws IOException {

        log.debug("<<query token request body: " + tokenRequest);
        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        String operatorID = tokenRequest.getOperatorId();
        if (operatorID == null) {
            String decodedData = (String) tokenRequest.getAdditionalProperties().get("Data");
            tokenRequest = JSONUtil.readParams(decodedData, TokenRequest.class);
        }
        if (tokenRequest == null) {
            resp.setMsg("Request params validation failed");
        } else {
            operatorID = tokenRequest.getOperatorId();
            TokenResponse tokenResponse = new TokenResponse();
            tokenResponse.setOperatorId(REDIS.getCacheObject("global:EVCS_OPID"));
            tokenResponse.setSuccStat(0);
            tokenResponse.setFailReason(0);
            XhpcInternetUser xhpcInternetUser =
                    xhpcInternetUserRepository.findByOperatorIdEvcsLikeAndCooperationStartTimeBeforeAndCooperationEndTimeAfter(tokenRequest.getOperatorId(), Instant.now(), Instant.now());
            if (xhpcInternetUser != null) {
                String operatorSecret = tokenRequest.getOperatorSecret();
                AuthSecretToken authSecretTokenIn =
                        authSecretTokenRepository.findByStatusAndOperatorId3irdptyAndSecretTokenTypeAndOperatorSecret(1,
                                operatorID, AuthSecretToken.SECRET_TOKEN_TYPE_IN, operatorSecret).orElse(null);
                if (authSecretTokenIn == null) {
                    resp.setRet("4003");
                    resp.setMsg("Invalid OperatorID/Secret");
                    tokenResponse.setSuccStat(1);
                    tokenResponse.setFailReason(2);
                } else {
                    String token;
                    if (authSecretTokenIn.getTokenExpiry() != null && !authSecretTokenIn.getTokenExpiry().before(Calendar.getInstance().getTime())) {
                        token = authSecretTokenIn.getToken();
                    } else {
                        token = UUID.randomUUID().toString().replaceAll("-", "");
                        authSecretTokenIn.setToken(token);
                        authSecretTokenIn.setTokenExpiry(getTokenExpiry(xhpcInternetUser));
                        authSecretTokenRepository.save(authSecretTokenIn);
                    }
                    tokenResponse.setAccessToken(token);
                    Instant te = authSecretTokenIn.getTokenExpiry().toInstant();
                    tokenResponse.setTokenAvailableTime(Long.valueOf(ChronoUnit.SECONDS.between(Instant.now(), te)).intValue());
                    tokenResponse.setSuccStat(0);
                    tokenResponse.setFailReason(0);
                    resp.setRet(EvcsConst.RET_SUCC);
                    resp.setMsg("Query token success");
                    resp.setData(JSONUtil.toJSONString(tokenResponse));
                }
            } else {
                resp.setMsg("Cooperation settings or start time are not valid");
            }
        }
        return resp;
    }

    private Date getTokenExpiry(XhpcInternetUser xhpcInternetUser) {

        Instant cooperationEndTime = xhpcInternetUser.getCooperationEndTime();
        LocalDateTime now = LocalDateTime.now();
        Instant tokenEndtime = now.plusSeconds(7200).toInstant(ZoneId.systemDefault().getRules().getOffset(now));
        if (tokenEndtime.isAfter(cooperationEndTime)) {
            return Date.from(cooperationEndTime);
        } else {
            return Date.from(tokenEndtime);
        }
    }



    @PostMapping("/v10/query_token")
    public CommonResponse queryTokenV10(@RequestHeader(value = "enc.out", defaultValue = "true") String encout,
                                        @RequestBody TokenRequest tokenRequest) throws IOException {
        log.debug("<<query token request body: " + tokenRequest);
        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        String operatorID = tokenRequest.getOperatorId();
        if (operatorID == null) {
            String decodedData = (String) tokenRequest.getAdditionalProperties().get("Data");
            tokenRequest = JSONUtil.readParams(decodedData, TokenRequest.class);
        }
        if (tokenRequest == null) {
            resp.setMsg("Request params validation failed");
        } else {
            operatorID = tokenRequest.getOperatorId();
            TokenResponse tokenResponse = new TokenResponse();
            tokenResponse.setOperatorId(REDIS.getCacheObject("global:EVCS_OPID"));
            tokenResponse.setSuccStat(0);
            tokenResponse.setFailReason(0);
            XhpcInternetUser xhpcInternetUser =
                    xhpcInternetUserRepository.findByOperatorIdEvcsLikeAndCooperationStartTimeBeforeAndCooperationEndTimeAfter(tokenRequest.getOperatorId(), Instant.now(), Instant.now());
            if (xhpcInternetUser != null) {
                String operatorSecret = tokenRequest.getOperatorSecret();
                AuthSecretToken authSecretTokenIn =
                        authSecretTokenRepository.findByStatusAndOperatorId3irdptyAndSecretTokenTypeAndOperatorSecret(2,
                                operatorID, AuthSecretToken.SECRET_TOKEN_TYPE_IN, operatorSecret).orElse(null);
                if (authSecretTokenIn == null) {
                    resp.setRet("4003");
                    resp.setMsg("Invalid OperatorID/Secret");
                    tokenResponse.setSuccStat(1);
                    tokenResponse.setFailReason(2);
                } else {
                    String token;
                    if (authSecretTokenIn.getTokenExpiry() != null && !authSecretTokenIn.getTokenExpiry().before(Calendar.getInstance().getTime())) {
                        token = authSecretTokenIn.getToken();
                    } else {
                        token = UUID.randomUUID().toString().replaceAll("-", "");
                        authSecretTokenIn.setToken(token);
                        authSecretTokenIn.setTokenExpiry(getTokenExpiry(xhpcInternetUser));
                        authSecretTokenRepository.save(authSecretTokenIn);
                    }
                    tokenResponse.setAccessToken(token);
                    Instant te = authSecretTokenIn.getTokenExpiry().toInstant();
                    tokenResponse.setTokenAvailableTime(Long.valueOf(ChronoUnit.SECONDS.between(Instant.now(), te)).intValue());
                    tokenResponse.setSuccStat(0);
                    tokenResponse.setFailReason(0);
                    resp.setRet(EvcsConst.RET_SUCC);
                    resp.setMsg("Query token success");
                    resp.setData(JSONUtil.toJSONString(tokenResponse));
                }
            } else {
                resp.setMsg("Cooperation settings or start time are not valid");
            }
        }
        return resp;
    }
    @PostMapping("/v20/query_token")
    public CommonResponse queryTokenV20(@RequestHeader(value = "enc.out", defaultValue = "true") String encout,
                                        @RequestBody TokenRequest tokenRequest) throws IOException {
        log.debug("<<query token request body: " + tokenRequest);
        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        String operatorID = tokenRequest.getOperatorId();
        if (operatorID == null) {
            String decodedData = (String) tokenRequest.getAdditionalProperties().get("Data");
            tokenRequest = JSONUtil.readParams(decodedData, TokenRequest.class);
        }
        if (tokenRequest == null) {
            resp.setMsg("Request params validation failed");
        } else {
            operatorID = tokenRequest.getOperatorId();
            TokenResponse tokenResponse = new TokenResponse();
            tokenResponse.setOperatorId(REDIS.getCacheObject("global:EVCS_OPID"));
            tokenResponse.setSuccStat(0);
            tokenResponse.setFailReason(0);
            XhpcInternetUser xhpcInternetUser =
                    xhpcInternetUserRepository.findByOperatorIdEvcsLikeAndCooperationStartTimeBeforeAndCooperationEndTimeAfter(tokenRequest.getOperatorId(), Instant.now(), Instant.now());
            if (xhpcInternetUser != null) {
                String operatorSecret = tokenRequest.getOperatorSecret();
                AuthSecretToken authSecretTokenIn =
                        authSecretTokenRepository.findByStatusAndOperatorId3irdptyAndSecretTokenTypeAndOperatorSecret(3,
                                operatorID, AuthSecretToken.SECRET_TOKEN_TYPE_IN, operatorSecret).orElse(null);
                if (authSecretTokenIn == null) {
                    resp.setRet("4003");
                    resp.setMsg("Invalid OperatorID/Secret");
                    tokenResponse.setSuccStat(1);
                    tokenResponse.setFailReason(2);
                } else {
                    String token;
                    if (authSecretTokenIn.getTokenExpiry() != null && !authSecretTokenIn.getTokenExpiry().before(Calendar.getInstance().getTime())) {
                        token = authSecretTokenIn.getToken();
                    } else {
                        token = UUID.randomUUID().toString().replaceAll("-", "");
                        authSecretTokenIn.setToken(token);
                        authSecretTokenIn.setTokenExpiry(getTokenExpiry(xhpcInternetUser));
                        authSecretTokenRepository.save(authSecretTokenIn);
                    }
                    tokenResponse.setAccessToken(token);
                    Instant te = authSecretTokenIn.getTokenExpiry().toInstant();
                    tokenResponse.setTokenAvailableTime(Long.valueOf(ChronoUnit.SECONDS.between(Instant.now(), te)).intValue());
                    tokenResponse.setSuccStat(0);
                    tokenResponse.setFailReason(0);
                    resp.setRet(EvcsConst.RET_SUCC);
                    resp.setMsg("Query token success");
                    resp.setData(JSONUtil.toJSONString(tokenResponse));
                }
            } else {
                resp.setMsg("Cooperation settings or start time are not valid");
            }
        }
        return resp;
    }

    /**
     * 用于平台之间认证Token的申请
     * @param encout
     * @param tokenRequest
     * @return
     * @throws IOException
     */
    @PostMapping("/v40/query_token")
    public CommonResponse queryTokenV40(@RequestHeader(value = "enc.out", defaultValue = "true") String encout,
                                     @RequestBody TokenRequest tokenRequest) throws IOException {

        log.debug("<<query token request body: " + tokenRequest);
        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        String operatorID = tokenRequest.getOperatorId();
        if (operatorID == null) {
            String decodedData = (String) tokenRequest.getAdditionalProperties().get("Data");
            tokenRequest = JSONUtil.readParams(decodedData, TokenRequest.class);
        }
        if (tokenRequest == null) {
            resp.setMsg("Request params validation failed");
        } else {
            operatorID = tokenRequest.getOperatorId();
            TokenResponse tokenResponse = new TokenResponse();
            //tokenResponse.setOperatorId(REDIS.getCacheObject("global:EVCS_OPID"));
            tokenResponse.setOperatorId("MA6DFCTD5");
            tokenResponse.setSuccStat(0);
            tokenResponse.setFailReason(0);
            XhpcInternetUser xhpcInternetUser =
                    xhpcInternetUserRepository.findByOperatorIdEvcsLikeAndCooperationStartTimeBeforeAndCooperationEndTimeAfter(tokenRequest.getOperatorId(), Instant.now(), Instant.now());
            if (xhpcInternetUser != null) {
                String operatorSecret = tokenRequest.getOperatorSecret();
                AuthSecretToken authSecretTokenIn =
                        authSecretTokenRepository.findByStatusAndOperatorId3irdptyAndSecretTokenTypeAndOperatorSecret(4,
                                operatorID, AuthSecretToken.SECRET_TOKEN_TYPE_IN, operatorSecret).orElse(null);
                if (authSecretTokenIn == null) {
                    resp.setRet("4003");
                    resp.setMsg("Invalid OperatorID/Secret");
                    tokenResponse.setSuccStat(1);
                    tokenResponse.setFailReason(2);
                } else {
                    String token;
                    if (authSecretTokenIn.getTokenExpiry() != null && !authSecretTokenIn.getTokenExpiry().before(Calendar.getInstance().getTime())) {
                        token = authSecretTokenIn.getToken();
                    } else {
                        token = UUID.randomUUID().toString().replaceAll("-", "");
                        authSecretTokenIn.setToken(token);
                        authSecretTokenIn.setTokenExpiry(getTokenExpiry(xhpcInternetUser));
                        authSecretTokenRepository.save(authSecretTokenIn);
                    }
                    tokenResponse.setAccessToken(token);
                    Instant te = authSecretTokenIn.getTokenExpiry().toInstant();
                    tokenResponse.setTokenAvailableTime(Long.valueOf(ChronoUnit.SECONDS.between(Instant.now(), te)).intValue());
                    tokenResponse.setSuccStat(0);
                    tokenResponse.setFailReason(0);
                    resp.setRet(EvcsConst.RET_SUCC);
                    resp.setMsg("Query token success");
                    resp.setData(JSONUtil.toJSONString(tokenResponse));

                    System.out.println("========/v40/query_token==============="+tokenResponse.toString());
                }
            } else {
                resp.setMsg("Cooperation settings or start time are not valid");
            }
        }


        System.out.println("========/v40/query_token==============="+resp.toString());
        return resp;
    }


    /**
     * 用于平台之间认证Token的申请
     * @param encout
     * @param tokenRequest
     * @return
     * @throws IOException
     */
    @PostMapping("/v50/query_token")
    public CommonResponse queryTokenV50(@RequestHeader(value = "enc.out", defaultValue = "true") String encout,
                                        @RequestBody TokenRequest tokenRequest) throws IOException {

        log.debug("<<query token request body: " + tokenRequest);
        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        String operatorID = tokenRequest.getOperatorId();
        if (operatorID == null) {
            String decodedData = (String) tokenRequest.getAdditionalProperties().get("Data");
            tokenRequest = JSONUtil.readParams(decodedData, TokenRequest.class);
        }
        if (tokenRequest == null) {
            resp.setMsg("Request params validation failed");
        } else {
            operatorID = tokenRequest.getOperatorId();
            TokenResponse tokenResponse = new TokenResponse();
            //tokenResponse.setOperatorId(REDIS.getCacheObject("global:EVCS_OPID"));
            tokenResponse.setOperatorId("MA6DFCTD5");
            tokenResponse.setSuccStat(0);
            tokenResponse.setFailReason(0);
            XhpcInternetUser xhpcInternetUser =
                    xhpcInternetUserRepository.findByOperatorIdEvcsLikeAndCooperationStartTimeBeforeAndCooperationEndTimeAfter(tokenRequest.getOperatorId(), Instant.now(), Instant.now());
            if (xhpcInternetUser != null) {
                String operatorSecret = tokenRequest.getOperatorSecret();
                AuthSecretToken authSecretTokenIn =
                        authSecretTokenRepository.findByStatusAndOperatorId3irdptyAndSecretTokenTypeAndOperatorSecret(5,
                                operatorID, AuthSecretToken.SECRET_TOKEN_TYPE_IN, operatorSecret).orElse(null);
                if (authSecretTokenIn == null) {
                    resp.setRet("4003");
                    resp.setMsg("Invalid OperatorID/Secret");
                    tokenResponse.setSuccStat(1);
                    tokenResponse.setFailReason(2);
                } else {
                    String token;
                    if (authSecretTokenIn.getTokenExpiry() != null && !authSecretTokenIn.getTokenExpiry().before(Calendar.getInstance().getTime())) {
                        token = authSecretTokenIn.getToken();
                    } else {
                        token = UUID.randomUUID().toString().replaceAll("-", "");
                        authSecretTokenIn.setToken(token);
                        authSecretTokenIn.setTokenExpiry(getTokenExpiry(xhpcInternetUser));
                        authSecretTokenRepository.save(authSecretTokenIn);
                    }
                    tokenResponse.setAccessToken(token);
                    Instant te = authSecretTokenIn.getTokenExpiry().toInstant();
                    tokenResponse.setTokenAvailableTime(Long.valueOf(ChronoUnit.SECONDS.between(Instant.now(), te)).intValue());
                    tokenResponse.setSuccStat(0);
                    tokenResponse.setFailReason(0);
                    resp.setRet(EvcsConst.RET_SUCC);
                    resp.setMsg("Query token success");
                    resp.setData(JSONUtil.toJSONString(tokenResponse));

                    System.out.println("========/v50/query_token==============="+tokenResponse.toString());
                }
            } else {
                resp.setMsg("Cooperation settings or start time are not valid");
            }
        }
        return resp;
    }
}
