package com.inspect.ivs.service;

import com.inspect.base.core.constant.Color;
import com.inspect.base.core.exception.ServiceException;
import com.inspect.ivs.base.feign.domain.IvsResult;
import com.inspect.ivs.config.IvsUserConfig;
import com.inspect.ivs.constant.IvsConst;
import com.inspect.ivs.domain.IvsPassword;
import com.inspect.ivs.domain.IvsUser;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec;

@Component
public class IvsLoginService extends IvsCommonService {
    private static final Logger logger = LoggerFactory.getLogger(IvsLoginService.class);

    private final RedisTemplate redisTemplate;
    private final IvsUserConfig ivsUserConfig;

    //qinyl
    @Value("${spring.profiles.active}")
    private String activeProfile;

    public IvsLoginService(RedisTemplate redisTemplate, IvsUserConfig ivsUserConfig) {
        this.redisTemplate = redisTemplate;
        this.ivsUserConfig = ivsUserConfig;
    }

    public void run() {
        if (!"dev".equals(activeProfile)) {
            logger.info("=================IVS LOGIN....===============");
            String resultCode = "";

            while (!IvsConst.HTTP_STATUS_OK.equals(resultCode)) {
                resultCode = this.login().getResultCode();
                String cookie = this.getCookie();
                boolean flag = true;
                byte res = -1;
                switch (resultCode.hashCode()) {
                    case 48:
                        if (resultCode.equals(IvsConst.HTTP_STATUS_OK)) {
                            res = 0;
                        }
                        break;
                    case 1624175007:
                        if (resultCode.equals("119101305")) {
                            res = 2;
                        }
                        break;
                    case 1624175010:
                        if (resultCode.equals("119101308")) {
                            res = 1;
                        }
                        break;
                    case 1624175166:
                        if (resultCode.equals("119101359")) {
                            res = 3;
                        }
                }

                switch (res) {
                    case 0:
                        logger.info("IVS登录成功！");
                        break;
                    case 1:
                        logger.info("IVS 1！");
                        flag = false;
                    case 2:
                        logger.info("IVS 2！");
                        this.modifyPassword(flag, cookie);
                        this.modifyPassword(flag, cookie);
                        break;
                    case 3:
                        logger.info("IVS 3！");
                        this.modifyPresetPassword(cookie);
                        break;
                    default:
                        logger.info("IVS: {}", String.format("登录失败:%s,请参见IVS接口文档中错误码详情！", resultCode) );
                        throw new ServiceException(String.format("登录失败:%s,请参见IVS接口文档中错误码详情！", resultCode));
                }
            }
        } else {
            logger.info("=================环境没有ivs，无法登录===============");
        }
    }

    private IvsResult login() {
        logger.info("-------------------------ivs user: {}", this.queryUser());
        return this.http(HttpMethod.POST, IvsConst.URI_LOGIN)
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(this.queryUser())
                .exchangeToMono((res) -> {
                    List<String> header = res.headers().header(IvsConst.COOKIE_KEY);
                    System.out.println(header.size());
                    String token = (res.headers().header(IvsConst.COOKIE_KEY).get(0)).split("=")[1].split(";")[0];
                    logger.info(Color.YELLOW + "===================ivs token:{}" + Color.END, token);
                    this.setCookie(token);
                    return res.bodyToMono(IvsResult.class);
                }).block();
    }

    private void modifyPassword(boolean flag, String cookie) {
        logger.debug(flag ? "用户密码过期，需要修改！" : "用户首次登陆需要修改密码！");
        String code = (this.http(HttpMethod.PUT, "/users/userPassword/v1.0").contentType(MediaType.APPLICATION_JSON).header(IvsConst.COOKIE_SESSION_NAME, new String[]{cookie})).bodyValue(this.queryPassword()).retrieve().bodyToMono(String.class).toString();
        if (!IvsConst.HTTP_STATUS_OK.equals(code)) {
            throw new ServiceException(String.format("修改密码失败，错误码为:%s,请参见IVS接口文档中错误码详情！", new Object[]{code}));
        } else {
            this.reversePassword();
        }
    }

    private void modifyPresetPassword(String cookie) {
        logger.debug("本次登录的是预置账号，需要修改预置账号密码！");
        String code = ((RequestBodySpec) this.http(HttpMethod.PUT, IvsConst.URI_MODIFY_PRESET_PASSWORD).contentType(MediaType.APPLICATION_JSON).header(IvsConst.COOKIE_SESSION_NAME, new String[]{cookie})).bodyValue(this.queryUser()).retrieve().bodyToMono(String.class).toString();
        if (!IvsConst.HTTP_STATUS_OK.equals(code)) {
            throw new ServiceException(String.format("修改密码失败，错误码为:%s,请参见IVS接口文档中错误码详情！", new Object[]{code}));
        }
    }

    private void reversePassword() {
        Long increment = redisTemplate.opsForValue().increment(IvsConst.IVS_PASSWORD_NEW, 1L);
        if (increment == 10000L) {
            redisService.setCacheObject(IvsConst.IVS_PASSWORD_NEW, Integer.valueOf(0));
        }

    }

    private IvsUser queryUser() {
        String password = ivsUserConfig.getPassword();
        Long index = redisService.getCacheObject(IvsConst.IVS_PASSWORD_NEW);
        if (null != index && index.longValue() % 2L != 0L) {
            password = this.ivsUserConfig.getNewPassword();
        }

        return new IvsUser(ivsUserConfig.getUserName(), password);
    }

    private IvsPassword queryPassword() {
        Long index = redisService.getCacheObject(IvsConst.IVS_PASSWORD_NEW);
        return index % 2L == 0L ? new IvsPassword(ivsUserConfig.getPassword(), ivsUserConfig.getNewPassword()) : new IvsPassword(ivsUserConfig.getNewPassword(), ivsUserConfig.getPassword());
    }
}
