package com.ym.mec.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.Collection;
import java.util.Date;
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.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
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.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.auth.service.SysUserService;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.entity.ImResult;
import com.ym.mec.common.entity.ImUserModel;
import com.ym.mec.common.security.AuthUser;
import com.ym.mec.common.security.SecurityConstants;
import com.ym.mec.common.security.SecurityUtils;
import com.ym.mec.im.ImFeignService;

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

	@Autowired
	private DefaultTokenServices tokenService;
	
	@Autowired
	private TokenStore tokenStore;

	@Autowired
	private RestTemplate restTemplate;

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private SysUserService userService;

	@Autowired
	private ImFeignService imFeignService;
    
    @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());
			if(StringUtils.isEmpty(sysUser.getImToken())){
				ImResult register = imFeignService.register(new ImUserModel(sysUser.getId().toString(), sysUser.getUsername(), null));
				sysUser.setImToken(register.getToken());
				sysUser.setUpdateTime(new Date());
				userService.update(sysUser);
			}
			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) {

		Collection<OAuth2AccessToken> list = tokenStore.findTokensByClientIdAndUserName(clientId, SecurityConstants.PHONE_PRINCIPAL_PREFIX + phone);

		if (list == null || list.size() == 0) {
			list = tokenStore.findTokensByClientIdAndUserName(clientId, SecurityConstants.USERNAME_PRINCIPAL_PREFIX + phone);
		} else {
			list.addAll(tokenStore.findTokensByClientIdAndUserName(clientId, SecurityConstants.USERNAME_PRINCIPAL_PREFIX + phone));
		}
		if (list != null) {
			for (OAuth2AccessToken accessToken : list) {
				if (accessToken != null) {
					if (accessToken.getRefreshToken() != null) {
						tokenStore.removeRefreshToken(accessToken.getRefreshToken());
					}
					tokenStore.removeAccessToken(accessToken);
				}
			}
		}

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

}
