package com.github.wxiaoqi.security.auth.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.auth.service.AuthService;
import com.github.wxiaoqi.security.auth.util.user.JwtAuthenticationRequest;
import com.github.wxiaoqi.security.common.constant.RequestTypeConstants;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.ClientUtil;
import com.github.wxiaoqi.security.common.util.EntityUtils;
import com.github.wxiaoqi.security.common.util.IpUtil;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.github.wxiaoqi.security.common.util.result.JsonResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

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

@Api(tags = "用户登录")
@RestController
@RequestMapping("jwt")
@Slf4j
public class AuthController {
    @Value("${jwt.token-header}")
    private String tokenHeader;

    @Autowired
    @Qualifier("baseAuthService")
    private AuthService authService;

    @Autowired
    @Qualifier("appAuthService")
    private AuthService appAuthService;

    @RequestMapping(value = "token", method = RequestMethod.POST)
    public ObjectRestResponse<String> createAuthenticationToken(
            @RequestBody JwtAuthenticationRequest authenticationRequest,
            HttpServletRequest request) throws Exception {
        log.info(authenticationRequest.getUsername()+" require logging...");
        // keliii 分请求类型处理token
        String requestType = request.getHeader(RequestTypeConstants.HEADER_KEY);
        if (requestType == null || requestType.trim().equals("")) {
            requestType = RequestTypeConstants.BASE;
        }
        final String token;
        if (RequestTypeConstants.APP.equals(requestType)) {
            token = appAuthService.login(authenticationRequest);
        } else {
            token = authService.login(authenticationRequest);
        }
        return new ObjectRestResponse<String>().data(token);
    }

    @RequestMapping(value = "token/small", method = RequestMethod.POST)
    public ObjectRestResponse<String> createAuthenticationTokenSmall(
            @RequestBody JwtAuthenticationRequest authenticationRequest,
            HttpServletRequest request) throws Exception {
        log.info(authenticationRequest.getUsername()+" require logging...");
        // keliii 分请求类型处理token
        return authService.loginSmall(authenticationRequest);
    }

    @RequestMapping(value = "refresh", method = RequestMethod.GET)
    public ObjectRestResponse<String> refreshAndGetAuthenticationToken(
            HttpServletRequest request) throws Exception {
        String token = request.getHeader(tokenHeader);
        String refreshedToken = authService.refresh(token);
        return new ObjectRestResponse<String>().data(refreshedToken);
    }

    @RequestMapping(value = "verify", method = RequestMethod.GET)
    public ObjectRestResponse<?> verify(String token) throws Exception {
        authService.validate(token);
        return new ObjectRestResponse<>();
    }
    @RequestMapping(value = "/sendsms", method = RequestMethod.POST)
    public JSONObject sendsms(@RequestParam(value="username",defaultValue="")String  username, @RequestParam(value="type",defaultValue="0")Integer type)throws Exception{
        log.info(username+"----require sendsms...");
        return appAuthService.sendsms(username,type);
    }
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public JSONObject register(@RequestParam(value="username",defaultValue="")String  username,
                              @RequestParam(value="mobilecode",defaultValue="")String mobilecode,
                              @RequestParam(value="password",defaultValue="")String  password,
                               @RequestParam(value="code",defaultValue="")String  code)throws Exception{
        log.info(username+"----require register...");
        JSONObject data=appAuthService.register(username,mobilecode,password,code);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JwtAuthenticationRequest authenticationRequest=new JwtAuthenticationRequest();
            authenticationRequest.setUsername(username);
            authenticationRequest.setPassword(password);
            String token=appAuthService.login(authenticationRequest);
            data.put("token",token);
        }
        return data;
    }
    @RequestMapping(value = "/wxregister", method = RequestMethod.POST)
    public JSONObject wxregister(
            @RequestParam(value="username",defaultValue="")String  username,
            @RequestParam(value="mobilecode",defaultValue="")String mobilecode,
            @RequestParam(value="password",defaultValue="")String  password,
            @RequestParam(value="nickname",defaultValue="")String  nickname,
            @RequestParam(value="headimgurl",defaultValue="")String  headimgurl,
            @RequestParam(value="openid",defaultValue="")String  openid,
            @RequestParam(value="unionid",defaultValue="")String  unionid,
            @RequestParam(value="type",defaultValue="0")Integer  type,
            @RequestParam(value="isQQ",defaultValue="0")Integer  isQQ,
            @RequestParam(value="code",defaultValue="")String  code
    )throws Exception{
        log.info(username+"----require wxregister...");
        JSONObject data=appAuthService.wxregister( username, mobilecode, password, nickname,
                headimgurl, openid, unionid,type,isQQ,code);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                String token=appAuthService.getToken(username,result.getInteger("userId"));
                data.put("token",token);
            }
        }
        return data;
    }
    @RequestMapping(value = "/checkBindWechat", method = RequestMethod.POST)
    public JSONObject checkBindWechat(@RequestParam(value="username",defaultValue="")String  username)throws Exception{
        log.info(username+"----require checkBindWechat...");
        return appAuthService.checkBindWechat(username);
    }
    @RequestMapping(value = "/wxlogin", method = RequestMethod.POST)
    public JSONObject wxlogin(@RequestParam(value="openid",defaultValue="")String  openid,
                              @RequestParam(value="isQQ",defaultValue="0")Integer isQQ,
                              @RequestParam(value="code",defaultValue="")String  code)throws Exception{
        log.info(openid+"----require wxlogin...");
        JSONObject data=appAuthService.wxlogin(openid,isQQ,code);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                String token=appAuthService.getToken(result.getString("username"),result.getInteger("userId"));
                data.put("token",token);
            }
        }
        return data;
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public JSONObject login(@RequestParam(value="username",defaultValue="")String  username,
                            @RequestParam(value="mobilecode",defaultValue="")String mobilecode,
                            @RequestParam(value="password",defaultValue="")String  password,
                            @RequestParam(value="type",defaultValue="1")Integer  type,
                            @RequestParam(value="code",defaultValue="")String  code)throws Exception{
        log.info(username+"----require login...");

        JSONObject data=appAuthService.tlogin(username,password,mobilecode,type,code);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                String token=appAuthService.getToken(username,result.getInteger("userId"));
                data.put("token",token);
            }
        }
        return data;
    }


    @RequestMapping(value = "other/sendsms", method = RequestMethod.GET)
    public JSONObject otherSendsms(@RequestParam(value="username",defaultValue="")String  username, @RequestParam(value="type",defaultValue="0")Integer type)throws Exception{
        log.info(username+"----require sendsms...");
        return appAuthService.sendsms(username,type);
    }

    @RequestMapping(value = "/otherLogin", method = RequestMethod.POST)
    public JSONObject otherLogin(@RequestBody Map<String,Object> params)throws Exception{
        log.info("----require otherLogin...");
        String  username=params.get("username")==null?"":params.get("username").toString();
        String mobilecode=params.get("mobilecode")==null?"":params.get("mobilecode").toString();
        String  password=params.get("password")==null?"":params.get("password").toString();
        Integer  type=params.get("type")==null?1:params.get("type").hashCode();
        String  code=params.get("code")==null?"":params.get("code").toString();
        JSONObject data=appAuthService.tlogin(username,password,mobilecode,type,code);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                Integer positionId=result.getInteger("positionId")==null?0:result.getInteger("positionId");
                if (positionId==4 || positionId==1 || positionId==2 || positionId==3){
                    String token=appAuthService.getToken(username,result.getInteger("userId"));
                    data.put("token",token);
                }else {
                    data.put("status",ResultCode.FAILED_CODE);
                    data.put("message","非内部员工，无法登录");
                }
            }
        }
        return data;
    }
    
    @RequestMapping(value = "/reset", method = RequestMethod.POST)
    public JSONObject reset(@RequestParam(value="username",defaultValue="")String  username,
                               @RequestParam(value="mobilecode",defaultValue="")String mobilecode,
                               @RequestParam(value="password",defaultValue="")String  password)throws Exception{
        log.info(username+"----require reset...");
        JSONObject data=appAuthService.reset(username,mobilecode,password);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                String token=appAuthService.getToken(username,result.getInteger("userId"));
                data.put("token",token);
            }
        }
        return data;
    }


    /**
     * 根据用户id登录 Unbelievable ! ! !
     * @param userId
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/applet/uid/login")
    public JSONObject appletLoginByUserId(@RequestParam("userId") Integer userId) throws Exception{
        log.info(userId+"----require appletLoginByUserId...");
        JSONObject data = appAuthService.appletLoginByUserId(userId);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                String token=appAuthService.getToken(String.valueOf(result.get("username")),result.getInteger("userId"));
                data.put("token",token);
            }
        }
        return data;
    }

    @PostMapping(value = "/applet/registry")
    public JSONObject registryWithApplet(
            @RequestParam(value="username",defaultValue="")String  username,
            @RequestParam(value="nickname",defaultValue="")String  nickname,
            @RequestParam(value="headimgurl",defaultValue="")String  headimgurl,
            @RequestParam(value="userid",defaultValue="0")Integer  userid)throws Exception {
        JSONObject data=appAuthService.appletRegistry(username,nickname,headimgurl,userid);
        if(data!=null&&data.getInteger("status")== ResultCode.SUCCESS_CODE){
            JSONObject result=data.getJSONObject("data");
            if(result==null){
                data.put("status",1001);
            }else {
                String token=appAuthService.getToken(String.valueOf(result.get("username")),result.getInteger("userId"));
                data.put("token",token);
            }
        }
        return data;
    }

    @PostMapping("/imi/login")
    public  JSONObject loginImiWithToken(){
        return JsonResultUtil.createSuccessResultWithObj(authService.loginImiWithToken());
    }

    /**
     * 检查token是否失效
     * @param token
     * @return
     */
    @RequestMapping(value = "checkToken", method = RequestMethod.GET)
    public ObjectRestResponse checkToken(String token){
        return authService.checkToken(token);
    }


    @RequestMapping(value = "/updUsername", method = RequestMethod.POST)
    public ObjectRestResponse updUsername(@RequestParam(value="username",defaultValue="")String  username,
                            @RequestParam(value="mobilecode",defaultValue="")String mobilecode,
                                  HttpServletRequest request)throws Exception {
        log.info(username + "----require updUsername...");
        String token = request.getHeader(tokenHeader);
        return appAuthService.updUsername(username, mobilecode, token);

    }

}
