package com.crunii.micro.service.sysmgr.controller;

import com.crunii.micro.common.captcha.MicroCaptcha;
import com.crunii.micro.common.constants.CommonConstants;
import com.crunii.micro.common.dto.CaptchaInfo;
import com.crunii.micro.common.dto.Result;
import com.crunii.micro.common.utils.NanoIdUtil;
import com.crunii.micro.domain.dto.LoginInfoDto;
import com.crunii.micro.domain.dto.Worker;
import com.crunii.micro.domain.entity.main.TsmPropertyValue;
import com.crunii.micro.domain.repo.main.TsmPropertyValueRepo;
import com.crunii.micro.feign.client.dto.*;
import com.crunii.micro.service.sysmgr.constants.DataUriScheme;
import com.crunii.micro.service.sysmgr.dto.sysmgr.*;
import com.crunii.micro.service.sysmgr.service.LoginService;
import com.crunii.micro.web.mvc.CurrWorker;
import com.github.bingoohuang.patchca.utils.encoder.EncoderHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import static com.crunii.micro.service.sysmgr.constants.SysmgrConstants.*;

/**
 * @author 田平 create 2023-02-21 10:47:31
 */
@RefreshScope
@Api(value = "系统登录相关")
@Slf4j
@Controller
@RequestMapping("/LoginController")
public class LoginController {

	// 默认验证码
	@Value("${default_captcha:youthcq}")
	public String defaultCaptcha;
	private final MicroCaptcha microCaptcha;

	private final LoginService loginService;

	private static String env = "dev";

	static {
		env = System.getProperty("spring.profiles.active");
	}

	@Value("${spring.application.name}")
	private String appName;

	@Resource
	private TsmPropertyValueRepo tsmPropertyValueRepo;

	public LoginController(MicroCaptcha microCaptcha, LoginService loginService) {
		this.microCaptcha = microCaptcha;
		this.loginService = loginService;
	}


	@ApiOperation(value = "用户登录")
	@RequestMapping(path = "/login", method = { RequestMethod.POST })
	@ResponseBody
	public Result<Worker> login(@RequestBody LoginDto loginDto, HttpServletRequest request) {
		//当前调用的url
		String callUrl = "/" + appName + request.getRequestURI();
		String innerToken = request.getHeader(CommonConstants.HEADER_INNER_AUTH_TOKEN);
		List<String> codes = tsmPropertyValueRepo.findAllByPropCodeAndState(code, 1).stream().map(TsmPropertyValue::getValueCode).collect(Collectors.toList());
		Result<Worker> result = new Result<>();
		if (CommonConstants.SCOPE_WEB.equals(loginDto.getScope())) {
			String storeCaptcha = loginService.removeCaptchaKeyId(loginDto.getCaptchaKey());
			log.info("username:{},password:{}", loginDto.getUsername(), loginDto.getPassword());
			log.info("captchaKey:{},captcha:{},storeCaptcha:{}", loginDto.getCaptchaKey(), loginDto.getCaptcha(), storeCaptcha);
			if ((StringUtils.hasText(storeCaptcha) && storeCaptcha.equalsIgnoreCase(loginDto.getCaptcha())) || codes.contains(loginDto.getCaptcha())) {
				Worker worker = loginService.doLogin(request,loginDto.getUsername(), loginDto.getPassword(), loginDto.getScope(), callUrl);
				result.setData(worker);
			} else {
				result.setSuccess(false);
				result.setMsg("验证码错误！");
				result.setCode(Result.DEFAULT_ERROR_CODE);
			}
		} else if(CommonConstants.SCOPE_SSO.equals(loginDto.getScope()) && CommonConstants.INNER_AUTH_TOKEN.equals(innerToken)){
			// SSO登录过来的请求
			Worker worker = loginService.doLogin(request,loginDto.getUsername(), loginDto.getPassword(), loginDto.getScope(), callUrl);
			result.setData(worker);
		}else {
			// 这个功能存在安全风险 只能在dev、local环境运行
			if(!env.contains("prod")){
				Worker worker = loginService.doLogin(request, loginDto.getUsername(), loginDto.getPassword(), loginDto.getScope(), callUrl);
				result.setData(worker);
			}
		}
		return result;
	}

	@ApiOperation(value = "刷新token（只需要传当前token）")
	@RequestMapping(path = "/auth/refreshToken", method = RequestMethod.GET)
	@ResponseBody
	public Result<Worker> refreshToken(@CurrWorker @ApiIgnore Worker worker) {
		Result<Worker> result = new Result<>();
		Worker newWorker = loginService.doRefreshToken(worker);
		result.setData(newWorker);
		return result;
	}

	@ApiOperation(value = "根据token获取用户信息")
	@RequestMapping(path = "/auth/getUserInfo", method = RequestMethod.GET)
	@ResponseBody
	public Result<Worker> getUserInfo(@CurrWorker @ApiIgnore Worker worker) {
		Result<Worker> result = new Result<>();
		Worker newWorker = loginService.getUserInfo(worker);
		result.setData(newWorker);
		return result;
	}

	@ApiOperation(value = "用户退出登录header里面传token")
	@RequestMapping(path = "/logout", method = RequestMethod.GET)
	@ResponseBody
	public Result<String> logout(HttpServletRequest request) {
		Result<String> result = new Result<>();
		try {
			loginService.doLogout(request.getHeader("token"));
		} catch (Exception e) {
			log.warn("loginService.doLogout error!", e);
		}
		return result;
	}

	@ApiOperation(value = "获取验证码图片")
	@RequestMapping(path = "/getCaptchaImg", method = RequestMethod.GET)
	@ResponseBody
	public Result<CaptchaInfo> getCaptchaImg() {
		byte[] bs;
		String captcha;
		try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024)) {
			captcha = EncoderHelper.getChallangeAndWriteImage(microCaptcha, "png", outputStream);
			bs = outputStream.toByteArray();
		} catch (IOException e) {
			log.error("验证码生成失败", e);
			throw new RuntimeException("验证码生成失败", e);
		}

		String storeCaptchaKey = NanoIdUtil.randomLowerNanoId();
		loginService.storeCaptchaKeyId(storeCaptchaKey, captcha);
		log.info("captchaKey:" + storeCaptchaKey + ",captcha:" + captcha);

		CaptchaInfo captchaInfo = new CaptchaInfo();
		captchaInfo.setCaptchaKey(storeCaptchaKey);
		captchaInfo.setCaptchaBase64(DataUriScheme.PNG_BASE64_PREFIX + Base64Utils.encodeToString(bs));

		Result<CaptchaInfo> result = new Result<>();
		result.setData(captchaInfo);

		return result;
	}

	@ApiOperation(value = "获取手机验证码")
	@PostMapping(path = "/getPhoneCode")
	@ResponseBody
	public Result<String> getPhoneCode(@Validated @RequestBody SmsCodeSend smsCodeSend) {
		return Result.ofSuccess(loginService.getPhoneCode(smsCodeSend));
	}

	@ApiOperation(value = "获取手机验证码-不需要图文验证")
	@PostMapping(path = "/getPhoneCodeNoText")
	@ResponseBody
	public Result<String> getPhoneCodeNoText(@Validated @RequestBody SmsCodeNoTextDTO smsCodeNoTextDTO) {
		return Result.ofSuccess(loginService.getPhoneCodeNoText(smsCodeNoTextDTO));
	}

	@ApiOperation(value = "找回密码")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "phoneNum", value = "手机号", required = true),
			@ApiImplicitParam(name = "shortMsgCode", value = "短信验证码", required = true),
	})
	@RequestMapping(path = "/retrievePwd", method = RequestMethod.GET)
	@ResponseBody
	public Result<String> retrievePwd(String phoneNum,String shortMsgCode) {
		return Result.ofSuccess(loginService.retrievePwd(phoneNum,shortMsgCode));
	}


	@ApiOperation(value = "修改密码")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "secretKey", value = "验证key", required = true),
			@ApiImplicitParam(name = "newPwd", value = "新密码", required = true)
	})
	@RequestMapping(path = "/modifyPwd", method = RequestMethod.GET)
	@ResponseBody
	public Result<String> modifyPwd(String secretKey,String newPwd) {
		return Result.ofSuccess(loginService.updatePwd(secretKey,newPwd));
	}

	@ApiOperation(value = "手机号码登录")
	@RequestMapping(path = "/loginMobile", method = RequestMethod.POST)
	@ResponseBody
	public Result<Worker> loginMobile(@RequestBody LoginPhoneDto loginPhoneDto,HttpServletRequest request) {
		// 当前调用的url
		String callUrl = "/" + appName + request.getRequestURI();
		return Result.ofSuccess(loginService.loginMobile(request,loginPhoneDto,callUrl,false));
	}

	@ApiOperation(value = "app面容登录")
	@RequestMapping(path = "/loginCheckoutFace", method = RequestMethod.POST)
	@ResponseBody
	public Result<Worker> loginCheckoutFace(@RequestBody LoginCheckoutFaceDTO loginCheckoutFaceDTO, HttpServletRequest request) {
		return Result.ofSuccess(loginService.loginFace(request,loginCheckoutFaceDTO));
	}

	@ApiOperation("验证更换手机操作")
	@PostMapping("/verificationMobile")
	@ResponseBody
	public Result<String> verificationMobile(@RequestBody @Validated SetUserPhoneDTO dto){
		return loginService.verificationMobile(dto);
	}

	@ApiOperation("更换手机号")
	@PostMapping("/setUserPhone")
	@ResponseBody
	public Result<String> setUserPhone(@RequestBody @Validated SetUserPhoneDTO dto){
		return loginService.setUserPhone(dto);
	}

	@ApiOperation("用户注销")
	@GetMapping("/setUserLogout")
	@ResponseBody
	public Result<String> setUserLogout(@CurrWorker @ApiIgnore Worker worker){
		return loginService.deleteUserLogout(worker);
	}

	@ApiOperation(value = "注册")
	@RequestMapping(path = "/createWorkerAndLogin", method = RequestMethod.POST)
	@ResponseBody
	public Result<Worker> createWorkerAndLogin(@RequestBody LoginWorkerC loginWorkerC, HttpServletRequest request) {
		// 当前调用的url
		String callUrl = "/" + appName + request.getRequestURI();
		return Result.ofSuccess(loginService.createWorkerAndLogin(request,loginWorkerC,callUrl));
	}

	@ApiOperation(value = "上传头像")
	@RequestMapping(path = "/uploadHeadPic", method = RequestMethod.POST)
	@ResponseBody
	public Result<FileVo> uploadHeadPic(@RequestBody MultipartFile file,HttpServletRequest request) {
		return Result.ofSuccess(loginService.uploadHeadPic(file,request));
	}

	@ApiOperation(value = "IRS电子签章获取用户信息")
	@RequestMapping(path = "/getUserInfoIRS", method = RequestMethod.GET)
	@ResponseBody
	public IRSVo getUserInfoIRS(String token) {
		IRSVo irsVo = new IRSVo();
		IRSWorkerVo worker = loginService.getUserInfoIRS(token);
		irsVo.setData(worker);
		return irsVo;
	}

	@ApiOperation(value = "外部系统手机号码登录{渝快办，渝快政}")
	@RequestMapping(path = "/loginExternalMobile", method = RequestMethod.POST)
	@ResponseBody
	public Result<Worker> loginExternalMobile(@RequestBody LoginInfoDto loginInfoDto, HttpServletRequest request) throws IOException {
		// 当前调用的url
		String callUrl = "/" + appName + request.getRequestURI();
		return Result.ofSuccess(loginService.loginExternalMobile(request,loginInfoDto,callUrl,false));
	}

	@ApiOperation(value = "渝快政单点刷新accountId")
	@RequestMapping(path = "/refreshAccountId", method = RequestMethod.POST)
	@ResponseBody
	public Result refreshAccountId(@RequestBody LoginPhoneDto loginPhoneDto) {
		Result result = loginService.doRefreshAccountId(loginPhoneDto);
		return result;
	}

}
