package com.cool.store.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
import com.cool.store.constants.CommonConstants;
import com.cool.store.dao.*;
import com.cool.store.dto.wx.CodeSessionDTO;
import com.cool.store.dto.wx.MiniProgramLoginDTO;
import com.cool.store.dto.wx.PhoneInfoDTO;
import com.cool.store.entity.HyOpenAreaInfoDO;
import com.cool.store.entity.HyPartnerLineInfoDO;
import com.cool.store.entity.HyPartnerUserInfoDO;
import com.cool.store.entity.HyPartnerUserPlatformBindDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.enums.UserChannelEnum;
import com.cool.store.enums.UserPlatformTypeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.http.WechatRest;
import com.cool.store.request.MobileUpdateRequest;
import com.cool.store.service.HyPhoneLocationService;
import com.cool.store.service.WechatMiniAppService;
import com.cool.store.utils.AesUtil;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.UUIDUtils;
import com.cool.store.vo.PartnerUserInfoVO;
import com.cool.store.vo.wx.MiniProgramUserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.Date;

/**
 * @author zhangchenbiao
 * @FileName: WechatMiniAppServiceImpl
 * @Description:
 * @date 2023-05-29 14:29
 */
@Slf4j
@Service
public class WechatMiniAppServiceImpl implements WechatMiniAppService {

    @Resource
    private RedisUtilPool redisUtilPool;
    @Resource
    private WechatRest wechatRest;
    @Resource
    private HyPartnerUserInfoDAO hyPartnerUserInfoDAO;
    @Resource
    private HyPartnerUserPlatformBindDAO hyPartnerUserPlatformBindDAO;
    @Resource
    private HyPartnerLineInfoDAO hyPartnerLineInfoDAO;
    @Resource
    HyOpenAreaInfoDAO hyOpenAreaInfoDAO;
    @Resource
    HyPartnerBaseInfoDAO hyPartnerBaseInfoDAO;
    @Resource
    HyPhoneLocationService hyPhoneLocationService;

    @Value("${weixin.appId}")
    private String wxAppId;
    @Value("${weixin.appSecret}")
    private String wxAppSecret;
    @Value("${fixMobileOpenid}")
    private String fixMobileOpenid;
    @Value("${exhibition.channel.id}")
    private Integer exhibition;
    @Value("${recommended.channel.id}")
    private Integer recommended;


    @Override
    public PartnerUserInfoVO miniProgramLogin(MiniProgramLoginDTO param) {
        log.info("miniProgramLogin #param {}", JSONObject.toJSONString(param));
        PartnerUserInfoVO userInfoVO = new PartnerUserInfoVO();
        String jsCode = param.getJsCode();
        String lockKey = "codeSession:" + wxAppId + CommonConstants.MOSAICS + jsCode;
        boolean lock = redisUtilPool.lock(lockKey);
        if (!lock) {
            throw new ServiceException(ErrorCodeEnum.OPERATION_OVER_TIME);
        }
        CodeSessionDTO codeSession = wechatRest.miniProgramJsCodeSession(wxAppId, wxAppSecret, jsCode);
        String openid = codeSession.getOpenid();
        String sessionCacheKey = MessageFormat.format(CommonConstants.MINI_PROGRAM_SESSION_KEY, wxAppId, openid);
        redisUtilPool.setString(sessionCacheKey, codeSession.getSessionKey(), CommonConstants.THREE_DAY_SECONDS);
        String unionId = codeSession.getUnionId();
        log.info("小程序登录:{}", unionId);
        log.info("sessionKey {}", codeSession.getSessionKey());
       /* String decryptUser = AesUtil.decryptWechat(codeSession.getSessionKey(), param.getEncryptedData(), param.getIvStr());
        log.info("解密用户信息：{}", decryptUser);
        MiniProgramUserVO miniProgramUser = JSON.parseObject(decryptUser, MiniProgramUserVO.class);
        if (Objects.isNull(miniProgramUser)) {
            throw new ServiceException(ErrorCodeEnum.GET_WECHAT_USER_INFO_FAIL);
        }*/
        // 获取小程序token
        String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
        // 获取手机号码
        PhoneInfoDTO phoneInfoDTO = wechatRest.getUserPhoneNumber(param.getMobileCode(), accessToken);
        if(phoneInfoDTO != null && phoneInfoDTO.getPhoneInfo() != null && StringUtils.isNotBlank(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){

            HyPartnerUserPlatformBindDO hyPartnerUserPlatformBindDO = hyPartnerUserPlatformBindDAO.getByPlatformTypeAndUserId(UserPlatformTypeEnum.WECHAT.getCode(), openid);
            HyPartnerUserInfoDO hyPartnerUserInfoDO = null;
            // 微信未授权过
            if(hyPartnerUserPlatformBindDO == null){
                hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
                if(hyPartnerUserInfoDO == null){
                    hyPartnerUserInfoDO = new  HyPartnerUserInfoDO();
                    hyPartnerUserInfoDO.setMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
                    // hyPartnerUserInfoDO.setUsername(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
                    hyPartnerUserInfoDO.setPartnerId(UUIDUtils.get32UUID());
                    hyPartnerUserInfoDO.setIsWritePartnerKnow(0);
                    Integer channelId = null;
                    if (param.getUserChannelEnum()!=null && UserChannelEnum.EXHIBITION.getCode().equals(param.getUserChannelEnum().getCode())){
                        channelId = exhibition;
                    }
                    if (param.getUserChannelEnum()!=null && UserChannelEnum.RECOMMENDED.getCode().equals(param.getUserChannelEnum().getCode())){
                        channelId = recommended;
                    }
                    hyPartnerUserInfoDO.setUserChannelId(channelId);
                    hyPartnerUserInfoDAO.insertSelective(hyPartnerUserInfoDO);
                }
                hyPartnerUserPlatformBindDO = new  HyPartnerUserPlatformBindDO();
                hyPartnerUserPlatformBindDO.setPlatformType(UserPlatformTypeEnum.WECHAT.getCode());
                hyPartnerUserPlatformBindDO.setPlatformUserId(openid);
                hyPartnerUserPlatformBindDO.setBindTime(new Date());
                hyPartnerUserPlatformBindDO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
                hyPartnerUserPlatformBindDAO.insertSelective(hyPartnerUserPlatformBindDO);
            }else {
                hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByPartnerId(hyPartnerUserPlatformBindDO.getPartnerId());
            }
            if(!hyPartnerUserInfoDO.getMobile().equals(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){
                throw new ServiceException(ErrorCodeEnum.WECHAT_BIND_OTHER_MOBILE);
            }
            BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
            HyPartnerLineInfoDO lineInfoDO = hyPartnerLineInfoDAO.getByPartnerId(hyPartnerUserInfoDO.getPartnerId());
            if (lineInfoDO != null){
                userInfoVO.setPartnerLineId(lineInfoDO.getId());
            }
        }
        userInfoVO.setOpenid(openid);
        userInfoVO.setUnionId(unionId);
        return userInfoVO;
    }

    @Override
    public String getUserPhoneNumber(String mobileCode) {
        // 获取小程序token
        String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
        // 获取手机号码
        PhoneInfoDTO phoneInfoDTO = wechatRest.getUserPhoneNumber(mobileCode, accessToken);
        if(phoneInfoDTO != null && phoneInfoDTO.getPhoneInfo() != null && StringUtils.isNotBlank(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){
            return phoneInfoDTO.getPhoneInfo().getPhoneNumber();
        }
        return null;
    }

    @Override
    public String updateUserPhoneNumber(MobileUpdateRequest request, PartnerUserInfoVO userInfoVO) {
        String newMobile = "";
        HyPartnerUserInfoDO oldUserInfo = hyPartnerUserInfoDAO.selectByMobile(userInfoVO.getMobile());
        if (oldUserInfo == null) {
            throw new ServiceException(ErrorCodeEnum.PARTNER_USER_NOT_EXIST);
        }
        // 获取小程序token
        String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
        // 获取手机号码
        PhoneInfoDTO phoneInfoDTO = wechatRest.getUserPhoneNumber(request.getMobileCode(), accessToken);
        if(phoneInfoDTO != null && phoneInfoDTO.getPhoneInfo() != null && StringUtils.isNotBlank(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){
            newMobile = phoneInfoDTO.getPhoneInfo().getPhoneNumber();
            if(newMobile.equals(oldUserInfo.getMobile())){
                return newMobile;
            }
            HyPartnerUserInfoDO newUserInfo = hyPartnerUserInfoDAO.selectByMobile(newMobile);
            if (newUserInfo != null) {
                throw new ServiceException(ErrorCodeEnum.NEW_MOBILE_HAS_EXIST);
            }
            oldUserInfo.setMobile(newMobile);
            hyPartnerUserInfoDAO.updateByPrimaryKeySelective(oldUserInfo);
            //修改意向申请信息中的手机号
            hyPartnerBaseInfoDAO.updateByPartnerId(null, newMobile, oldUserInfo.getPartnerId());
        }
        return newMobile;
    }

    @Override
    public PartnerUserInfoVO getUserInfo(String mobile, String openId) {
        PartnerUserInfoVO userInfoVO = new PartnerUserInfoVO();
        if(fixMobileOpenid.equals(mobile)){
            userInfoVO.setMobile(mobile);
            userInfoVO.setOpenid(mobile);
            userInfoVO.setPartnerId("");
            return  userInfoVO;
        }
        HyPartnerUserPlatformBindDO hyPartnerUserPlatformBindDO = hyPartnerUserPlatformBindDAO.getByPlatformTypeAndUserId(UserPlatformTypeEnum.WECHAT.getCode(), openId);
        if(hyPartnerUserPlatformBindDO != null){
            HyPartnerUserInfoDO hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByPartnerId(hyPartnerUserPlatformBindDO.getPartnerId());
            BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
            userInfoVO.setOpenid(hyPartnerUserPlatformBindDO.getPlatformUserId());
            if(StringUtils.isNotBlank(hyPartnerUserInfoDO.getWantShopArea())){
                HyOpenAreaInfoDO hyOpenAreaInfoDO = hyOpenAreaInfoDAO.selectById(Long.valueOf(hyPartnerUserInfoDO.getWantShopArea()));
                userInfoVO.setWantShopAreaName(hyOpenAreaInfoDO.getAreaPath().replace("/", " ").trim());
            }
            HyPartnerLineInfoDO lineInfoDO = hyPartnerLineInfoDAO.getByPartnerId(hyPartnerUserInfoDO.getPartnerId());
            if (lineInfoDO != null){
                userInfoVO.setPartnerLineId(lineInfoDO.getId());
            }
        }
        return userInfoVO;
    }

}
