package com.cool.store.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.dao.*;
import com.cool.store.dto.wx.*;
import com.cool.store.entity.*;
import com.cool.store.enums.*;
import com.cool.store.exception.ServiceException;
import com.cool.store.http.WechatRest;
import com.cool.store.mapper.HyPartnerUserChannelMapper;
import com.cool.store.request.MobileUpdateRequest;
import com.cool.store.service.WechatMiniAppService;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.UUIDUtils;
import com.cool.store.vo.PartnerUserInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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

/**
 * @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;
    @Autowired
    private HyPartnerUserChannelMapper hyPartnerUserChannelMapper;
    @Resource
    private LineInfoDAO lineInfoDAO;
    @Resource
    HyOpenAreaInfoDAO hyOpenAreaInfoDAO;
    @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())){
            HyPartnerUserInfoDO hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByOpenid(openid);
            if( hyPartnerUserInfoDO != null && !hyPartnerUserInfoDO.getMobile().equals(phoneInfoDTO.getPhoneInfo().getPhoneNumber())){
                throw new ServiceException(ErrorCodeEnum.WECHAT_BIND_OTHER_MOBILE);
            }
            // 微信未授权过
            if(hyPartnerUserInfoDO == null){
                hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
                if(hyPartnerUserInfoDO != null && StringUtils.isNotBlank(hyPartnerUserInfoDO.getOpenid()) && !openid.equals(hyPartnerUserInfoDO.getOpenid())){
                    throw new ServiceException(ErrorCodeEnum.MOBILE_WECHAT_EXIST);
                }
                if(hyPartnerUserInfoDO == null){
                    hyPartnerUserInfoDO = new  HyPartnerUserInfoDO();
                    hyPartnerUserInfoDO.setMobile(phoneInfoDTO.getPhoneInfo().getPhoneNumber());
                    hyPartnerUserInfoDO.setOpenid(openid);
                    hyPartnerUserInfoDO.setPartnerId(UUIDUtils.get32UUID());
                    Integer channelId = null;
                    String userChannel = param.getUserChannelEnum();
                    if(StringUtils.isNotEmpty(userChannel)){
                        if(UserChannelEnum.EXHIBITION.getCode().equals(userChannel)){
                            channelId = exhibition;
                        }else if(UserChannelEnum.RECOMMENDED.getCode().equals(userChannel)){
                            channelId = recommended;
                        }else {
                            if (StringUtils.isNumeric(userChannel)) {
                                channelId = Integer.valueOf(userChannel);
                                HyPartnerUserChannelDO hyPartnerUserChannelDO = hyPartnerUserChannelMapper.selectByChannelId(Long.valueOf(channelId));
                                if (Objects.isNull(hyPartnerUserChannelDO)|| hyPartnerUserChannelDO.getChannelId() == null ) {
                                    //用户渠道不存在
                                    throw new ServiceException(ErrorCodeEnum.USER_CHANNEL_NOT_EXISTS);
                                }

                            }
                        }
                    }
                    hyPartnerUserInfoDO.setUserChannelId(channelId);
                    hyPartnerUserInfoDAO.insertSelective(hyPartnerUserInfoDO);
                    //授权的时候 新增线索 放到公海
                    LineInfoDO lineInfoDO = new LineInfoDO();
                    lineInfoDO.setLineStatus(LineStatusEnum.PUBLIC_SEAS.getCode());
                    lineInfoDO.setWorkflowSubStage(WorkflowSubStageEnum.INTEND.getCode());
                    lineInfoDO.setMobile(hyPartnerUserInfoDO.getMobile());
                    lineInfoDO.setWorkflowStage(WorkflowStageEnum.INTENT.getCode());
                    lineInfoDO.setWorkflowSubStageStatus(WorkflowSubStageStatusEnum.INTENT_0.getCode());
                    lineInfoDO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
                    lineInfoDAO.insertOrUpdate(lineInfoDO);
                }else {
                    hyPartnerUserInfoDO.setOpenid(openid);
                    hyPartnerUserInfoDAO.updateByPrimaryKeySelective(hyPartnerUserInfoDO);
                }
            }
            BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
            fillLineInfo(userInfoVO, hyPartnerUserInfoDO.getPartnerId());
        }
        userInfoVO.setOpenid(openid);
        userInfoVO.setUnionId(unionId);
        return userInfoVO;
    }

    @Override
    public PartnerUserInfoVO getUserInfoByJsCode(String jsCode) {
        PartnerUserInfoVO userInfoVO = null;
        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);
        HyPartnerUserInfoDO hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByOpenid(openid);
        if(hyPartnerUserInfoDO != null){
            userInfoVO = new PartnerUserInfoVO();
            BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
            fillLineInfo(userInfoVO, hyPartnerUserInfoDO.getPartnerId());
        }
        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;
        }
        HyPartnerUserInfoDO hyPartnerUserInfoDO = hyPartnerUserInfoDAO.selectByOpenid(openId);
        if(hyPartnerUserInfoDO != null){
            BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
            /*if(StringUtils.isNotBlank(hyPartnerUserInfoDO.getWantShopArea())){
                HyOpenAreaInfoDO hyOpenAreaInfoDO = hyOpenAreaInfoDAO.selectById(Long.valueOf(hyPartnerUserInfoDO.getWantShopArea()));
                userInfoVO.setWantShopAreaName(hyOpenAreaInfoDO.getAreaPath().replace("/", " ").trim());
            }*/
            fillLineInfo(userInfoVO, hyPartnerUserInfoDO.getPartnerId());
        }
        return userInfoVO;
    }

    private void fillLineInfo(PartnerUserInfoVO userInfoVO, String partnerId) {
        LineInfoDO lineInfoDO = lineInfoDAO.getByPartnerId(partnerId);
        if (lineInfoDO != null){
            userInfoVO.setLiveAddress(lineInfoDO.getLiveAddress());
            userInfoVO.setUsername(lineInfoDO.getUsername());
            userInfoVO.setLineId(lineInfoDO.getId());
            userInfoVO.setWorkflowStage(lineInfoDO.getWorkflowStage());
            userInfoVO.setWorkflowSubStage(lineInfoDO.getWorkflowSubStage());
            userInfoVO.setWorkflowSubStageStatus(lineInfoDO.getWorkflowSubStageStatus());
            userInfoVO.setLineStatus(lineInfoDO.getLineStatus());
            userInfoVO.setLineSource(lineInfoDO.getLineSource());
        }
    }

    @Override
    public String getMiniAppUrl() {
        MiniAppUrlLinkReqDTO miniAppUrlLinkReqDTO = new MiniAppUrlLinkReqDTO();
        return getMiniAppUrlLink(miniAppUrlLinkReqDTO);
    }

    @Override
    public String getMiniAppUrlLink(MiniAppUrlLinkReqDTO miniAppUrlLinkReqDTO) {
        String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
        MiniAppUrlLinkDTO miniAppUrlLink = wechatRest.getMiniAppUrlLink(accessToken, miniAppUrlLinkReqDTO);
        if (miniAppUrlLink != null){
            return miniAppUrlLink.getUrlLink();
        }
        return null;
    }

}
