package com.ycwl.basic.service.mobile.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.constant.NumberConstant;
import com.ycwl.basic.enums.BizCodeEnum;
import com.ycwl.basic.enums.WechatErrorCodeEnum;
import com.ycwl.basic.exception.AppException;
import com.ycwl.basic.mapper.MemberMapper;
import com.ycwl.basic.model.jwt.JwtInfo;
import com.ycwl.basic.model.mobile.weChat.DTO.WeChatUserInfoDTO;
import com.ycwl.basic.model.mobile.weChat.DTO.WeChatUserInfoUpdateDTO;
import com.ycwl.basic.model.pc.member.entity.MemberEntity;
import com.ycwl.basic.model.pc.member.req.MemberReqQuery;
import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppMemberService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.JwtTokenUtil;
import com.ycwl.basic.utils.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author：songmingsong
 */
@Slf4j
@Service
public class AppMemberServiceImpl implements AppMemberService {
    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private ScenicRepository scenicRepository;

    public static final String GET_OPEN_ID = "https://api.weixin.qq.com/sns/jscode2session";

    @Override
    public Map<String, Object> getOpenId(Long scenicId, String code) {
        Map<String, Object> paramMap = new HashMap<>(NumberConstant.FOUR);
        MpConfigEntity scenicMpConfig = scenicRepository.getScenicMpConfig(scenicId);
        paramMap.put("appid", scenicMpConfig.getAppId());
        paramMap.put("secret", scenicMpConfig.getAppSecret());
        paramMap.put("js_code", code);
        paramMap.put("grant_type", "authorization_code");
        try {
            String response = HttpUtil.post(GET_OPEN_ID, paramMap);
            if (StringUtils.isBlank(response)) {
                return null;
            }
            return JSONObject.parseObject(response);
        } catch (Exception e) {
            log.error("getOpenId", e);
            throw new AppException(BizCodeEnum.SERVER_INTERNAL_ERROR);
        }
    }


    @Override
    public ApiResponse login(Long scenicId, String code, WeChatUserInfoDTO userInfoDTO) throws Exception {
        Map<String, Object> weixinResponse = this.getOpenId(scenicId, code);
        if (CollectionUtils.isEmpty(weixinResponse)) {
            throw new AppException(BizCodeEnum.SERVER_INTERNAL_ERROR);
        }
        Object errcode = weixinResponse.get("errcode");
        if (errcode != null) {
            WechatErrorCodeEnum errorCode = WechatErrorCodeEnum.getErrorCode(errcode.toString());
            throw new AppException(BizCodeEnum.PARAM_ERROR.getCode(), errorCode.getDetail());
        }

        // 获取openId
        Object openId = weixinResponse.get("openid");
        if (openId == null) {
            log.warn("warning={}", "未获取到当前用户openId");
            throw new AppException(BizCodeEnum.SERVER_UNKONWN_ERROR, "未获取到当前用户openId");
        }

        MemberRespVO memberRespVO = new MemberRespVO();
        JwtInfo jwtInfo = new JwtInfo();
        // 根据返回的openId，判断用户是否是新用户，是的话，将用户信息存到数据库；
        MemberReqQuery memberReqQuery = new MemberReqQuery();
        memberReqQuery.setOpenId(openId.toString());
        List<MemberRespVO> list = memberMapper.list(memberReqQuery);
        if (list.isEmpty()) {
            MemberEntity memberEntity = new MemberEntity();
            memberEntity.setId(SnowFlakeUtil.getLongId());
            memberEntity.setScenicId(scenicId);
            memberEntity.setOpenId(openId.toString());
            memberEntity.setNickname(userInfoDTO.getNickname());
            memberEntity.setAvatarUrl(userInfoDTO.getAvatarUrl());
            memberEntity.setAgreement(1);
            memberEntity.setPhone(userInfoDTO.getPhone());
            memberEntity.setCountry(userInfoDTO.getCountry());
            memberEntity.setProvince(userInfoDTO.getProvince());
            memberEntity.setCity(userInfoDTO.getCity());
            memberMapper.add(memberEntity);
            memberRespVO.setId(memberEntity.getId());
            memberRespVO.setOpenId(memberEntity.getOpenId());
            memberRespVO.setNickname(memberEntity.getNickname());
            memberRespVO.setAvatarUrl(memberEntity.getAvatarUrl());
            memberRespVO.setAgreement(1);
            memberRespVO.setPhone(memberEntity.getPhone());
            memberRespVO.setCountry(memberEntity.getCountry());
            memberRespVO.setProvince(memberEntity.getProvince());
            memberRespVO.setCity(memberEntity.getCity());
            memberRespVO.setScenicId(memberEntity.getScenicId());
        } else {
            MemberRespVO temp = list.getFirst();
            memberRespVO.setId(temp.getId());
            memberRespVO.setOpenId(temp.getOpenId());
            memberRespVO.setNickname(temp.getNickname());
            memberRespVO.setAvatarUrl(temp.getAvatarUrl());
            memberRespVO.setAgreement(1);
            memberRespVO.setPhone(temp.getPhone());
            memberRespVO.setCountry(temp.getCountry());
            memberRespVO.setProvince(temp.getProvince());
            memberRespVO.setCity(temp.getCity());
            memberRespVO.setScenicId(temp.getScenicId());
        }
        jwtInfo.setUserId(memberRespVO.getId());
        jwtInfo.setName(memberRespVO.getNickname());
        jwtInfo.setPhone(memberRespVO.getPhone());

        String jwt = jwtTokenUtil.generateToken(jwtInfo);
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("token", jwt);
        resMap.put("user", memberRespVO);

        return ApiResponse.success(resMap);
    }

    @Override
    public ApiResponse<MemberRespVO> getUserInfo() {
        MemberRespVO respVO = memberMapper.getById(Long.parseLong(BaseContextHandler.getUserId()));
        return ApiResponse.success(respVO);
    }

    @Override
    public ApiResponse<?> update(WeChatUserInfoUpdateDTO userInfoUpdateDTO) {
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setId(Long.parseLong(BaseContextHandler.getUserId()));
        memberEntity.setNickname(userInfoUpdateDTO.getNickname());
        memberEntity.setAvatarUrl(userInfoUpdateDTO.getAvatarUrl());
        memberEntity.setAgreement(userInfoUpdateDTO.getAgreement());
        return ApiResponse.success(memberMapper.update(memberEntity));
    }

    @Override
    public ApiResponse<?> agreement() {
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setId(Long.parseLong(BaseContextHandler.getUserId()));
        memberEntity.setAgreement(1);
        return ApiResponse.success(memberMapper.update(memberEntity));
    }

    @Override
    public ApiResponse<String> updateScenicServiceNoticeStatus(Long scenicId) {
        JwtInfo worker = JwtTokenUtil.getWorker();
        Integer scenicServiceNoticeStatus = memberMapper.getScenicServiceNoticeStatus(scenicId, worker.getUserId());
        //没有就初始化为开启
        if(scenicServiceNoticeStatus==null){
            int i = memberMapper.addScenicServiceNoticeStatus(scenicId, worker.getUserId());
            if(i>0){
                return ApiResponse.success("成功");
            }else {
                return ApiResponse.fail("失败");
            }
        }else {
            // 有就修改
            int i = memberMapper.updateScenicServiceNoticeStatus(scenicId, worker.getUserId());
            if (i == 0) {
                return ApiResponse.fail("失败");
            }
            return ApiResponse.success("成功");
        }

    }

    @Override
    public ApiResponse<Integer> getScenicServiceNoticeStatus(Long scenicId) {
        Integer scenicServiceNoticeStatus = memberMapper.getScenicServiceNoticeStatus(scenicId, Long.parseLong(BaseContextHandler.getUserId()));
        if(scenicServiceNoticeStatus==null){
            scenicServiceNoticeStatus=0;
        }
        return ApiResponse.success(scenicServiceNoticeStatus);
    }
}
