package com.diaoyun.zion.chinafrica.service.impl;

import com.diaoyun.zion.chinafrica.constant.EmailTemplateConstant;
import com.diaoyun.zion.chinafrica.constant.KeyConstant;
import com.diaoyun.zion.chinafrica.dao.TbCfCouponDao;
import com.diaoyun.zion.chinafrica.dao.TbCfUserInfoDao;
import com.diaoyun.zion.chinafrica.entity.TbCfCouponEntity;
import com.diaoyun.zion.chinafrica.entity.TbCfIssueCouponEntity;
import com.diaoyun.zion.chinafrica.entity.TbCfUserInfoEntity;
import com.diaoyun.zion.chinafrica.service.TbCfCouponService;
import com.diaoyun.zion.chinafrica.service.TbCfIssueCouponService;
import com.diaoyun.zion.chinafrica.service.TbCfUserInfoService;
import com.diaoyun.zion.chinafrica.vo.TbCfUserInfoVo;
import com.diaoyun.zion.master.base.Result;
import com.diaoyun.zion.master.base.StateConstant;
import com.diaoyun.zion.master.bo.EmailTemplateBo;
import com.diaoyun.zion.master.common.RedisCache;
import com.diaoyun.zion.master.common.TokenManager;
import com.diaoyun.zion.master.config.DomainProperties;
import com.diaoyun.zion.master.enums.ResultCodeEnum;
import com.diaoyun.zion.master.enums.SexEnum;
import com.diaoyun.zion.master.enums.UserTypeEnum;
import com.diaoyun.zion.master.exception.ApplicationException;
import com.diaoyun.zion.master.security.JwtTokenProvider;
import com.diaoyun.zion.master.util.*;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.EmailException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 用户表Service实现类
 *
 * @author G
 * @date 2019-08-14 09:11:47
 */
@Service("tbCfUserInfoService")
public class TbCfUserInfoServiceImpl implements TbCfUserInfoService {
    @Autowired
    private TbCfUserInfoDao tbCfUserInfoDao;
    @Autowired
    private TbCfCouponDao tbCfCouponDao;
    @Autowired
    private TbCfCouponService tbCfCouponService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @Autowired
    private TbCfIssueCouponService tbCfIssueCouponService;


    @Autowired
    private AuthenticationManager authenticationManager;

    @Resource(name = "redisTokenManager")
    private TokenManager tokenManager;

    @Autowired
    private EmailHelper emailHelper;

    @Autowired
    private DomainProperties domainProperties;

    @Autowired
    private HttpServletRequest request; //自动注入request

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private RedisCache<Object> captchaRedisCache;



    @Override
    public TbCfUserInfoEntity queryObject(String userId) {
        return tbCfUserInfoDao.queryObject(userId);
    }

    @Override
    public List<TbCfUserInfoEntity> queryList(Map<String, Object> map) {
        return tbCfUserInfoDao.queryList(map);
    }

    @Override
    public int queryTotal(Map<String, Object> map) {
        return tbCfUserInfoDao.queryTotal(map);
    }

    @Override
    public int save(TbCfUserInfoEntity tbCfUserInfo) {
        tbCfUserInfo.setUserId(IdUtil.createIdbyUUID());
        return tbCfUserInfoDao.save(tbCfUserInfo);
    }

    @Override
    public int update(TbCfUserInfoEntity tbCfUserInfo) {
        return tbCfUserInfoDao.update(tbCfUserInfo);
    }

    @Override
    public int delete(String userId) {
        return tbCfUserInfoDao.delete(userId);
    }

    @Override
    public int deleteBatch(String[] userIds) {
        return tbCfUserInfoDao.deleteBatch(userIds);
    }

    @Override
    public Integer sendRegisterIdentifyCode(String email, String nick) throws EmailException, TemplateException, IOException {
        EmailTemplateBo emailTemplateBo = new EmailTemplateBo();
        Integer randomCode = RandomCodeHelper.producedRandomCode(6);
        emailTemplateBo.setNick(nick);
        emailTemplateBo.setIdentifyCode(randomCode);
        Integer identifyCode = emailHelper.sendIdentifyEmail(email, EmailTemplateConstant.REGISTER, emailTemplateBo);
        captchaRedisCache.set(KeyConstant.CAPTCHA + email, identifyCode, 1800);
        return identifyCode;
    }

    @Override
    public Result registerAndLogin(TbCfUserInfoVo tbCfUserInfoVo) {
        Result result = new Result();
        Integer identifyCode = (Integer) captchaRedisCache.get(KeyConstant.CAPTCHA + tbCfUserInfoVo.getAccount());
        if (identifyCode == null || identifyCode.intValue() != tbCfUserInfoVo.getCaptcha().intValue()) {
            result.setCode(ResultCodeEnum.VALIDATE_ERROR.getCode());
            result.setMessage("Verification code error");
        } else {
            //验证邮箱有没有被注册
            TbCfUserInfoEntity existUser = findByAccount(tbCfUserInfoVo.getAccount());
            if (existUser == null) {

                TbCfUserInfoEntity tbCfUserInfoEntity = new TbCfUserInfoEntity();
                /**
                 * 填充必要信息
                 */
                //目前有验证码的都是邮箱类型
                tbCfUserInfoVo.setUserType(UserTypeEnum.EMAIL.getCode());
                tbCfUserInfoVo.setEmailFlag(StateConstant.VALID);
                //生成UUID用一个string 类型来保存着，后面会用到
                String userid = IdUtil.createIdbyUUID();
                tbCfUserInfoVo.setUserId(userid);
                //用户姓名
                String nick = domainProperties.getProperty("user.nick");
                tbCfUserInfoVo.setNick(nick);
                fillUserNecessayInfo(tbCfUserInfoVo);
                //加密密码
                String password = passwordEncoder.encode(tbCfUserInfoVo.getPassword());
                tbCfUserInfoVo.setPassword(password);
                BeanUtils.copyProperties(tbCfUserInfoVo, tbCfUserInfoEntity);
                tbCfUserInfoDao.save(tbCfUserInfoEntity);
                //赠送用户优惠券 tbCfIssueCouponService
                List<TbCfCouponEntity> couponVailList = tbCfCouponService.getCouponAndVaildAll();
                //获取当前时间的时分秒
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                String date = df.format(new Date());
                for (int i = 0; i < couponVailList.size(); i++) {
                    TbCfIssueCouponEntity issue = new TbCfIssueCouponEntity();
                    String coupon_id = couponVailList.get(i).getCouponId();
                    String issuseCoupon_id = IdUtil.createIdbyUUID();
                    //把上面获取到的值，赋值到实体类中
                    issue.setCouponId(coupon_id);
                    issue.setIssueId(issuseCoupon_id);
                    issue.setCreateTime(date);
                    issue.setUserId(userid);
                    issue.setNick(nick);
                    issue.setEnableFlag(0);
                    tbCfIssueCouponService.save(issue);
                }
                //注册成功 创建token
                String token = jwtTokenProvider.createToken(tbCfUserInfoVo.getAccount());
                tbCfUserInfoVo.setToken(token);
                //保存在redis
                tokenManager.addToken(token, tbCfUserInfoVo);
                result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
                result.setData(tbCfUserInfoVo);
/*
                //获取购物返券
                List<TbCfCouponEntity> couponList = tbCfCouponDao.getCouponByCategory(CouponCategoryEnum.REGISTER.getValue(),new Date());
                if(!couponList.isEmpty()) {
                    //领取优惠券
                    tbCfCouponService.takeCoupon(couponList.get(0).getCouponId(),tbCfUserInfoVo.getUserId());
                }*/
            } else {
                result.setCode(ResultCodeEnum.VALIDATE_ERROR.getCode());
                result.setMessage("The mailbox or nick has been registered");
            }
            tbCfUserInfoVo.setEnableFlag(StateConstant.VALID);

        }
        return result;
    }

    @Override
    public Result login(String ip, String account, String password) {
        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(account, password));
            String token = jwtTokenProvider.createToken(account);
            //password = passwordEncoder.encode(password);
            return loginOfficial(ip, account, token);
        } catch (AuthenticationException e) {
            throw new ApplicationException(ResultCodeEnum.NEED_LOGIN.getCode(), "Invalid username/password supplied or account is disable");
        }
    }

    /**
     * 登录
     *
     * @param ip
     * @param account
     * @param token
     * @return
     */
    private Result loginOfficial(String ip, String account, String token) {
        Result<TbCfUserInfoVo> result = new Result<>();
        TbCfUserInfoEntity user = findByAccount(account);
        user.setLastLoginIp(ip);
        user.setLoginCount(user.getLoginCount() + 1);
        user.setLastLoginTime(new Date());
        tbCfUserInfoDao.update(user);
        TbCfUserInfoVo loginUser = new TbCfUserInfoVo();
        BeanUtils.copyProperties(user, loginUser);
        loginUser.setToken(token);
        //更新用户
        tokenManager.addToken(token, loginUser);
        result.setData(loginUser).setMessage(ResultCodeEnum.SUCCESS.getDesc());
        return result;
    }

    @Override
    public TbCfUserInfoEntity findByAccount(String account) {
        TbCfUserInfoEntity tbCfUserInfoEntity = tbCfUserInfoDao.findByAccount(account);
        return tbCfUserInfoEntity;
    }

    @Override
    public Result updatePassWord(String newPassword, String oldPassword) {
        Result result = new Result();
        //获取用户
        String token = jwtTokenProvider.resolveToken(request);
        TbCfUserInfoVo loginUser = tokenManager.validate(token);
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginUser.getAccount(), oldPassword));
        newPassword = passwordEncoder.encode(newPassword);
        int res = tbCfUserInfoDao.updatePassWord(loginUser.getUserId(), newPassword);
        if (res > 0) {
            logout();
            result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
        } else {
            result.setCode(ResultCodeEnum.ERROR.getCode()).setMessage("update wrong");
        }
        return result;
    }

    @Override
    public Result logout() {
        String token = jwtTokenProvider.resolveToken(request);
        if (StringUtils.isNotBlank(token)) {
            tokenManager.remove(token);
        }
        return new Result("login out");
    }

    @Override
    public int updateUserInfo(TbCfUserInfoVo tbCfUserInfoVo) {
        //获取用户
        String token = jwtTokenProvider.resolveToken(request);
        TbCfUserInfoVo loginUser = tokenManager.validate(token);
        String userId = loginUser.getUserId();
        tbCfUserInfoVo.setUserId(userId);
        TbCfUserInfoEntity tbCfUserInfoEntity = new TbCfUserInfoEntity();
        BeanUtils.copyProperties(tbCfUserInfoVo, tbCfUserInfoEntity);
        int res = this.update(tbCfUserInfoEntity);
        //更新缓存
        TbCfUserInfoEntity newUser = tbCfUserInfoDao.queryObject(userId);
        BeanUtils.copyProperties(newUser, loginUser);
        loginUser.setToken(token);
        tokenManager.addToken(token, loginUser);
        return res;
    }

    @Override
    // TODO
    public Result loginByThirdParty(String ip, String account, String nick, String userType) throws UnsupportedEncodingException {
        /*Result result = new Result();
        String token = CookieUtils.getCookie(request, TokenManager.TOKEN);
        if (StringUtils.isNotBlank(token) && tokenManager.validate(token) != null) {

            TbCfUserInfoVo tbCfUserInfoVo = tokenManager.validate(token);
            if (tbCfUserInfoVo == null) {
                CookieUtils.removeCookie(response, TokenManager.TOKEN, "/", null);
                result.setCode(ResultCodeEnum.ERROR.getCode()).setMessage("please login again");
            } else {
                if (StringUtils.isBlank(account)) {
                    account = tbCfUserInfoVo.getAccount();
                }
                if (StringUtils.isBlank(nick)) {
                    nick = tbCfUserInfoVo.getNick();
                }
                loginByThirdPartyOfficial(token, ip, account, nick, result);
            }
        } else {
            Validator.NOT_BLANK.validate("account", account);
            Validator.NOT_BLANK.validate("nick", nick);
            Validator.NOT_BLANK.validate("userType", userType);
            nick = URLDecoder.decode(nick, Consts.UTF_8.name());
            //根据账号找用户
            TbCfUserInfoEntity oldUser = findByAccount(account);
            //新用户则注册
            if (oldUser == null) {
                UserTypeEnum userTypeEnum = matchUserType(userType);
                TbCfUserInfoVo tbCfUserInfoVo = new TbCfUserInfoVo();
                tbCfUserInfoVo.setAccount(account);
                tbCfUserInfoVo.setUserType(userTypeEnum.getCode());
                tbCfUserInfoVo.setNick(nick);
                tbCfUserInfoVo.setLastLoginIp(ip);
                TbCfUserInfoEntity tbCfUserInfoEntity = new TbCfUserInfoEntity();
                *//**
         * 填充必要信息
         *//*
                fillUserNecessayInfo(tbCfUserInfoVo);

                BeanUtils.copyProperties(tbCfUserInfoVo, tbCfUserInfoEntity);
                tbCfUserInfoDao.save(tbCfUserInfoEntity);

                //注册成功 创建token
                buildUserToken(tbCfUserInfoEntity);
                result.setMessage("登录成功").setData(tbCfUserInfoVo);
            } else {
                if (nick.equals(oldUser.getNick())) {
                    oldUser.setLastLoginIp(ip);
                    oldUser.setLoginCount(oldUser.getLoginCount() + 1);
                    oldUser.setLastLoginTime(new Date());
                    tbCfUserInfoDao.update(oldUser);
                    //为用户添加token
                    buildUserToken(oldUser);
                    result.setData(oldUser).setMessage(ResultCodeEnum.SUCCESS.getDesc());
                } else {
                    result.setCode(ResultCodeEnum.NEED_LOGIN.getCode()).setMessage("please login again");
                }

            }
        }*/
        return null;
    }

    @Override
    public Result loginByToken(String ip) {
        String token = jwtTokenProvider.resolveToken(request);
        String account = jwtTokenProvider.getUsername(token);
        return loginOfficial(ip, account, token);
    }

    @Override
    public Result resetPassWord(String account,String newPassword, Integer captcha) {
        Result result = new Result();
        Integer identifyCode = (Integer) captchaRedisCache.get(KeyConstant.CAPTCHA + account);
        if (identifyCode == null || identifyCode.intValue() != captcha) {
            result.setCode(ResultCodeEnum.VALIDATE_ERROR.getCode());
            result.setMessage("Verification code error");
        } else {
            Integer randomCode = RandomCodeHelper.producedRandomCode(6);
            captchaRedisCache.set(KeyConstant.CAPTCHA + account, randomCode, 1800);
            //authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginUser.getAccount(), oldPassword));
            TbCfUserInfoEntity existUser = findByAccount(account);
            String userId = existUser.getUserId();
            newPassword = passwordEncoder.encode(newPassword);
            int res = tbCfUserInfoDao.updatePassWord(userId, newPassword);
            if (res > 0) {
                logout();
                result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
            } else {
                result.setCode(ResultCodeEnum.ERROR.getCode()).setMessage("update wrong");
            }
        }

        return result;
    }

    @Override
    public Result<TbCfUserInfoVo> getUserInfo() {
        String token = jwtTokenProvider.resolveToken(request);
        TbCfUserInfoVo loginUser = tokenManager.validate(token);
        return new Result<>(loginUser);
    }


    /**
     * 获取用户类型
     *
     * @param userType
     * @return
     */
    private UserTypeEnum matchUserType(String userType) {
        UserTypeEnum userTypeEnum;
        switch (userType) {
            case "1": {
                userTypeEnum = UserTypeEnum.EMAIL;
                break;
            }
            case "2": {
                userTypeEnum = UserTypeEnum.FACEBOOK;
                break;
            }
            case "3": {
                userTypeEnum = UserTypeEnum.PHONE;
                break;
            }
            case "4": {
                userTypeEnum = UserTypeEnum.TWITTER;
                break;
            }
            default: {
                userTypeEnum = UserTypeEnum.UN_KNOW;
                break;
            }
        }
        return userTypeEnum;
    }

    /**
     * 为用户添加token
     *
     * @param oldUser
     */
  /*  private void buildUserToken(TbCfUserInfoEntity oldUser) {
        TbCfUserInfoVo loginUser = new TbCfUserInfoVo();
        BeanUtils.copyProperties(oldUser, loginUser);
        String newToken = createToken(loginUser);
        addTokenInCookie(newToken, request, response);
        SessionUtils.setSessionUser(request, new SessionUser(newToken, loginUser.getAccount()));
    }*/

    /**
     * 第三方登录
     *
     * @return
     */
   /* private void loginByThirdPartyOfficial(String token, String ip, String account, String nick, Result result) {
        TbCfUserInfoEntity user = findByAccount(account);
        if (user != null && nick.equals(user.getNick())) {
            user.setLastLoginIp(ip);
            user.setLoginCount(user.getLoginCount() + 1);
            user.setLastLoginTime(new Date());
            tbCfUserInfoDao.update(user);
            //更新token用户
            TbCfUserInfoVo loginUser = new TbCfUserInfoVo();
            BeanUtils.copyProperties(user, loginUser);
            tokenManager.addToken(token, loginUser);
            result.setData(user).setMessage(ResultCodeEnum.SUCCESS.getDesc());
        } else {
            tokenManager.remove(token);
            CookieUtils.removeCookie(response, TokenManager.TOKEN, "/", null);
            result.setCode(ResultCodeEnum.NEED_LOGIN.getCode()).setMessage("please login again");
        }
    }*/
    private void fillUserNecessayInfo(TbCfUserInfoVo tbCfUserInfoVo) {
        tbCfUserInfoVo.setAvatar(domainProperties.getProperty("user.avatar"));
        tbCfUserInfoVo.setUserNo(IdUtil.createIdByDate());
        tbCfUserInfoVo.setPhoneFlag(StateConstant.INVALID);
        tbCfUserInfoVo.setLoginCount(0);
        tbCfUserInfoVo.setCreateTime(new Date());
        tbCfUserInfoVo.setSex(SexEnum.UNKNOW.getCode());
        tbCfUserInfoVo.setInvitedCount(0);
        tbCfUserInfoVo.setEnableFlag(StateConstant.VALID);
    }

    //创建token
  /*  private String createToken(TbCfUserInfoVo loginUser) {
        // 生成token
        String token = IdUtil.createIdbyUUID();
        // 缓存中添加token对应User
        tokenManager.addToken(token, loginUser);
        return token;
    }*/

    //添加cookie
    /*private void addTokenInCookie(String token, HttpServletRequest request, HttpServletResponse response) {
        // Cookie添加token
        Cookie cookie = new Cookie(TokenManager.TOKEN, token);
        cookie.setPath("/");
        if ("https".equals(request.getScheme())) {
            cookie.setSecure(true);
        }
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
    }*/

}
