package com.yonge.cooleshow.auth.web.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.io.IOException;
import java.util.Base64;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.auth.core.service.CustomTokenServices;
import com.yonge.cooleshow.auth.service.SysUserService;
import com.yonge.cooleshow.common.controller.BaseController;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.security.AuthUser;
import com.yonge.cooleshow.common.security.SecurityUtils;

@RestController
@Api(tags = "认证服务")
public class TokenController extends BaseController {

	@Autowired
	private CustomTokenServices tokenService;
	
	@Autowired
	private ResourceServerTokenServices resourceServerTokenServices;
	
	@Autowired
	private TokenStore tokenStore;

	@Autowired
	private RestTemplate restTemplate;

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private SysUserService userService;

    @PostMapping(value = "/smsLogin",consumes = MediaType.APPLICATION_JSON_VALUE)
	@ApiOperation(value = "短信验证码的方式登录")
	@ApiImplicitParams({ @ApiImplicitParam(name = "smsCode", value = "验证码", required = true, dataType = "String"),
			@ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),
			@ApiImplicitParam(name = "clientId", value = "固定传 app", required = true, dataType = "String"),
			@ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String") })
    public Object smsLogin() {
		return succeed();
    }

    @GetMapping("/queryUserInfo")
    public SysUser queryUserInfo() {
		AuthUser authUser = SecurityUtils.getUser();
		if(authUser != null){
			SysUser sysUser = userService.get(authUser.getUserId());
			return userService.get(authUser.getUserId());
		}
		return null;
    }

	@ApiOperation(value = "获取用户信息")
    @GetMapping("/api/queryUserInfo")
    public Object apiQueryUserInfo() {
		AuthUser authUser = SecurityUtils.getUser();
		if(authUser != null){
			return succeed(userService.queryUserInfo(authUser.getUserId()));
		}
		return failed("获取用户信息失败");
    }
    
    @PostMapping(value = "/usernameLogin",consumes = MediaType.APPLICATION_JSON_VALUE)
	@ApiOperation(value = "手机号密码方式登录")
	@ApiImplicitParams({ @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String"),
			@ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),
			@ApiImplicitParam(name = "clientId", value = "固定传 app", required = true, dataType = "String"),
			@ApiImplicitParam(name = "username", value = "手机号", required = true, dataType = "String") })
    public Object usernameLogin() {
		return succeed();
    }

	@PostMapping(value = "/refreshToken",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	@ApiOperation(value = "刷新token")
	public HttpResponseResult refreshToken(String refreshToken, String clientId, String clientSecret) throws IOException {
		String url = "http://auth-server/oauth/token";

		String base64ClientCredentials = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes());

		HttpHeaders headers = new HttpHeaders();
		headers.add("Authorization", "Basic " + base64ClientCredentials);
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

		MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
		params.add("refresh_token", refreshToken);
		params.add("grant_type", "refresh_token");
		params.add("client_id", clientId);
		params.add("client_secret", clientSecret);

		HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(params, headers);

		ResponseEntity<String> resp = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

		return succeed(objectMapper.readValue(resp.getBody(), Map.class));
	}

	@PostMapping(value = "exit",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	@ApiOperation(value = "退出登录")
	public HttpResponseResult<String> logout(HttpServletRequest request) {
		
		String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
		if (StringUtils.isBlank(authHeader)) {
			return failed("退出失败，token 为空");
		}

		String tokenValue = authHeader.toLowerCase().replace(OAuth2AccessToken.BEARER_TYPE.toLowerCase(), StringUtils.EMPTY).trim();

		tokenService.revokeToken(tokenValue);

		return succeed("退出成功");
	}

	@PostMapping(value = "exit/{clientId}/{phone}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	@ApiOperation(value = "指定用户退出登录")
	public HttpResponseResult<String> exitByPhone(@PathVariable("clientId") String clientId, @PathVariable("phone") String phone) {

		return tokenService.revokeToken(clientId, phone) ? succeed("退出成功") : failed();
	}

	@GetMapping(value = "/checkToken",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	@ApiOperation(value = "检查token")
	public HttpResponseResult<Object> checkToken(HttpServletRequest request) throws IOException {

		String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
		if (StringUtils.isBlank(authHeader)) {
			return failed(HttpStatus.FORBIDDEN, "token 为空");
		}

		String tokenValue = authHeader.toLowerCase().replace(OAuth2AccessToken.BEARER_TYPE.toLowerCase(), StringUtils.EMPTY).trim();

		OAuth2AccessToken accessToken = resourceServerTokenServices.readAccessToken(tokenValue);
		if (accessToken == null) {
			return failed(HttpStatus.FORBIDDEN, "token 无效");
		}

		if (accessToken.isExpired()) {
			return failed(HttpStatus.FORBIDDEN, "token 已过期");
		}

		return succeed();
	}

}
