package com.bcxin.ars.rest;

import com.alibaba.fastjson.JSON;
import com.bcxin.ars.dto.AjaxResult;
import com.bcxin.ars.exception.ArsException;
import com.bcxin.ars.model.SecurityCompany;
import com.bcxin.ars.model.User;
import com.bcxin.ars.model.sys.ThirdParty;
import com.bcxin.ars.service.LoginLogService;
import com.bcxin.ars.service.SecurityCompanyService;
import com.bcxin.ars.service.UserService;
import com.bcxin.ars.service.sys.ThirdPartyService;
import com.bcxin.ars.service.util.ArsUtil;
import com.bcxin.ars.util.Constants;
import com.bcxin.ars.util.StringUtil;
import com.bcxin.ars.util.TokenUtil;
import com.bcxin.ars.util.redis.RedisUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 第三方对接信息控制器
 *
 * @author linqinglin
 * @Date 2020-05-15 10:14:15
 */
@Controller
@RequestMapping("thirdParty")
public class ThirdPartyController {

    Logger logger = LoggerFactory.getLogger(ThirdPartyController.class);

    @Autowired
    ThirdPartyService thirdPartyService;

    @Autowired
    SecurityCompanyService securityCompanyService;

    @Autowired
    UserService userService;

    @Autowired
    LoginLogService loginLogService;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    ArsUtil arsUtil;

    @Value("${redis.shiro.expire}")
    public String  shiroExpire="0";

    private final String keyPrefix = "ARS:shiro_redis_session:";


    @RequestMapping("accessToken")
    @ResponseBody
    public AjaxResult accessToken(String clientId, String clientSecret,HttpServletRequest request) throws Exception {
        AjaxResult result = new AjaxResult();
        try {
            Long id = Long.parseLong(clientId);
            ThirdParty thirdParty = thirdPartyService.findById(id);
            if(thirdParty != null && thirdParty.getClientSecret().equals(clientSecret)){

                String accessToken = TokenUtil.getInstance().makeToken();
                result.setToken(accessToken);
                if(thirdParty.getComId() != null){
                    comLogin(thirdParty.getComId(),accessToken,request);
                }else {
                    User user = new User();
                    user.setUsername(thirdParty.getId().toString());
                    user.setPlatform(99);
                    user.setId(thirdParty.getId());
                    user.setRealname(thirdParty.getName());
                    //半小时内有效
                    redisUtil.set(Constants.ARS_SHIRO_REDIS_TOKEN_KEY + accessToken, JSON.toJSONString(user), 30 * 60);
                }
                result.setSuccessful(true);
            }else{
                result.setSuccessful(false);
                result.setMsg("clientId不存在或者秘钥错误");
            }
        }catch (Exception e){
            result.setSuccessful(false);
            result.setMsg("clientId不存在或者秘钥错误");
        }
        return result;
    }


    /***
     * 登陆
     * @param comId 用户信息
     * @return
     * @throws Exception
     */
    private void comLogin(Long comId,String accessToken, HttpServletRequest request) throws Exception{
        UsernamePasswordToken token = new UsernamePasswordToken(comId.toString(), comId.toString());
        Subject currentUser = SecurityUtils.getSubject();
        try {
            token.setRememberMe(true);
            token.setHost(Constants.SaaSCode);
            try {
                currentUser.login(token);
            } catch (AuthenticationException e) {
                logger.error(e.getMessage(), e);
                throw new ArsException("获取token失败");
            }
            // 判断是否登录成功！
            if (currentUser.isAuthenticated()) {
                Session session = currentUser.getSession();
                SecurityCompany securityCompany = securityCompanyService.findByComId(comId);
                if(securityCompany == null){
                    logger.error("公共安全服务平台公司id("+comId+")不存在");
                }
                User user = securityCompany.getUser();
                user.setAreaCode(securityCompany.getAreaCode());
                user.setComId(String.valueOf(comId));
                logger.info("当前登录用户是：" + user.getUsername());
                user.setSessionId(session.getId().toString());
                //半小时内有效
                redisUtil.set(Constants.ARS_SHIRO_REDIS_TOKEN_KEY + accessToken, JSON.toJSONString(user), 30 * 60);

                /***
                 * saas的SID
                 */
                //如果有key先做删除操作，再设置redis
                if(StringUtil.isNotEmpty(redisUtil.get(keyPrefix + accessToken))){
                    redisUtil.delete(keyPrefix + accessToken);
                }
                if(Integer.valueOf(shiroExpire)!=0) {
                    redisUtil.set(keyPrefix + accessToken, session.getId().toString(), Integer.valueOf(shiroExpire));
                }else{
                    redisUtil.set(keyPrefix + accessToken, session.getId().toString());
                }
                arsUtil.setCurrentUser(user, -1000);
                // 更新一下登陆状态
                user.setLoginstate(1);
                // 登录次数+1
                if (user.getLoginNum() != null) {
                    user.setLoginNum(user.getLoginNum() + 1);
                } else {
                    user.setLoginNum(1);
                }
                // 登录时间为当前时间
                user.setLoginDate(new Date());
                userService.updateLoginState(user);
                loginLogService.logIn(request);

            } else {
                throw new ArsException("获取token失败");
            }
        } catch (UnknownAccountException e) {
            logger.error(e.getMessage(), e);
            throw new ArsException("获取token失败");
        } catch (IncorrectCredentialsException e) {
            logger.error(e.getMessage(), e);
            throw new ArsException("获取token失败");
        } catch (ExcessiveAttemptsException e) {
            logger.error(e.getMessage(), e);
            throw new ArsException("获取token失败");
        } catch (AuthenticationException e) {
            logger.error(e.getMessage(), e);
            throw e;
        }
    }
}

