package com.lutao.cloud.auth.endpoint;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.lutao.cloud.admin.api.dto.SysUserDTO;
import com.lutao.cloud.auth.service.CloudTokenDealServiceImpl;
import com.lutao.cloud.admin.api.entity.SysTenant;
import com.lutao.cloud.admin.api.feign.RemoteTenantService;
import com.lutao.cloud.common.core.constant.SecurityConstants;
import com.lutao.cloud.common.core.util.MessageInfo;
import com.lutao.cloud.common.security.annotation.Inner;
import com.lutao.cloud.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

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

/**

 * @date 2018/6/24 删除token端点
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/token")
public class CloudTokenEndpoint{

	private final ClientDetailsService clientDetailsService;

	private final CloudTokenDealServiceImpl dealService;

	private final RemoteTenantService tenantService;

	/**
	 * 认证页面
	 * @param modelAndView
	 * @param error 表单登录失败处理回调的错误信息
	 * @return ModelAndView
	 */
	@GetMapping("/login")
	public ModelAndView require(ModelAndView modelAndView, @RequestParam(required = false) String error){
		MessageInfo<List<SysTenant>> tenantList = tenantService.list(SecurityConstants.FROM_IN);
		modelAndView.setViewName("ftl/login");
		modelAndView.addObject("error", error);
		modelAndView.addObject("tenantList", tenantList.getData());
		return modelAndView;
	}

	/**
	 * 确认授权页面
	 * @param request
	 * @param session
	 * @param modelAndView
	 * @return
	 */
	@GetMapping("/confirm_access")
	public ModelAndView confirm(HttpServletRequest request, HttpSession session, ModelAndView modelAndView){
		Map<String, Object> scopeList = (Map<String, Object>) request.getAttribute("scopes");
		modelAndView.addObject("scopeList", scopeList.keySet());

		Object auth = session.getAttribute("authorizationRequest");
		if (auth != null){
			AuthorizationRequest authorizationRequest = (AuthorizationRequest) auth;
			ClientDetails clientDetails = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
			modelAndView.addObject("app", clientDetails.getAdditionalInformation());
			modelAndView.addObject("user", SecurityUtils.getUser());
		}

		modelAndView.setViewName("ftl/confirm");
		return modelAndView;
	}

	/**
	 * 退出token
	 * @param authHeader Authorization
	 */
	@DeleteMapping("/logout")
	public MessageInfo logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader){
		if (StrUtil.isBlank(authHeader)){
			return MessageInfo.ok(Boolean.FALSE, "退出失败，token 为空");
		}

		String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();
		return delToken(tokenValue);
	}

	/**
	 * 令牌管理调用
	 * @param token token
	 * @return
	 */
	@Inner
	@DeleteMapping("/{token}")
	public MessageInfo<Boolean> delToken(@PathVariable("token") String token){
		return dealService.removeToken(token);
	}

	/**
	 * 查询token
	 * Inner 注解供内部使用，默认true
	 * Inner 值为false的时候可以供外部直接访问
	 * @param page 分页参数
	 * @param username 用户名
	 * @return
	 */
	@Inner
	@GetMapping("/page")
	public MessageInfo<Page> tokenList(Page page, String username){
		// 根据username 查询 token 列表
		if (StrUtil.isNotBlank(username)){
			return dealService.queryTokenByUsername(page, username);
		}

		return dealService.queryToken(page);
	}


	/**
	 * 根据token获取用户信息和权限信息
	 * @param
	 * @return
	 */
//	@Inner
	@GetMapping("/check")
	public  MessageInfo checkUser(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader){
		if (StrUtil.isBlank(authHeader)){
			return MessageInfo.ok(Boolean.FALSE, "token为空");
		}
		String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();

		return dealService.userByToken(tokenValue);

	}

	/**
	 * 查询token
	 * 根据用户名查询token
	 * @param username 用户名
	 * @return
	 */
	@Inner
	@DeleteMapping("/delTokenByUsername")
	public MessageInfo<Boolean> delTokenByUsername(@RequestParam("username") String username){
		// 根据username 查询 token 列表
		log.info("delTokenByUsername:{}",username);
		if (StrUtil.isNotBlank(username)){
			List tokenList = dealService.queryTokenByUsername(username);
			if (tokenList != null){
				tokenList.forEach( token ->{
					JSONObject jsonObject = JSONUtil.parseObj(token);
					MessageInfo<Boolean> delRet = delToken(jsonObject.getStr("value"));
				});
			}
		}
		return MessageInfo.ok(Boolean.TRUE);
	}
}
