package com.liquidnet.service.adam.controller.web.user;

import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.common.swagger.config.SwaggerApiVersion;
import com.liquidnet.service.ResponseDto;
import com.liquidnet.service.adam.common.AdamErrorCode;
import com.liquidnet.service.adam.config.swagger.AdamSwaggerApiVersionConstant;
import com.liquidnet.service.adam.dto.AdamUserSignInCheckRespDto;
import com.liquidnet.service.adam.dto.AdamUserSignInRespDto;
import com.liquidnet.service.adam.dto.AdamUserSignUpParam;
import com.liquidnet.service.adam.dto.base.AdamResultDto;
import com.liquidnet.service.adam.entity.AdamUser;
import com.liquidnet.service.adam.interceptor.annotation.NoAuth;
import com.liquidnet.service.adam.service.IAdamUserService;
import com.liquidnet.service.adam.util.CurrentUserUtil;
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.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

@Slf4j
@Api(tags = "web user sign")
@RestController
@RequestMapping("/adam-user-sign-in")
public class AdamUserSignInController {

    @Autowired
    private IAdamUserService adamUserService;

    @NoAuth
    @ApiOperation(value = "user sign up")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_0)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "firstName", value = "名"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "lastName", value = "姓"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "jobTitle", value = "职业"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "companyName", value = "公司名"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "email", value = "邮箱"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "password", value = "密码"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "comType", value = "公司描述"),
            @ApiImplicitParam(paramType = "form", dataType = "String", name = "comTypeOther", value = "补充信息")
    })
    @PostMapping("/sign-up")
    public ResponseDto signUp(String firstName,
                              String lastName,
                              String jobTitle,
                              String companyName,
                              String email,
                              String password,
                              String comType,
                              String comTypeOther) {

        log.info("[USER SIGN UP]; user email : {} Company : {} type : {} and complementary info : {}", email, companyName, comType, comTypeOther);
        AdamUserSignUpParam param = new AdamUserSignUpParam(firstName, lastName, jobTitle, companyName, email, password, comType, comTypeOther);

        AdamResultDto dto = null;
        try {
            dto = adamUserService.userSignUp(param);
        } catch (Exception e) {
            log.error("[USER SIGN UP]; catch an exception=[{}]", e.getMessage(), e);
            return ResponseDto.failure(ErrorCode.HTTP_SYSTEM_ERROR);
        }
        return AdamResultDto.getResponseDto(dto);
    }

    /**
     * 用户登录,第一步,校验邮箱和密码,给邮箱绑定的手机号发送验证码
     */
    @NoAuth
    @ApiOperation(value = "user sign in check")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_0)
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", dataType = "String", name = "email", value = "邮箱"),
            @ApiImplicitParam(type = "form", dataType = "String", name = "password", value = "密码")
    })
    @PostMapping("/sign-in-check")
    public ResponseDto userSignInCheck(String email, String password) {
        log.info("[USER SIGN IN CHECK] User: {} do sign in check at {}", email, LocalDateTime.now());

        if (Strings.isEmpty(email) || Strings.isEmpty(password)) {
            return ResponseDto.failure(AdamErrorCode.ILLEGAL_PARAM.getCode(), AdamErrorCode.ILLEGAL_PARAM.getVal());
        }
        AdamResultDto<AdamUserSignInCheckRespDto> respDto = adamUserService.signInCheck(email, password);
        return AdamResultDto.getResponseDto(respDto);
    }

    /**
     * 用户登录,第二步,用邮箱和手机验证码登录
     */
    @NoAuth
    @ApiOperation(value = "user sign in")
    @SwaggerApiVersion(group = AdamSwaggerApiVersionConstant.WEB_1_0)
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", dataType = "String", name = "email", value = "邮箱"),
            @ApiImplicitParam(type = "form", dataType = "String", name = "smsCode", value = "验证码")
    })
    @PostMapping("/sign-in")
    public ResponseDto signIn(String email, String smsCode, HttpServletRequest request) {
        log.info("[USER SIGN IN] User: {} sign in at {}", email, LocalDateTime.now());
        AdamResultDto<AdamUserSignInRespDto> respDto = adamUserService.confirmSMSCode(email, smsCode, getRealIP(request));
        if (respDto.isSuccess()) {
            AdamUserSignInRespDto data = respDto.getData();
            AdamUser adamUser = adamUserService.selectById(data.getUserId());
            CurrentUserUtil.setCurrentUser(request, adamUser);
        }
        return AdamResultDto.getResponseDto(respDto);
    }

    private String getRealIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}
