package com.qiankun.controller.rainbowplan;

import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qiankun.annotation.Auth;
import com.qiankun.config.WxMaConfiguration;
import com.qiankun.config.WxMaProperties;
import com.qiankun.controller.base.BaseController;
import com.qiankun.dao.RainbowPlanUserDao;
import com.qiankun.dao.WishDao;
import com.qiankun.dao.WishReplyDao;
import com.qiankun.dao.core.Hints;
import com.qiankun.entity.Activity;
import com.qiankun.entity.RainbowPlanUser;
import com.qiankun.entity.Wish;
import com.qiankun.entity.WishReply;
import com.qiankun.pages.IPageList;
import com.qiankun.service.ActivityService;
import com.qiankun.utils.JwtTokenUtil;
import com.qiankun.vo.*;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.util.UserDataDocumentFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
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.scheduling.support.SimpleTriggerContext;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

@RestController
@RequestMapping("/wx/rainbowplan")
public class RainbowPlanController extends BaseController<Object> {
    private final Logger logger = LoggerFactory.getLogger(RainbowPlanController.class);
    @Autowired
    private JwtTokenUtil tokenUtil;
    @Autowired
    private RainbowPlanUserDao userDao;
    @Autowired
    private WishDao wishDao;
    @Autowired
    private WishReplyDao wishReplyDao;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private WxMaProperties propertis;
    private ResourceBundle rb = ResourceBundle.getBundle("system");
    private String uploadAvatarPath = File.separator + "rainbowplan" + File.separator + "uploadAvatar";
    private String uploadWishImagePath = File.separator + "rainbowplan" + File.separator + "wishUploadImage";

    private String getAppid(){
        return propertis.getConfigs().get(0).getAppid();
    }


    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public Map<String,Object> login(@RequestParam String code){
        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();

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

            return result;
        } catch (WxErrorException e) {
            this.logger.error(e.getMessage(), e);
            return null;
        }
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/register",method = RequestMethod.POST)
    public Map<String,Object> register(@RequestBody RegisterInfo info) throws Exception {
        Map<String,Object> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(info.getOpenid())){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        RainbowPlanUser user = userDao.findByPhone(info.getPhone());
        if (info.getType() == RainbowPlanUser.TYPE_BABY && user != null){
            //红会人员录入过信息
            if (!Strings.isNullOrEmpty(user.getOpenid())){
                //如果openid不为空，说明该手机号已与其它微信绑定
                result.put("status","error");
                result.put("errorMsg","该手机号已与其它微信绑定");
                return result;
            }
            user.setName(info.getName());
            user.setGender(info.getGender());
            user.setOpenid(info.getOpenid());
            result.put("isExist",true);
            userDao.update(user);
        }else if (info.getType() == RainbowPlanUser.TYPE_BABY && user == null){
            //新注册用户
            user = new RainbowPlanUser();
            user.setPhone(info.getPhone());
            user.setName(info.getName());
            user.setGender(info.getGender());
            user.setOpenid(info.getOpenid());
            user.setType(info.getType());
            if (Strings.isNullOrEmpty(info.getInviter())){
                //无邀请码用户
                user.setStatus(RainbowPlanUser.STATUS_UNAUDIT);
            }else if (inviterExist(info.getInviter())){
                user.setStatus(RainbowPlanUser.STATUS_AUDIT);
                user.setInviterId(info.getInviter());
            }else {
                result.put("status","error");
                result.put("errorMsg","注册失败，邀请者不存在");
                return result;
            }
            userDao.save(user);
        }else if (info.getType() == RainbowPlanUser.TYPE_LOVE && user == null){
            //爱心人士
            user = new RainbowPlanUser();
            user.setPhone(info.getPhone());
            user.setName(info.getName());
            user.setType(info.getType());
            user.setOpenid(info.getOpenid());
            userDao.save(user);
        }else if (info.getType() == RainbowPlanUser.TYPE_LOVE && user != null){
            result.put("status","error");
            result.put("errorMsg","该手机号已存在");
            return result;
        }


        result.put("status","OK");
        result.put("userInfo",user);
        result.put("sKey",tokenUtil.generateToken(info.getOpenid()));
        return result;
    }

    private boolean inviterExist(String inviterId) {
        //TODO 判断邀请人是否存在
        return true;
    }

    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public RainbowPlanUser getUserInfo(@RequestHeader String sKey) throws Exception {
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        RainbowPlanUser user = userDao.findByOpenid(openid);
        if (user == null) {
            throw new Exception("请求的用户不存在");
        }

        return user;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/userInfo",method = RequestMethod.POST)
    public @ResponseBody RainbowPlanUser updateUserInfo(@RequestBody UserInfo info,@RequestHeader String sKey) throws Exception {
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        RainbowPlanUser user = userDao.findByOpenid(openid);
        if (user != null){
            user.setPhone(info.getPhone());
            user.setName(info.getName());
            user.setNickName(info.getNickName());
            user.setGender(info.getGender());
            user.setBirthday(info.getBirthday());
            user.setBedNum(info.getBedNum());
            user.setReceiveName(info.getReceiveName());
            user.setConnectTel(info.getConnectTel());
            user.setReceiveAddress(info.getReceiveAddress());
            user.setDisease(info.getDisease());
            userDao.update(user);
        }else {
            throw new Exception("保存失败，请求用户不存在");
        }

        return user;
    }

    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/userInfoWithAvatar",method = RequestMethod.POST)
    public @ResponseBody RainbowPlanUser updateUserInfoWithAvatar(UserInfo info, @RequestHeader String sKey) throws Exception {
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        RainbowPlanUser user = userDao.findByOpenid(openid);
        if (user != null){
            if (!info.getFile().isEmpty()){
                String originalFileName = info.getFile().getOriginalFilename();
                String rootPath = rb.getString("file_path");
                File destFile = new File(rootPath + uploadAvatarPath,originalFileName);
                FileUtils.writeByteArrayToFile(destFile,info.getFile().getBytes());
                user.setPhone(info.getPhone());
                user.setName(info.getName());
                user.setNickName(info.getNickName());
                user.setGender(info.getGender());
                user.setBirthday(info.getBirthday());
                user.setBedNum(info.getBedNum());
                user.setReceiveName(info.getReceiveName());
                user.setConnectTel(info.getConnectTel());
                user.setReceiveAddress(info.getReceiveAddress());
                user.setAvatar(uploadAvatarPath + File.separator + originalFileName);
                user.setDisease(info.getDisease());
                userDao.update(user);
            }else {
                throw new Exception("保存失败，请上传图片");
            }
        }else {
            throw new Exception("保存失败，请求用户不存在");
        }
        return user;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/publishWish",method = RequestMethod.POST)
    public String publishWish(PublishWish publishWish,@RequestHeader String sKey) throws Exception {
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        RainbowPlanUser user = userDao.findByOpenid(openid);
        if (user != null){
            if (!publishWish.getFile().isEmpty()){

                String originalFileName = publishWish.getFile().getOriginalFilename();
                String rootPath = rb.getString("file_path");
                File destFile = new File(rootPath + uploadWishImagePath,originalFileName);
                FileUtils.writeByteArrayToFile(destFile,publishWish.getFile().getBytes());
                Wish wish = new Wish();
                wish.setTitle(publishWish.getTitle());
                wish.setContent(publishWish.getWish());
                wish.setUploadImage(uploadWishImagePath + File.separator + originalFileName);
                wish.setStatus(Wish.STATUS_PUBLISH);
                wish.setRainbowPlanUserId(user.getId());
                wish.setActivityId(publishWish.getActivityId());
                
                wish.setChildren(user);
                wish.setActivity(activityService.findById(publishWish.getActivityId()));
                
                wishDao.save(wish);
            }else {
                throw new Exception("保存失败，请上传图片");
            }
        }else {
            throw new Exception("保存失败，请求用户不存在");
        }

        return "OK";
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/wish/myList",method = RequestMethod.GET)
    public Map<String,Object> myWishList(@RequestHeader String sKey,HttpServletRequest request){
        Map<String,Object> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        RainbowPlanUser user = userDao.findByOpenid(openid);
        if (user == null){
            result.put("status","error");
            result.put("errorMsg","用户不存在");
            return result;
        }
        if (user.getType() == RainbowPlanUser.TYPE_LOVE){
            IPageList<Wish> wishPageList = wishDao.findByVolunteeId(user.getId(),new Hints(getStartRow(request),getPageCount(request)));
            result.put("wishPageList",wishPageList);
        }
        result.put("status","OK");
        return result;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/wish/list",method = RequestMethod.GET)
    public Map<String,Object> wishList(@RequestHeader String sKey, HttpServletRequest request) throws Exception {
        Map<String,Object> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        RainbowPlanUser user = userDao.findByOpenid(openid);

        Activity activity = activityService.findByAavailableAndType("3");
        result.put("activity",activity == null ? "" : activity);
        if (activity == null || user == null){
            //没有活动时
            return result;
        }
        if (user.getType() == RainbowPlanUser.TYPE_BABY){
            //小朋友，只获取它自己的愿望
            IPageList<Wish> wishPage = wishDao.findByRainbowPlanUserId(user.getId(),activity.getId(),
                    new Hints(getStartRow(request),getPageCount(request)));
            result.put("wishPageList",wishPage);
        }else {
            //爱心人士，获取全部愿望
            IPageList<Wish> wishPage = wishDao.findAllByAvailableActivity(activity.getId(),
                    new Hints(getStartRow(request),getPageCount(request)));
            result.put("wishPageList",wishPage);
        }

        return result;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/wish",method = RequestMethod.GET)
    public WishDetailVo getWish(@RequestParam String id,@RequestHeader String sKey){
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);

        Wish wish = wishDao.findById(id);
        List<WishReply> replys = wishReplyDao.findByWishId(wish.getId());
        List<WishReplyVo> replyVoList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(replys)){
            List<String> ids = Lists.newArrayList();
            for(WishReply reply : replys){
                if (!ids.contains(reply.getRainbowplanUserId())){
                    ids.add(reply.getRainbowplanUserId());
                }
            }
            List<RainbowPlanUser> users = userDao.findByIds(ids);
            for (WishReply reply : replys){
                WishReplyVo vo = new WishReplyVo();
                BeanUtils.copyProperties(reply,vo);
                for(RainbowPlanUser user : users){
                    if (reply.getRainbowplanUserId().equals(user.getId())){
                        vo.setRainbowplanUserAvatar(user.getAvatar());
                        if (!Strings.isNullOrEmpty(user.getNickName())){
                            vo.setRainbowplanUserName(user.getNickName());
                        }else {
                            vo.setRainbowplanUserName(user.getName());
                        }

                    }
                }
                replyVoList.add(vo);
            }
        }
        RainbowPlanUser currentUser = userDao.findByOpenid(openid);
        RainbowPlanUser babyUser = null;
        if (currentUser.getType() == RainbowPlanUser.TYPE_LOVE){
            babyUser = userDao.find(wish.getRainbowPlanUserId());

        }
        WishDetailVo vo = new WishDetailVo(wish,replyVoList,babyUser);
        return vo;

    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/receiveWish",method = RequestMethod.POST)
    public Map<String,String> receiveWish(@RequestHeader String sKey,@RequestBody ReceiveWishVo vo){
        Map<String,String> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        Wish wish = wishDao.findById(vo.getWishId());
        if (wish == null || wish.getStatus() != Wish.STATUS_PUBLISH){
            result.put("status","error");
            result.put("errorMsg","心愿不存或已被其他人领取");
            return result;
        }
        wish.setStatus(Wish.STATUS_RECEIVE);
        wish.setVolunteerId(vo.getUserId());
        
        RainbowPlanUser volunteer = userDao.find(vo.getUserId());
        wish.setVolunteer(volunteer);
        
        wishDao.save(wish);
        result.put("status","OK");
        return result;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/sendWish",method = RequestMethod.POST)
    public Map<String,String> send(@RequestHeader String sKey, @RequestBody SendWishVo vo){
        Map<String,String> result = Maps.newConcurrentMap();
        if (Strings.isNullOrEmpty(sKey)){
            result.put("status","error");
            result.put("errorMsg","请求参数错误");
            return result;
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        Wish wish = wishDao.findById(vo.getWishId());
        if (wish == null){
            result.put("status","error");
            result.put("errorMsg","心愿不存在");
            return result;
        }
//        wish.setVolunteerId(vo.getUserId());
        wish.setHelpType(vo.getHelpType());
        if (wish.getHelpType() == Wish.HELP_TYPE_EXPRESS){
            wish.setExpressCompany(vo.getExpressCompany());
            wish.setExpressCode(vo.getExpressCode());
        }
        wish.setStatus(Wish.STATUS_SEND);
        wishDao.update(wish);
        if (vo.isShowMyAddr()){
            RainbowPlanUser user = userDao.find(vo.getUserId());
            user.setReceiveName(vo.getReceiveName());
            user.setReceiveAddress(vo.getReceiveAddress());
            user.setConnectTel(vo.getConnectTel());
            userDao.update(user);
        }
        result.put("status","OK");
        return result;
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/reply",method = RequestMethod.POST)
    public String reply(@RequestBody WishReply reply,@RequestHeader String sKey){
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        wishReplyDao.save(reply);
        return "OK";
    }
    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value  ="/completeWish",method = RequestMethod.GET)
    public String completeWish(String wishId,@RequestHeader String sKey){
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        Wish wish = wishDao.findById(wishId);
        if (wish != null){
            wish.setStatus(Wish.STATUS_COMPLETE);
        }
        wishDao.update(wish);
        return "OK";
    }


    @Auth(verifyURL = false,verifyLogin = false)
    @RequestMapping(value = "/qrcode",method = RequestMethod.GET)
    public ResponseEntity<byte[]> getQrcode(@RequestHeader String sKey) throws WxErrorException {
        if (Strings.isNullOrEmpty(sKey)){
            throw new IllegalArgumentException("请求参数错误");
        }
        String openid = tokenUtil.getUsernameFromToken(sKey);
        WxMaService wxMaService = WxMaConfiguration.getMaService(getAppid());

        WxMaQrcodeService qrcodeService = wxMaService.getQrcodeService();
        byte[] codeBytes = qrcodeService.createWxaCodeUnlimitBytes("inviter="+openid,"pages/register",360,true,null,false);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(codeBytes,headers,HttpStatus.OK);
    }

    @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 = "/importWish",method = RequestMethod.POST)
    public Map<String,Object> importWish(ImportWishVo importWishVo) throws Exception {
        Map<String,Object> result = Maps.newConcurrentMap();
        Activity activity = activityService.findByAavailableAndType("3");
        if (activity == null){
            result.put("status","error");
            result.put("errorMsg","当前不存在开放的彩虹计划活动");
            return result;
        }
        boolean flag = userDao.validateUserExistByPhone(importWishVo.getPhone());
        if (flag){
            result.put("status","error");
            result.put("errorMsg","该手机号已存");
            return result;
        }
        RainbowPlanUser user = new RainbowPlanUser();
        user.setPhone(importWishVo.getPhone());
        user.setName(importWishVo.getName());
        user.setNickName(importWishVo.getNickName());
        user.setReceiveAddress(importWishVo.getReceiveAddress());
        user.setConnectTel(importWishVo.getConnectTel());
        user.setReceiveName(importWishVo.getReceiveName());
        user.setBedNum(importWishVo.getBedNum());
        user.setBirthday(importWishVo.getBirthday());
        user.setGender(importWishVo.getGender());
        user.setCreateTime(new Date());
        user.setType(RainbowPlanUser.TYPE_BABY);
        user.setStatus(RainbowPlanUser.STATUS_AUDIT);
        user.setDisease(importWishVo.getDisease());

        userDao.save(user);

        if (!importWishVo.getFile().isEmpty()){

            String originalFileName = importWishVo.getFile().getOriginalFilename();
            String rootPath = rb.getString("file_path");
            File destFile = new File(rootPath + uploadWishImagePath,originalFileName);
            FileUtils.writeByteArrayToFile(destFile,importWishVo.getFile().getBytes());
            Wish wish = new Wish();
            wish.setContent(importWishVo.getWish());
            wish.setUploadImage(uploadWishImagePath + File.separator + originalFileName);
            wish.setStatus(Wish.STATUS_PUBLISH);
            wish.setRainbowPlanUserId(user.getId());
            wish.setActivityId(activity.getId());
            wishDao.save(wish);
        }else {
            throw new Exception("保存失败，请上传图片");
        }
        result.put("status","OK");
        return result;
    }

    @Auth(verifyLogin = false,verifyURL = false)
    @RequestMapping(value = "/testData",method = RequestMethod.GET)
    public String testData(){
        for (int i=0;i<50;i++){
            RainbowPlanUser user = new RainbowPlanUser();
            user.setPhone("136123456"+ RandomUtils.nextInt(10,99));
            user.setName("宝宝"+i);
            user.setNickName("宝宝昵称"+i);
            user.setGender(i % 2 == 0 ? "1" : "2");
            user.setBirthday("2010/4/5");
            user.setDisease("血液病");
            user.setBedNum("12楼302室5床");
            user.setReceiveName("收件人姓名");
            user.setReceiveAddress("收件人地址");
            user.setConnectTel(user.getPhone());
            userDao.save(user);

            Wish wish = new Wish();
            wish.setContent("测试心愿测试心愿测试心愿测试心愿测试心愿测试心愿测试心愿");
            wish.setUploadImage("/rainbowplan/wishUploadImage/wxd097672957e48ba8.o6zAJs19Nssw1OXAZZr6YDF-tx6U.0fpELldkHhwg5d73b7fa0dc34be23d4dca9ebe797b28.jpeg");
            wish.setStatus(Wish.STATUS_PUBLISH);
            wish.setRainbowPlanUserId(user.getId());
            wish.setChildren(user);
            wish.setActivityId("0d734916-e53f-4fb6-82cc-ff812d8a429d");
            wish.setActivity(activityService.findById("0d734916-e53f-4fb6-82cc-ff812d8a429d"));
            
            RainbowPlanUser volunteer = userDao.find("a23bcd0d-2ad6-4ab1-b16d-199056e9ed95");
            wish.setVolunteer(volunteer);
            
            wishDao.save(wish);
        }
        return "OK";
    }
}
