package com.zhongzheng.modules.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;

import cn.hutool.extra.template.TemplateException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.zhongzheng.common.utils.DateUtils;
import com.zhongzheng.common.utils.SecurityUtils;
import com.zhongzheng.modules.alioss.bo.OssRequest;
import com.zhongzheng.modules.alioss.service.impl.OssServiceImpl;
import com.zhongzheng.modules.alisms.service.IAliSmsService;
import com.zhongzheng.modules.base.bo.UserProfileFit;
import com.zhongzheng.modules.goods.service.IGoodsService;
import com.zhongzheng.modules.goods.vo.GoodsVo;
import com.zhongzheng.modules.inform.bo.InformUserAddBo;
import com.zhongzheng.modules.inform.service.IInformRemindService;
import com.zhongzheng.modules.inform.service.IInformUserService;
import com.zhongzheng.modules.inform.vo.InformRemindVo;
import com.zhongzheng.modules.order.vo.OrderGoodsVo;
import com.zhongzheng.modules.user.service.IUserService;
import com.zhongzheng.modules.user.vo.UserVo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.zhongzheng.modules.base.bo.UserProfileAddBo;
import com.zhongzheng.modules.base.bo.UserProfileQueryBo;
import com.zhongzheng.modules.base.bo.UserProfileEditBo;
import com.zhongzheng.modules.base.domain.UserProfile;
import com.zhongzheng.modules.base.mapper.UserProfileMapper;
import com.zhongzheng.modules.base.vo.UserProfileVo;
import com.zhongzheng.modules.base.service.IUserProfileService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import java.awt.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 填写资料审核Service业务层处理
 *
 * @author ruoyi
 * @date 2021-12-20
 */
@Service
public class UserProfileServiceImpl extends ServiceImpl<UserProfileMapper, UserProfile> implements IUserProfileService {

    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;

    @Value("${zhongzheng.profile}")
    private String ZHONGZHENG_PROFILE;

    @Autowired
    private OssServiceImpl ossService;

    @Autowired
    private IGoodsService iGoodsService;

    @Autowired
    private com.zhongzheng.modules.alisms.service.IAliSmsService IAliSmsService;

    @Autowired
    private IUserService iUserService;

    @Autowired
    private IInformUserService iInformUserService;

    @Autowired
    private IInformRemindService informRemindService;

    @Value("${aliyun.sms.materialReviewCode}")
    private String materialReviewCode;

    @Value("${aliyun.sms.NotificationOfFailureCode}")
    private String NotificationOfFailureCode;

    @Value("${aliyun.sms.commitmentCode}")
    private String commitmentCode;

    @Value("${aliyun.sms.commitmentFailsCode}")
    private String commitmentFailsCode;

    @Override
    public UserProfileVo queryById(Long id){
        UserProfileQueryBo userProfileQueryBo = new UserProfileQueryBo();
        userProfileQueryBo.setId(id);
        UserProfileVo userProfileVo = baseMapper.selectUserProfile(userProfileQueryBo).get(0);
        return userProfileVo;
    }

    @Override
    public List<UserProfileVo> queryList(UserProfileQueryBo bo) {

        return baseMapper.selectUserProfile(bo);
    }

    /**
    * 实体类转化成视图对象
    *
    * @param collection 实体类集合
    * @return
    */
    private List<UserProfileVo> entity2Vo(Collection<UserProfile> collection) {
        List<UserProfileVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, UserProfileVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<UserProfile> page = (Page<UserProfile>)collection;
            Page<UserProfileVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page,pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Override
    public Boolean insertByAddBo(UserProfileAddBo bo) {
        UserProfile add = BeanUtil.toBean(bo, UserProfile.class);
        validEntityBeforeSave(add);
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        add.setStatus(2);
        add.setOneTime(DateUtils.getNowTime());
        add.setLastTime(DateUtils.getNowTime());
        add.setCurrentStatus(1L);
        add.setChangeStatus(1);
        return this.save(add);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByEditBo(UserProfileEditBo bo) {
        UserProfileVo userProfileVo = this.queryById(bo.getId());

        UserProfile addProfile = BeanUtil.toBean(bo,UserProfile.class);
        addProfile.setCreateTime(DateUtils.getNowTime());
        addProfile.setUpdateTime(DateUtils.getNowTime());
        addProfile.setStatus(3);
        addProfile.setOneTime(userProfileVo.getOneTime());
        addProfile.setLastTime(DateUtils.getNowTime());
        addProfile.setCurrentStatus(1L);
        addProfile.setChangeStatus(2);

        UserProfile update = new UserProfile();
        update.setId(bo.getId());
        update.setCurrentStatus(2L);
        update.setUpdateTime(DateUtils.getNowTime());
        this.updateById(update);
        return this.save(addProfile);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(UserProfile entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return this.removeByIds(ids);
    }

    @Override
    public String addWord(UserProfileAddBo bo) throws IOException {
        UserProfileQueryBo userProfileQueryBo = new UserProfileQueryBo();
        userProfileQueryBo.setUserId(bo.getUserId());
        userProfileQueryBo.setGoodsId(bo.getGoodsId());
        userProfileQueryBo.setTypeStatus(1L);
        UserProfileVo info = baseMapper.getInfo(userProfileQueryBo);
        //第一种方式
        Map<String, String> maps = JSONObject.parseObject(info.getKeyValue(),Map.class);
        //默认配置就够用了
 /*       TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH));
        Template template = engine.getTemplate("word.ftl");*/
        //给STRING_TEMPLATE绑定数据
        Map<String, Object> bindingMap = new HashMap<>();
        bindingMap.put("name", JSONObject.parseObject(String.valueOf(maps.get("name")), UserProfileFit.class).getValue());
        bindingMap.put("s", JSONObject.parseObject(String.valueOf(maps.get("sex")), UserProfileFit.class).getValue());
        bindingMap.put("post", JSONObject.parseObject(String.valueOf(maps.get("apply_post")), UserProfileFit.class).getValue());
        bindingMap.put("idcard", JSONObject.parseObject(String.valueOf(maps.get("idcard")), UserProfileFit.class).getValue());
        bindingMap.put("phone", JSONObject.parseObject(String.valueOf(maps.get("telphone")), UserProfileFit.class).getValue());
        bindingMap.put("school", JSONObject.parseObject(String.valueOf(maps.get("school")), UserProfileFit.class).getValue());
        bindingMap.put("edu", JSONObject.parseObject(String.valueOf(maps.get("education")), UserProfileFit.class).getValue());
        bindingMap.put("major", JSONObject.parseObject(String.valueOf(maps.get("major")), UserProfileFit.class).getValue());
        bindingMap.put("cname", JSONObject.parseObject(String.valueOf(maps.get("unit_contact")), UserProfileFit.class).getValue());
        bindingMap.put("cphone", JSONObject.parseObject(String.valueOf(maps.get("unit_tel")), UserProfileFit.class).getValue());
        bindingMap.put("image",  Image2Base64(ALIYUN_OSS_ENDPOINT+"/"+JSONObject.parseObject(String.valueOf(maps.get("commitment_electr_signature")), UserProfileFit.class).getValue()));
        bindingMap.put("y", 1);
        bindingMap.put("m", 1);
        bindingMap.put("d", 1);
        bindingMap.put("time", JSONObject.parseObject(String.valueOf(maps.get("graduation_time")), UserProfileFit.class).getValue());
        bindingMap.put("year", JSONObject.parseObject(String.valueOf(maps.get("working_years")), UserProfileFit.class).getValue());
        File touch = FileUtil.touch(ZHONGZHENG_PROFILE+"word.doc");
        //最终渲染出来的样子
        /*template.render(bindingMap,touch);*/


        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        Template template = configuration.getTemplate("word.ftl");
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(touch),"UTF-8"));
        try {
            template.process(bindingMap,out);
            out.flush();
            out.close();

        } catch (TemplateException | freemarker.template.TemplateException e) {
            e.printStackTrace();
        }


        OssRequest ossRequest = new OssRequest();
        FileInputStream fileInputStream = new FileInputStream(touch);
        MultipartFile multipartFile = new MockMultipartFile(touch.getName(), touch.getName(),
                ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
        ossRequest.setFile(multipartFile);
        ossRequest.setImageStatus(6);
        String upload = ossService.upload(ossRequest);
        return upload;
    }

    @Override
    public UserProfileVo getInfo(UserProfileQueryBo bo) {
        return baseMapper.getInfo(bo);
    }

    @Override
    public boolean updateAuditByEditBo(UserProfileEditBo bo) {
        UserProfile update = BeanUtil.toBean(bo,UserProfile.class);
        update.setId(bo.getId());
        update.setCreateByName("SAAS-"+ SecurityUtils.getUsername());
        update.setUpdateTime(DateUtils.getNowTime());
        update.setAuditTime(DateUtils.getNowTime());
        update.setChangeStatus(1);

        UserProfileVo userProfileVo = this.queryById(bo.getId());
        if (userProfileVo.getTypeStatus().equals(1)){
            sendAuidit(update);
        }else if (userProfileVo.getTypeStatus().equals(2)){
            sendAuiditSMS(update);
        }
        return this.updateById(update);
    }

    private void sendAuiditSMS(UserProfile bo) {
        UserProfileVo userProfileVo = this.queryById(bo.getId());
        if (bo.getStatus().equals(1)) {
            InformRemindVo informRemindVo = informRemindService.queryById(23L);
            if (informRemindVo.getWayStatus().equals(1)) {
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(23L);
                informUserAddBo.setSystemStatus(1);
                informUserAddBo.setRemind("资料审核通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您上传"+goodsVo1.getGoodsName()+"课程的承诺书审核成功");
                iInformUserService.insertByAddBo(informUserAddBo);
            }
            if (informRemindVo.getNoteStatus().equals(1)){
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(23L);
                informUserAddBo.setSystemStatus(3);
                informUserAddBo.setRemind("资料审核通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您上传"+goodsVo1.getGoodsName()+"课程的承诺书审核成功");
                iInformUserService.insertByAddBo(informUserAddBo);
                UserVo userVo = iUserService.queryById(userProfileVo.getUserId());
                Map<String, Object> param = new HashMap<>();
                param.put("goods", goodsVo1.getGoodsName());
                IAliSmsService.sendInformSms(userVo.getTelphone(), JSON.toJSONString(param), commitmentCode);
            }
        }else {
            InformRemindVo informRemindTwoVo = informRemindService.queryById(24L);
            if (informRemindTwoVo.getWayStatus().equals(1)) {
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(24L);
                informUserAddBo.setSystemStatus(1);
                informUserAddBo.setRemind("资料审核不通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您上传"+goodsVo1.getGoodsName()+"课程的承诺书审核不通过，请重新完善吧");
                iInformUserService.insertByAddBo(informUserAddBo);
            }
            if (informRemindTwoVo.getNoteStatus().equals(1)){
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(24L);
                informUserAddBo.setSystemStatus(3);
                informUserAddBo.setRemind("资料审核不通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您上传"+goodsVo1.getGoodsName()+"课程的承诺书审核不通过，请重新完善吧");
                iInformUserService.insertByAddBo(informUserAddBo);
                UserVo userVo = iUserService.queryById(userProfileVo.getUserId());
                Map<String, Object> param = new HashMap<>();
                param.put("goods", goodsVo1.getGoodsName());
                IAliSmsService.sendInformSms(userVo.getTelphone(), JSON.toJSONString(param), commitmentFailsCode);
            }
        }
    }

    private void sendAuidit(UserProfile bo) {
        UserProfileVo userProfileVo = this.queryById(bo.getId());
        if (bo.getStatus().equals(1)) {
            InformRemindVo informRemindVo = informRemindService.queryById(3L);
            if (informRemindVo.getWayStatus().equals(1)) {
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(3L);
                informUserAddBo.setSystemStatus(1);
                informUserAddBo.setRemind("报名资料审核通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您填写的"+goodsVo1.getGoodsName()+"课程报名信息审核成功，请尽快去学习吧");
                iInformUserService.insertByAddBo(informUserAddBo);
            }
            if (informRemindVo.getNoteStatus().equals(1)){
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(3L);
                informUserAddBo.setSystemStatus(3);
                informUserAddBo.setRemind("报名资料审核通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您购买的" + goodsVo1.getGoodsName() + "已经开通，请尽快去学习吧。");
                iInformUserService.insertByAddBo(informUserAddBo);
                UserVo userVo = iUserService.queryById(userProfileVo.getUserId());
                Map<String, Object> param = new HashMap<>();
                param.put("goods", goodsVo1.getGoodsName());
                IAliSmsService.sendInformSms(userVo.getTelphone(), JSON.toJSONString(param), materialReviewCode);
            }
        }else {
            InformRemindVo informRemindTwoVo = informRemindService.queryById(4L);
            if (informRemindTwoVo.getWayStatus().equals(1)) {
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(4L);
                informUserAddBo.setSystemStatus(1);
                informUserAddBo.setRemind("报名资料审核不通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您填写的"+goodsVo1.getGoodsName()+"课程报名信息审核不通过，请重新完善吧");
                iInformUserService.insertByAddBo(informUserAddBo);
            }
            if (informRemindTwoVo.getNoteStatus().equals(1)){
                InformUserAddBo informUserAddBo = new InformUserAddBo();
                informUserAddBo.setUserId(userProfileVo.getUserId());
                informUserAddBo.setSendTime(DateUtils.getNowTime());
                informUserAddBo.setSendStatus(1);
                informUserAddBo.setCreateTime(DateUtils.getNowTime());
                informUserAddBo.setUpdateTime(DateUtils.getNowTime());
                informUserAddBo.setRemindId(3L);
                informUserAddBo.setSystemStatus(3);
                informUserAddBo.setRemind("报名资料审核不通过通知");
                informUserAddBo.setGoodsId(userProfileVo.getGoodsId());
                GoodsVo goodsVo1 = iGoodsService.queryById(userProfileVo.getGoodsId());
                informUserAddBo.setText("尊敬的用户：您填写的"+goodsVo1.getGoodsName()+"课程报名信息审核不通过，请重新完善吧");
                iInformUserService.insertByAddBo(informUserAddBo);
                UserVo userVo = iUserService.queryById(userProfileVo.getUserId());
                Map<String, Object> param = new HashMap<>();
                param.put("goods", goodsVo1.getGoodsName());
                IAliSmsService.sendInformSms(userVo.getTelphone(), JSON.toJSONString(param), NotificationOfFailureCode);
            }
        }
    }

    @Override
    public List<UserProfileVo> listRecord(UserProfileQueryBo bo) {
        return baseMapper.listRecord(bo);
    }

    /**
     * 远程读取image转换为Base64字符串
     *
     * @param imgUrl
     * @return
     */
    public static String Image2Base64(String imgUrl) {
        URL url = null;
        InputStream is = null;
        ByteArrayOutputStream outStream = null;
        HttpURLConnection httpUrl = null;
        try {
            url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();
            is = httpUrl.getInputStream();

            outStream = new ByteArrayOutputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用一个输入流从buffer里把数据读取出来
            while ((len = is.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            // 对字节数组Base64编码
            return new BASE64Encoder().encode(outStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        }  //下载
        finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outStream != null) {
                try {
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpUrl != null) {
                httpUrl.disconnect();
            }
        }
        return imgUrl;
    }


}
