package com.sv.api.service.impl;

import com.enums.MemberAuthTypeEnum;
import com.enums.MemberStatusEnum;
import com.sv.api.context.PlatformContext;
import com.sv.dto.api.BindMobileDTO;
import com.sv.dto.api.MemberInformationDTO;
import com.sv.dto.api.MemberTokenDTO;
import com.sv.entity.Member;
import com.sv.entity.MemberAuth;
import com.sv.exception.api.ExceptionCodeTemplate;
import com.sv.api.util.OSSHelper;
import com.sv.service.api.MemberAuthService;
import com.sv.service.api.MemberService;
import com.sv.service.api.MemberTokenService;
import com.sv.service.common.ApiConstants;
import com.sv.service.common.CaptchaCacheServiceImpl;
import com.sv.service.common.OSSClientUtil;
import com.ydd.framework.core.common.utils.ValidationUtils;
import com.ydd.framework.core.entity.enums.DeletedEnum;
import com.ydd.framework.core.exception.ServiceException;
import com.ydd.framework.core.service.impl.BaseServiceImpl;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * Service - 用户登录注册service
 *
 * @author zhaoziyu
 * @since 2018-08-01
 */
@Service
@Transactional
public class LoginRegisterServiceImpl extends BaseServiceImpl {

	private final Logger logger = LoggerFactory.getLogger(LoginRegisterServiceImpl.class);

	@Resource
	private CaptchaCacheServiceImpl captchaCacheService;
	@Resource
	private MemberService memberService;
	@Resource
    private MemberAuthService memberAuthService;
	@Resource
    private MemberTokenService memberTokenService;

    @Resource
    private OSSClientUtil ossClientUtil;

    /**
	 * 手机号注册
	 */
	@Transactional
	public MemberTokenDTO registerByMobile(String mobile,String captcha,String name,Integer sex,Integer age,String address){
		ValidationUtils.assertNotBlank(mobile, "请输入手机号码");
		ValidationUtils.assertMobile(mobile);
		ValidationUtils.assertNotNull(captcha);

        // 校验验证码是否正确
		captchaCacheService.assertCaptcha(mobile, ApiConstants.REGISTER_SMS_CAPTCHA_PREFIX, captcha);
        MemberTokenDTO memberTokenDTO = null;
        synchronized (mobile){
            // 根据手机号码创建新用户
            Member member = memberService.createByMobile(mobile,name,sex,age,address,PlatformContext.getValue());

            // 删除验证码
            captchaCacheService.remove(mobile, ApiConstants.REGISTER_SMS_CAPTCHA_PREFIX);

            // 查询认证
            MemberAuth memberAuth = memberAuthService.findByMobile(mobile);
            if (memberAuth == null){
                // 创建用户登录认证
                memberAuth = memberAuthService.createByMobile(member.getId(),member.getPlatformId(),mobile);
            }

            // 查询访问凭证，并强制更新
            memberTokenDTO = memberTokenService.findDTOByMemberId(memberAuth.getMemberId(), Boolean.TRUE);
        }


        return memberTokenDTO;
	}


    /**
     * 手机号和验证码登录
     */
    @Transactional
    public MemberTokenDTO loginByMobile(String mobile, String captcha){
        // 参数校验
        ValidationUtils.assertNotBlank(mobile, "请输入手机号码");
        ValidationUtils.assertMobile(mobile);
        ValidationUtils.assertNotBlank(captcha, "请输入验证码");
        // 校验验证码是否正确
        captchaCacheService.assertCaptcha(mobile, ApiConstants.LOGIN_SMS_CAPTCHA_PREFIX, captcha);

        // 判断是否有注册，根据手机号码查找用户
        Member member = memberService.findByMobile(mobile);
        if (member == null){
            throw new ServiceException(ExceptionCodeTemplate.LOGIN_ERROR);
        }

        // 查询认证
        MemberAuth memberAuth = memberAuthService.findByMobile(mobile);
        memberAuth.setModifiedTime(new Date());
        memberAuthService.update(memberAuth);

        // 查询访问凭证，并强制更新
        MemberTokenDTO memberTokenDTO = memberTokenService.findDTOByMemberId(memberAuth.getMemberId(), Boolean.TRUE);

        return memberTokenDTO;
    }

    /**
     * 微信快捷登录
     */
    public MemberTokenDTO loginWithXcx(String openId,String nickname, String avatar){

        MemberTokenDTO memberTokenDTO = null;
        synchronized (openId){
            // 判断用户是否注册过，用微信登录过
            MemberAuth memberAuth = memberAuthService.findByAuthId(openId);
            // 登录过，则直接登录成功
            if (memberAuth != null){
                // 查询访问凭证，并强制更新
                memberTokenDTO = memberTokenService.findDTOByMemberId(memberAuth.getMemberId(), Boolean.TRUE);
                // 修改用户图像
                updateInformation(memberAuth.getMemberId(),nickname,avatar);
            }
        }
        return memberTokenDTO;
    }

    /**
     * 已用手机号登录，支付，再跳转微信登录
     * @param openId
     * @param nickname
     * @param avatar
     * @param memberId
     * @return
     */
    public MemberTokenDTO loginCheckWx(String openId,String nickname, String avatar,Integer memberId,Integer platformId){
        // 参数校验
        if (memberId == null){
            throw new ServiceException("token过期");
        }

        MemberTokenDTO memberTokenDTO = null;
        synchronized (openId){
            // 1.根据openId,查找登录表，是否有记录，无，直接登录，插入信息到登录表
            Member member = memberService.findById(memberId);
//            memberService.verify(member);

            // 判断用户是否用微信登录过
            MemberAuth memberAuth = memberAuthService.findByAuthId(openId);
            if (memberAuth == null){
                // 创建用户登录认证
                memberAuth = memberAuthService.createByMobileByOpenId( memberId, platformId,  member.getMobile(),  openId);
            }else {
                // 2.登录表有信息，通过用户ID，查找用户的电话号码，和通过openid查找的电话号码，进行匹配，相同，登录成功
                Member memberInfo = memberService.findById(memberAuth.getMemberId());
                // 3.不相同，报异常
                if (!member.getMobile().equals(memberInfo.getMobile())){
                    throw new ServiceException("该微信已绑定其他手机号");
                }
            }
        }

        // 修改用户图像
        updateInformation(memberId,nickname,avatar);

        // 查询访问凭证，并强制更新
        memberTokenDTO = memberTokenService.findDTOByMemberId(memberId, Boolean.TRUE);
        return memberTokenDTO;
    }

    //将微信头像上传到OSS
    public String updateWxImgToOss(String avatar) throws IOException {
        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpGet httpget = new HttpGet(avatar);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1200).build();
        httpget.setConfig(requestConfig);
        HttpResponse response = null;
        response = client.execute(httpget);
        HttpEntity resEntity = response.getEntity();
        InputStream inputStream = resEntity.getContent();
        return ossClientUtil.upload(System.currentTimeMillis() + ".png", inputStream);
    }

    /**
     *
     * 返回openId
     */
    public MemberInformationDTO info(String avatar,String nickname,String openId){
        MemberInformationDTO informationDTO = new MemberInformationDTO();
        informationDTO.setAvatar(avatar);
        informationDTO.setNickname(nickname);
        informationDTO.setOpenId(openId);
        return informationDTO;
    }

    /**
     * 绑定手机号
     */
    public MemberTokenDTO bildMobile(BindMobileDTO bindMobileDTO){
        // 参数校验
        ValidationUtils.assertNotBlank(bindMobileDTO.getMobile(), "请输入手机号码");
        ValidationUtils.assertMobile(bindMobileDTO.getMobile());
        ValidationUtils.assertNotNull(bindMobileDTO.getNickname());
        ValidationUtils.assertNotNull(bindMobileDTO.getAvatar());
        ValidationUtils.assertNotNull(bindMobileDTO.getOpenId());
        ValidationUtils.assertNotBlank(bindMobileDTO.getCaptcha(), "请输入验证码");
        // 校验验证码是否正确
		captchaCacheService.assertCaptcha(bindMobileDTO.getMobile(), ApiConstants.PHONE_SMS_CAPTCHA_PREFIX, bindMobileDTO.getCaptcha());

        MemberTokenDTO memberTokenDTO = null;
        Member member = memberService.findByMobile(bindMobileDTO.getMobile());
        // 不存在直接注册
        if (member == null){
            // 根据手机号码创建新用户
             member = memberService.createByMobile(bindMobileDTO.getMobile(),bindMobileDTO.getName(),
                    bindMobileDTO.getSex(),bindMobileDTO.getAge(),bindMobileDTO.getAddress(),PlatformContext.getValue());
             // 修改用户图像
            updateInformation(member.getId(),bindMobileDTO.getNickname(),bindMobileDTO.getAvatar());
            // 删除验证码
            captchaCacheService.remove(bindMobileDTO.getMobile(), ApiConstants.REGISTER_SMS_CAPTCHA_PREFIX);

            // 查询认证
            MemberAuth memberAuth = memberAuthService.findByMobile(bindMobileDTO.getMobile());
            if (memberAuth == null){
                // 创建用户登录认证
                memberAuth = memberAuthService.createByMobileByOpenId(member.getId(),member.getPlatformId(),
                        bindMobileDTO.getMobile(),bindMobileDTO.getOpenId());
            }

            // 查询访问凭证，并强制更新
             memberTokenDTO = memberTokenService.findDTOByMemberId(memberAuth.getMemberId(), Boolean.TRUE);
        }else {
            if (DeletedEnum.YES.value.equals(member.getDeleted())) {
                throw new ServiceException(ExceptionCodeTemplate.NONE_MEMBER_INFORMATION);
            }
            if(member.getStatus().intValue() == MemberStatusEnum.DISABLE.value.intValue()){
                throw new ServiceException(ExceptionCodeTemplate.MEMBER_ERROR);
            }

            // 查询用户登录的方式（member_auth表中）
            memberTokenDTO = checkLogin(member.getId(),bindMobileDTO.getOpenId(),member,bindMobileDTO);
        }

        return memberTokenDTO;
    }

    /**
     * 具体查看用户的登录情况
     */
    @Transactional
    public MemberTokenDTO checkLogin(Integer memberId,String openId,Member member,BindMobileDTO bindMobileDTO){
        MemberTokenDTO memberTokenDTO = null;
        // 微信登录方式
        MemberAuth memberAuth = memberAuthService.checkLoginWay(memberId,MemberAuthTypeEnum.WEIXIN.value);
        // 如果用户有用微信登录过，并且openId,与登录中的一致，则直接登录，否则拒绝登录3
        if (memberAuth != null){
            if (memberAuth.getAuthId().equals(openId)) {
                // 查询访问凭证，并强制更新
                memberTokenDTO = memberTokenService.findDTOByMemberId(memberAuth.getMemberId(), Boolean.TRUE);
                // 修改用户信息
                updateMember(member,bindMobileDTO);
            }else {
                throw new ServiceException("手机号已被绑定");
            }
        }else {
            // 用户注册过，member表中有数据，登录表中没有数据，直接更新用户登录表
            // 创建用户登录认证
            memberAuth = memberAuthService.createByMobileByOpenId(member.getId(),member.getPlatformId(),
                    bindMobileDTO.getMobile(),bindMobileDTO.getOpenId());
            // 查询访问凭证，并强制更新
            memberTokenDTO = memberTokenService.findDTOByMemberId(memberAuth.getMemberId(), Boolean.TRUE);
            // 修改用户图像
            updateInformation(memberAuth.getMemberId(),bindMobileDTO.getNickname(),bindMobileDTO.getAvatar());
        }

        return memberTokenDTO;
    }

    /**
     * 更新用户信息
     */
    @Transactional
    public Member updateMember(Member member,BindMobileDTO bindMobileDTO){
        member.setAvatar(bindMobileDTO.getAvatar());
        member.setNickname(bindMobileDTO.getNickname());
        member.setMobile(bindMobileDTO.getMobile());
        if (bindMobileDTO.getName() != null){
            member.setName(bindMobileDTO.getName());
        }
        if (bindMobileDTO.getSex() != null){
            member.setSex(bindMobileDTO.getSex());
        }
        if (bindMobileDTO.getAge() != null){
            member.setAge(bindMobileDTO.getAge());
        }
        if (bindMobileDTO.getAddress() != null){
            member.setAddress(bindMobileDTO.getAddress());
        }
        try {
            member.setAvatar(updateWxImgToOss(bindMobileDTO.getAvatar()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        memberService.update(member);
        return member;
    }

    /**
     * 退出登录
     */
    public void logout(Integer memberId){
        memberTokenService.logout(memberId);
    }

    /***
     * 修改用户图像
     */
    @Transactional
    public void updateInformation(Integer memberId,String nickname,String avatar){
        // 修改用户图像，昵称同步微信
        Member member = memberService.findById(memberId);
        memberService.verify(member);

        if (nickname != null){
            member.setNickname(nickname);
        }
        member.setAvatar(avatar);
        try {
            member.setAvatar(updateWxImgToOss(avatar));
        } catch (Exception e) {
            e.printStackTrace();
        }
        memberService.update(member);
    }
}

