package com.bizzan.bitrade.controller;

import com.bizzan.bitrade.entity.LoginInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import com.bizzan.bitrade.constant.SysConstant;
import com.bizzan.bitrade.entity.Member;
import com.bizzan.bitrade.entity.MemberWeightUpper;
import com.bizzan.bitrade.entity.Sign;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.bizzan.bitrade.event.MemberEvent;
import com.bizzan.bitrade.exception.AuthenticationException;
import com.bizzan.bitrade.service.LocaleMessageSourceService;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.service.MemberWeightUpperService;
import com.bizzan.bitrade.service.SignService;
import com.bizzan.bitrade.service.SysConfigService;
import com.bizzan.bitrade.system.GeetestLib;
import com.bizzan.bitrade.util.GoogleAuthenticatorUtil;
import com.bizzan.bitrade.util.InnerInvokeUtil;
import com.bizzan.bitrade.util.MessageResult;

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

import javax.servlet.http.HttpServletRequest;

import static com.bizzan.bitrade.constant.SysConstant.SESSION_MEMBER;
import static org.springframework.util.Assert.hasText;
import static org.springframework.util.Assert.isTrue;
import static org.springframework.util.Assert.notNull;

import java.util.Calendar;
import java.util.HashMap;

/**
 * @author 
 * @date 2020年01月10日
 */
@Api(value = "LoginController" , tags = "登录接口")
@RestController
@Slf4j
public class LoginController extends BaseController {

    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberEvent memberEvent;
    @Autowired
    private LocaleMessageSourceService messageSourceService;
    @Autowired
    private LocaleMessageSourceService msService;
    @Autowired
    private GeetestLib gtSdk;
    @Autowired
    private SignService signService;
    @Autowired
    private MemberWeightUpperService memberWeightUpperService;
    @Autowired
    private InnerInvokeUtil invokeUtil;
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private SysConfigService sysConfigService;

    @Value("${dev.mode.vcode:}")
    private String devModeVcode;

    @PostMapping(value = "/login")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "username",value = "用户名",required = true,dataType = "string"),
    		@ApiImplicitParam(name = "password",value = "密码",required = true,dataType = "string"),
    		@ApiImplicitParam(name = "vtype",value = "验证类型 1短信 2邮箱 3谷歌",required = true,dataType = "int"),
    		@ApiImplicitParam(name = "vcode",value = "验证码",required = true,dataType = "int")
    })
    @Transactional(rollbackFor = Exception.class)
    public MessageResult login(HttpServletRequest request, String username, String password, Integer vtype, String vcode) {

        Assert.hasText(username, messageSourceService.getMessage("MISSING_USERNAME"));
        Assert.hasText(password, messageSourceService.getMessage("MISSING_PASSWORD"));
        String ip = getRemoteIp(request);
        try {
        	Member member = memberService.login(username, password);
        	if(!member.getSuperPartner().equals("1")) {
        		return MessageResult.error(msService.getMessage("USER_NOT_AGENT"));
        	}
        	
        	boolean isDevBypass = !devModeVcode.isEmpty() && devModeVcode.equals(vcode);
        	if(vtype == 1) {
            	if (!isDevBypass) {
	            	ValueOperations valueOperations = redisTemplate.opsForValue();
	                Object cache = valueOperations.get(SysConstant.PHONE_LOGIN_CODE_PREFIX + member.getMobilePhone());
	                notNull(cache, msService.getMessage("NO_GET_VERIFICATION_CODE"));
	                hasText(vcode, msService.getMessage("MISSING_VERIFICATION_CODE"));
	                if (!vcode.equals(cache.toString())) {
	                	return MessageResult.error(messageSourceService.getMessage("VERIFICATION_CODE_INCORRECT"));
	                } else {
	                    valueOperations.getOperations().delete(SysConstant.PHONE_LOGIN_CODE_PREFIX + member.getMobilePhone());
	                }
            	}
            } else if (vtype == 2) {
            	if (!isDevBypass) {
	            	ValueOperations valueOperations = redisTemplate.opsForValue();
	                Object cache = valueOperations.get(SysConstant.EMAIL_LOGIN_CODE_PREFIX + member.getEmail());
	                notNull(cache, msService.getMessage("NO_GET_VERIFICATION_CODE"));
	                isTrue(vcode.equals(cache.toString()), msService.getMessage("VERIFICATION_CODE_INCORRECT"));
            	}
            } else {
            	return MessageResult.error(messageSourceService.getMessage("VERIFICATION_CODE_INCORRECT"));
            }
        	
            LoginInfo loginInfo = getLoginInfo(username, password, ip, request);
            return success(loginInfo);
        } catch (Exception e) {
            return error(e.getMessage());
        }
    }

    private LoginInfo getLoginInfo(String username, String password, String ip, HttpServletRequest request) throws Exception {
        //Member member = memberService.login(username, password);
    	//if(!invokeUtil.login(username, password))
    	//	throw new AuthenticationException(messageSourceService.getMessage("USER_PASSWORD_ERROR"));
    	//Member member = memberService.findByUsername(username);
        //if(!member.getSuperPartner().equals("1"))
        //	throw new Exception("只有代理商才能登录");
    	Member member = memberService.findByUsername(username);
        memberEvent.onLoginSuccess(member, ip);
        request.getSession().setAttribute(SysConstant.SESSION_MEMBER, AuthMember.toAuthMember(member));
        //String token = request.getHeader("access-auth-token");
        //if (!StringUtils.isBlank(token)) {
        //    member.setToken(token);
        //}
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR_OF_DAY, 24 * 7);
        member.setTokenExpireTime(calendar.getTime());
        // 获取登录次数
        int loginCount = member.getLoginCount();
        member.setLoginCount(loginCount+1);
        // 签到活动是否进行
        Sign sign = signService.fetchUnderway();
        LoginInfo loginInfo;
        if (sign == null) {
            loginInfo = LoginInfo.getLoginInfo(member, request.getSession().getId(), false, sysConfigService.get().getPromotionPrefix());
        } else {
            loginInfo = LoginInfo.getLoginInfo(member, request.getSession().getId(), true, sysConfigService.get().getPromotionPrefix());
        }
        MemberWeightUpper memberWeightUpper = memberWeightUpperService.findMemberWeightUpperByMemberId(member.getId());
        if(memberWeightUpper.getRate()!=null)
        	loginInfo.setMemberRate(memberWeightUpper.getRate().toString());
        return loginInfo;
    }

    /**
     * 登出
     *
     * @return
     */
    @ApiOperation(value="登出", notes="登出")
    @PostMapping(value = "/loginout")
    @Transactional(rollbackFor = Exception.class)
    public MessageResult loginOut(HttpServletRequest request, @SessionAttribute(SESSION_MEMBER) AuthMember user) {
        MessageResult messageResult = new MessageResult();
        log.info(">>>>>退出登陆接口开始>>>>>");
        try {
            request.getSession().removeAttribute(SysConstant.SESSION_MEMBER);
            Member member = memberService.findOne(user.getId());
            member.setToken(null);
            messageResult= request.getSession().getAttribute(SysConstant.SESSION_MEMBER) != null ? error(messageSourceService.getMessage("LOGOUT_FAILED")) : success(messageSourceService.getMessage("LOGOUT_SUCCESS"));
        } catch (Exception e) {
            e.printStackTrace();
            log.info(">>>>>登出失败>>>>>"+e);
        }
        log.info(">>>>>退出登陆接口结束>>>>>");
        return messageResult;
    }

    /**
     * 检查是否登录
     *
     * @param request
     * @return
     */
    @ApiOperation(value="检查是否登录", notes="检查是否登录")
    @GetMapping("/check/login")
    public MessageResult checkLogin(HttpServletRequest request) {
        AuthMember authMember = (AuthMember) request.getSession().getAttribute(SESSION_MEMBER);
        MessageResult result = MessageResult.success();
        if (authMember != null) {
            result.setData(true);
        } else {
            result.setData(false);
        }
        return result;
    }
}
