package com.qiankun.controller.mdp;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.qiankun.annotation.Auth;
import com.qiankun.config.WxMaConfiguration;
import com.qiankun.config.WxMaProperties;
import com.qiankun.dao.UserDao;
import com.qiankun.entity.*;
import com.qiankun.service.ActivityService;
import com.qiankun.service.BloodService;
import com.qiankun.service.UserService;
import com.qiankun.utils.JwtTokenUtil;
import com.qiankun.utils.QRCodeUtil;
import com.qiankun.utils.UserUtils;
import com.qiankun.vo.DecryptedDataVo;
import com.qiankun.vo.PaperIdLoginVo;
import com.qiankun.vo.UserVo;
import com.sun.mail.imap.ResyncData;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/wx/mdp")
public class MdpController {
    private final Logger logger = LoggerFactory.getLogger(MdpController.class);
    @Autowired
    private JwtTokenUtil tokenUtil;
    @Autowired
    private WxMaProperties propertis;
    @Autowired
    private UserService userService;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private BloodService bloodService;
    private ResourceBundle rb = ResourceBundle.getBundle("system");
    private String getAppid(){
        return propertis.getConfigs().get(1).getAppid();
    }
    private String uploadAvatarPath = File.separator + "mdp" + File.separator + "uploadAvatar";

    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public Map<String,Object> login(@RequestParam String code) throws Exception {
        if (StringUtils.isBlank(code)) {
            return null;
        }

        final WxMaService wxService = WxMaConfiguration.getMaService(getAppid());

        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
            this.logger.info(session.getSessionKey());
            this.logger.info(session.getOpenid());
            Map<String,Object> result = Maps.newConcurrentMap();

            User userInfo = userService.findByOpenid(session.getOpenid());
            if (userInfo != null){
                String sKey = tokenUtil.generateToken(userInfo.getOpenid());
                result.put("sKey",sKey);
                result.put("userInfo", UserUtils.converToVo(userInfo));
            }else {
                result.put("sKey","");
                result.put("userInfo","");
                result.put("openid",session.getOpenid());
            }

            return result;
        } catch (WxErrorException e) {
            this.logger.error(e.getMessage(), e);
            throw new Exception(e.getMessage(),e);
        }
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value ="/loginByPaperId",method = RequestMethod.POST)
    public Map<String,Object> loginByPaperId(@RequestBody PaperIdLoginVo vo){
        User user = userService.findByPaperId(vo.getPaperId(),vo.getPaperType());
        Map<String,Object> result = Maps.newConcurrentMap();
        if (user == null){
            //新用户
            result.put("isExist",false);
        }else {
            //老用户
            if (!user.getName().equals(vo.getName())){
                result.put("errorMsg","姓名与库中信息不符，请核实后重新提交");
            }else if(!Strings.isNullOrEmpty(user.getOpenid())){
                result.put("errorMsg","该用户已与其他微信绑定");
            }else {

                user.setOpenid(vo.getOpenid());
                if (!Strings.isNullOrEmpty(vo.getPhone())){
                    //更新微信绑定的手机号
                    user.setMobile(vo.getPhone());
                }
                userService.save(user);
                result.put("sKey",tokenUtil.generateToken(user.getOpenid()));
                result.put("userInfo",UserUtils.converToVo(user));
            }
            result.put("isExist",true);
        }
        return result;
    }

    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public UserVo getUserInfo(@RequestHeader String sKey){
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        User user = userService.findByOpenid(openid);
        return UserUtils.converToVo(user);
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/findUser",method = RequestMethod.GET)
    public UserVo findUserById(@RequestParam String id){
        User user = userService.findById(id);
        return UserUtils.converToVo(user);
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/decryptedData",method = RequestMethod.POST)
    public Map<String,Object> decryptedData(@RequestBody DecryptedDataVo dataVo){
        Map<String,Object> result = Maps.newConcurrentMap();
        final WxMaService wxService = WxMaConfiguration.getMaService(getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(dataVo.getCode());
            WxMaUserService wxUserService = wxService.getUserService();
            WxMaPhoneNumberInfo phoneInfo = wxUserService.getPhoneNoInfo(session.getSessionKey(),dataVo.getEncryptedData(),dataVo.getIv());
            result.put("status","ok");
            result.put("phoneInfo",phoneInfo);
        } catch (WxErrorException e) {
            result.put("status","error");
            result.put("errorMsg","微信登陆失败");
        }
        return result;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/uploadAvatar",method = RequestMethod.POST)
    public Map<String,String> uploadAvatar(MultipartFile file,@RequestHeader String sKey){
        Map<String,String> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        User user = userService.findByOpenid(openid);
        if (user == null){
            result.put("status","error");
            result.put("errorMsg","用户不存在");
            return result;
        }
        try{
            if (file != null && !file.isEmpty()){
                String originalFileName = file.getOriginalFilename();
                String rootPath = rb.getString("file_path");
                File destFile = new File(rootPath + uploadAvatarPath,originalFileName);
                FileUtils.writeByteArrayToFile(destFile,file.getBytes());
                user.setAvatarImage(uploadAvatarPath + File.separator + originalFileName);
                userService.save(user);
                result.put("status","ok");
                result.put("avatarImage",user.getAvatarImage());
            }else {
                result.put("status","error");
                result.put("errorMsg","上传文件不存在");
                return result;
            }
        }catch (IOException e){
            logger.error(e.getMessage(),e);
            result.put("status","error");
            result.put("errorMsg","上传文件失败");
        }

        return result;
    }

    /**
     * 获取用户积分、参与的活动等相关信息
     * @param sKey
     * @return
     */
    @Auth(verifyURL = false,verifyLogin = false)
    @RequestMapping(value = "/userActivityInfo",method = RequestMethod.GET)
    public Map<String,Object> getUserActivityInfo(@RequestHeader String sKey){
        Map<String,Object> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        User user = userService.findByOpenid(openid);
        if (user == null){
            result.put("status","error");
            result.put("errorMsg","用户不存在");
            return result;
        }

        if (Strings.isNullOrEmpty(user.getName()) ||
                Strings.isNullOrEmpty(user.getBirthday()) ||
                Strings.isNullOrEmpty(user.getPaperType()) ||
                Strings.isNullOrEmpty(user.getPaperId()) ||
                Strings.isNullOrEmpty(user.getNation()) ||
                Strings.isNullOrEmpty(user.getNationality()) ||
                Strings.isNullOrEmpty(user.getNativePlace()) ||
                Strings.isNullOrEmpty(user.getAddr()) ||
                Strings.isNullOrEmpty(user.getMobile()) ||
                Strings.isNullOrEmpty(user.getQq()) ||
                !validateContacts(user)){
            result.put("userInfoStatus","unComplete");
        }else{
            result.put("userInfoStatus","complete");
        }
        result.put("points",getUserPoints(user));
        result.put("status","ok");
        return result;
    }

    /**
     * 获取用户积分
     * @param user
     * @return
     */
    private int getUserPoints(User user){
        return 0;
    }
    private boolean validateContacts(User user){
        boolean flag = true;
        Set<Contacts> sets = user.getContacts();
        if (sets == null){
            flag = false;
        }else {
            Iterator<Contacts> it = sets.iterator();
            while (it.hasNext()){
                Contacts c = it.next();
                if (Strings.isNullOrEmpty(c.getName()) ||
                    Strings.isNullOrEmpty(c.getRelation()) ||
                    Strings.isNullOrEmpty(c.getMobile())){
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/loadResource",method = RequestMethod.GET)
    public ResponseEntity<byte[]> loadResource(@RequestParam String imageName) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        File file = new File(rb.getString("file_path"),imageName);
        return new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/userQrcode",method = RequestMethod.GET)
    public void getUserQrcode(@RequestParam String id, HttpServletResponse response) throws Exception {
        QRCodeUtil.generateQRCode(id,100,100,"png",response);
        response.flushBuffer();
    }
    @Auth(verifyURL = false,verifyLogin = false)
    @RequestMapping(value = "/activity/apply",method = RequestMethod.GET)
    public Map<String,Object> activityApply(@RequestParam String userId,@RequestParam String activityId){
        Map<String,Object> result = Maps.newConcurrentMap();
        User user = userService.findById(userId);
        if (user == null){
            result.put("status","error");
            result.put("errorMsg","用户不存在");
            return result;
        }
        Activity activity = activityService.findById(activityId);
        if (activity == null){
            result.put("status","error");
            result.put("errorMsg","活动不存在");
            return result;
        }else if (!activity.isAvailable()){
            result.put("status","error");
            result.put("errorMsg","活动已关闭");
            return result;
        }else if (activity.getActivityReg().size() >= activity.getMax()){
            result.put("status","error");
            result.put("errorMsg","活动报名人数已达上限");
            return result;
        }
        ActivityReg reg = new ActivityReg();
        reg.setUser(user);
        reg.setActivity(activity);
        activityService.saveActivityReg(reg);
        result.put("status","ok");
        return result;
    }
    @Auth(verifyURL = false,verifyLogin = false)
    @RequestMapping(value = "/activity/collectionBlood",method = RequestMethod.POST)
    public Map<String,Object> collectionBlood(@RequestBody Map<String,String> formData,@RequestHeader String sKey){
        Map<String,Object> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        if (Strings.isNullOrEmpty(openid)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String userId = formData.get("userId");
        String activityId = formData.get("activityId");
        String bloodId = formData.get("bloodId");

        User user = userService.findById(userId);
        Activity activity = activityService.findById(activityId);
        //验证一个用户在一次采血活动中只能有一次采血
        boolean isExist = bloodService.isExistByUserAndActivty(user,activity);
        if (isExist){
            result.put("status","error");
            result.put("errorMsg","该用户已经采血，请不要重复采集");
            return result;
        }
        Blood blood = new Blood();
        blood.setBloodId(bloodId);
        blood.setBloodAddr(activity.getAddr());
        blood.setUpdateTime(new Date());
        blood.setUser(user);
        blood.setActivity(activity);
        bloodService.save(blood);
        result.put("status","ok");
        return result;
    }
}
