package com.ozs.account.controller;

import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletResponse;

import com.ozs.account.service.AccountInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ozs.account.api.AccountInfoAPI;
import com.ozs.account.dto.UserDTO;
import com.ozs.account.util.JWTTool;
import com.ozs.account.util.R;
import com.ozs.account.util.S;

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

@Api("用户登录相关接口")
@RestController
public class AccountInfoController implements AccountInfoAPI {

	private final Logger log = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private AccountInfoService accountInfoService;
	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Override
	@ApiOperation("用户登录")
	@PostMapping("/account/login")
	public R<UserDTO> login(@RequestBody UserDTO user, HttpServletResponse response) {
		try {
			R<UserDTO> result = accountInfoService.login(user, response);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@Override
	@ApiOperation("获取用户类型 1前台用户 2后端管理用户")
	@GetMapping("/account/getUserType")
	public Integer getUserType(@RequestParam("userId") String userId) {
		try {
			Integer result = accountInfoService.getUserType(userId);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	@ApiOperation(value = "创建token")
	@ApiImplicitParams({
			@ApiImplicitParam(paramType = "query", name = "id", value = "账号id", required = true, dataType = "String"),
			@ApiImplicitParam(paramType = "query", name = "subject", value = "企业id", required = false, dataType = "String"),
			@ApiImplicitParam(paramType = "query", name = "minutes", value = "生效时长，分钟", required = true, dataType = "Long") })
	@GetMapping("/account/createToken")
	public String createToken(@RequestParam("id") String id,
			@RequestParam(name = "subject", required = false) String subject, @RequestParam("minutes") long minutes) {
		try {
			return JWTTool.createJWT(id, subject, 60 * 1000 * minutes);
		} catch (Exception e) {
			log.error(e.getMessage());
			return "创建token异常";
		}
	}

	@ApiOperation(value = "通过token获取userId")
	@ApiImplicitParam(paramType = "query", name = "jwt", value = "jwt", required = true, dataType = "String")
	@GetMapping("/account/parseTokenId")
	public String parseTokenId(@RequestParam("jwt") String jwt) {
		Claims claims = null;
		try {
			claims = JWTTool.parseJWT(jwt);
		} catch (Exception e) {
			log.error(jwt);
			log.error(e.getMessage());
			return null;
		}
		return claims.getId();
	}

	@ApiOperation(value = "通过token获取第二参数")
	@ApiImplicitParam(paramType = "query", name = "jwt", value = "jwt", required = true, dataType = "String")
	@GetMapping("/account/parseTokenSubject")
	public String parseTokenSubject(@RequestParam("jwt") String jwt) {
		Claims claims = null;
		try {
			claims = JWTTool.parseJWT(jwt);
		} catch (Exception e) {
			log.error(e.getMessage());
			return null;
		}
		return claims.getSubject();
	}

	@ApiOperation(value = "保存token")
	@ApiImplicitParams({
			@ApiImplicitParam(paramType = "query", name = "id", value = "id", required = true, dataType = "String"),
			@ApiImplicitParam(paramType = "query", name = "token", value = "token", required = true, dataType = "String"),
			@ApiImplicitParam(paramType = "query", name = "minute", value = "生效时长，分钟", required = true, dataType = "int") })
	@GetMapping("/account/saveToken")
	public String saveToken(@RequestParam("id") String id, @RequestParam("token") String token,
			@RequestParam("minute") int minute) {
		Long expire1 = redisTemplate.getExpire(id, TimeUnit.MINUTES);
		log.info("token剩余时长-刷新前：{}分钟", expire1);
		redisTemplate.opsForValue().set(id, token, minute, TimeUnit.MINUTES);
		Long expire2 = redisTemplate.getExpire(id, TimeUnit.MINUTES);
		log.info("token剩余时长-刷新后：{}分钟", expire2);
		return "1";
	}

	@GetMapping("/account/deleteToken")
	public String deleteToken(@RequestParam("id") String id) {
		log.info("id for token : {}", id);
		Boolean result = false;
		if (id == null) {
			return "1";
		}
		try {
			result = redisTemplate.delete(id);
		} catch (Exception e) {
			log.error(e.getMessage());
			return "-1";
		}
		if (result) {
			return "1";
		} else {
			return "-1";
		}
	}

	@PostMapping("/account/deleteTokenBatch")
	public String deleteTokenBatch(@RequestBody List<String> ids) {
		if (ids == null) {
			return "1";
		}
		try {
			redisTemplate.delete(ids);
		} catch (Exception e) {
			log.error(e.getMessage());
			return "-1";
		}
		return "1";
	}

	@ApiOperation("判断账号ID对应的token是否存在")
	@GetMapping("/account/getTokenByAccountId")
	public String getTokenByAccountId(String accountId) {
		Object token = redisTemplate.opsForValue().get(accountId);
		if (token != null) {
			return token.toString();
		}
		return null;
	}

	@ApiOperation("刷新token")
	@ApiImplicitParams({ @ApiImplicitParam(name = "accountId", value = "账号ID", required = true, paramType = "query"),
			@ApiImplicitParam(name = "minute", value = "保存时间，单位分钟", required = true, paramType = "query", dataType = "Int") })
	@GetMapping("/account/refreshToken")
	public String refreshToken(String accountId, int minute) {
		Boolean result = false;
		try {
			Long expire1 = redisTemplate.getExpire(accountId, TimeUnit.MINUTES);
			log.info("token剩余时长-刷新前：{}分钟", expire1);
			result = redisTemplate.expire(accountId, minute, TimeUnit.MINUTES);
			Long expire2 = redisTemplate.getExpire(accountId, TimeUnit.MINUTES);
			log.info("token剩余时长-刷新后：{}分钟", expire2);
		} catch (Exception e) {
			log.error(e.getMessage());
			return "-1";
		}
		if (result) {
			return "1";
		} else {
			return "-1";
		}
	}

}
