package com.qunzhixinxi.hnqz.admin.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qunzhixinxi.hnqz.admin.api.constant.CacheConstants;
import com.qunzhixinxi.hnqz.admin.entity.SysWxReplyMessage;
import com.qunzhixinxi.hnqz.admin.entity.SysWxReplyMessageMedia;
import com.qunzhixinxi.hnqz.admin.entity.SysWxReplyMessagePostBody;
import com.qunzhixinxi.hnqz.admin.enums.SysWxReplyMessageEnum;
import com.qunzhixinxi.hnqz.admin.service.SysWxAccountApiService;
import com.qunzhixinxi.hnqz.admin.service.SysWxReplyMessageService;
import com.qunzhixinxi.hnqz.admin.util.RegUtils;
import com.qunzhixinxi.hnqz.common.core.util.R;
import com.qunzhixinxi.hnqz.common.security.annotation.Inner;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信消息自动回复
 *
 * @author lixuesong
 * @date 2021年04月28日 15:21
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/sysWxReplyMessage")
@Api(value = "sysWxReplyMessage", tags = "微信消息自动回复接口")
public class SysWxReplyMessageController {

	/**
	 * 每条文本限制的最大字符数
	 */
	private static final Integer LIMIT_TEXT_LENGTH = 700;

	private final SysWxAccountApiService sysWxAccountApiService;

	private final SysWxReplyMessageService sysWxReplyMessageService;

	private final RedisTemplate redisTemplate;

	/**
	 * 微信回调-开发者验证接口（每次配置微信服务并提交时会被调用）
	 *
	 * @param signature 微信加密签名
	 * @param timestamp 时间戳
	 * @param nonce     随机数
	 * @param echostr   随机字符串
	 * @return
	 */
	@Inner(value = false)
	@GetMapping(value = "/wxCallBack")
	public String developerVerify(String signature, String timestamp, String nonce, String echostr) {
		log.info("微信回调-开发者验证接口请求参数：signature={}，timestamp={}，nonce={}，echostr={}",
				signature, timestamp, nonce, echostr);
		if (StringUtils.isBlank(signature) || StringUtils.isBlank(timestamp)
				|| StringUtils.isBlank(nonce) || StringUtils.isBlank(echostr)) {
			return "";
		}
		// 验证微信服务器
		boolean verifyWxServer = sysWxAccountApiService.verifyWxServer(signature, timestamp, nonce);
		if (verifyWxServer) {
			return echostr;
		}
		return "";
	}

	/**
	 * 微信回调-消息接口
	 *
	 * @param timestamp    时间戳
	 * @param nonce        随机数
	 * @param encryptType  加密类型，为 aes
	 * @param msgSignature 消息体签名，用于验证消息体的正确性
	 * @param postData
	 * @return
	 */
	@Inner(value = false)
	@PostMapping(value = "/wxCallBack")
	public String wxCallBack(String timestamp, String nonce, @RequestParam("encrypt_type") String encryptType,
							 @RequestParam("msg_signature") String msgSignature, @RequestBody String postData) {
		log.info("微信回调-消息接口请求参数：timestamp={}，nonce={}，encrypt_type={}，msg_signature={}，postData={}",
				timestamp, nonce, encryptType, msgSignature, postData);
		if (StringUtils.isBlank(postData) || StringUtils.isBlank(timestamp)
				|| StringUtils.isBlank(nonce) || StringUtils.isBlank(encryptType) || StringUtils.isBlank(msgSignature)) {
			return "";
		}
		// 加锁
		Boolean absent = redisTemplate.opsForValue().setIfAbsent(CacheConstants.SYS_WX_ACCOUNT_CALLBACK + postData, "send", 10L, TimeUnit.SECONDS);
		if (!absent) {
			return "";
		}
		try {
			// 解密消息体
			SysWxReplyMessagePostBody messagePostBody = sysWxAccountApiService.decryptWxMessage(msgSignature, timestamp, nonce, postData);
			// 暂设置为只接收文本消息
			if (messagePostBody.getMsgType() == null
					|| !SysWxReplyMessageEnum.WX_MEDIA_TYPE_TEXT.getDescription().equals(messagePostBody.getMsgType())) {
				return "";
			}

			// 判断是否二次查询（是：返回一个带有编号的选择列表，否：返回实际查询到的内容）
			String content = messagePostBody.getContent().trim();
			if (RegUtils.isStartWithNumberAndSpot(content)) {
				Integer id = Integer.valueOf(content.substring(0, content.indexOf(".")));
				// 先尝试根据id查询单条数据
				SysWxReplyMessage finalMessage = sysWxReplyMessageService.getMessageById(id);
				if (finalMessage == null || CollectionUtil.isEmpty(finalMessage.getMediaList())) {
					return "";
				}
				// 根据查询到的消息类型，封装为不同的返回类型
				String returnMsg = "";
				if (SysWxReplyMessageEnum.WX_MEDIA_TYPE_TEXT.getType().equals(finalMessage.getType())) {
					// 文本
					returnMsg = sysWxAccountApiService.encryptWxTextMessage(messagePostBody, finalMessage);
				} else if (SysWxReplyMessageEnum.WX_MEDIA_TYPE_IMAGE.getType().equals(finalMessage.getType())) {
					// 图片
					returnMsg = sysWxAccountApiService.encryptWxImageMessage(messagePostBody, finalMessage);
				} else if (SysWxReplyMessageEnum.WX_MEDIA_TYPE_VIDEO.getType().equals(finalMessage.getType())) {
					// 视频
					returnMsg = sysWxAccountApiService.encryptWxVideoMessage(messagePostBody, finalMessage);
				} else if (SysWxReplyMessageEnum.WX_MEDIA_TYPE_NEWS.getType().equals(finalMessage.getType())) {
					// 图文（文本+图片，此处调用微信主动发送消息接口，可以连续发送多条）
					sysWxAccountApiService.sendWxNewsMessage(messagePostBody.getFromUserName(), finalMessage);
					returnMsg = "success";
				}
				return returnMsg;
			} else {
				// 根据文本内容查询，返回一个带有编号的选择列表
				List<SysWxReplyMessage> messageList = sysWxReplyMessageService
						.list(Wrappers.<SysWxReplyMessage>lambdaQuery().like(SysWxReplyMessage::getKeyword, messagePostBody.getContent()).orderByAsc(SysWxReplyMessage::getId));
				if (CollectionUtil.isEmpty(messageList)) {
					return "";
				}
				String returnMsg = "";
				String selectContent = sysWxAccountApiService.joinWxSelectListMessage(messageList);
				// 如果内容超出最大限制，则拼接选择列表，以客服消息形式发送
				if (selectContent.length() > LIMIT_TEXT_LENGTH) {
					SysWxReplyMessage message = sysWxAccountApiService.splitContentByLine(selectContent, LIMIT_TEXT_LENGTH);
					sysWxAccountApiService.sendWxNewsMessage(messagePostBody.getFromUserName(), message);
					returnMsg = "success";
				} else {
					// 加密
					returnMsg = sysWxAccountApiService.encryptWxSelectListMessage(messagePostBody, selectContent);
				}
				return returnMsg;
			}
		} catch (Exception e) {
			log.error("微信回调-消息接口异常", e);
		}

		return "success";
	}

	/**
	 * 上传微信素材
	 *
	 * @param file
	 * @return
	 */
	@PostMapping(value = "/uploadMedia")
	@ApiOperation(value = "上传微信素材", notes = "上传微信素材")
	public R uploadMedia(@RequestParam("file") MultipartFile file, Integer mediaType, String title, String introduction) {
		log.info("上传微信素材接口请求参数：fileSize={}, mediaType={}, title={}, introduction={}", file.getSize(), mediaType, title, introduction);
		if (file.isEmpty()) {
			return R.failed("文件不能为空");
		}
		try {
			Map<String, String> result = sysWxAccountApiService.uploadMedia(file, mediaType, title, introduction);
			if (result != null) {
				return R.ok(result);
			}
		} catch (Exception e) {
			log.error("上传微信素材失败", e);
		}
		return R.failed("上传失败");
	}

	/**
	 * 查询消息列表分页
	 *
	 * @param page
	 * @param sysWxReplyMessage
	 * @return
	 */
	@GetMapping(value = "/listMessagePage")
	@ApiOperation(value = "查询消息列表分页", notes = "查询消息列表分页")
	public R listMessagePage(Page page, SysWxReplyMessage sysWxReplyMessage) {
		log.info("查询消息列表分页请求参数：page={}，sysWxReplyMessage={}", JSON.toJSONString(page), JSON.toJSONString(sysWxReplyMessage));
		IPage<List<SysWxReplyMessage>> messageList = sysWxReplyMessageService.listMessagePage(page, sysWxReplyMessage);
		return R.ok(messageList);
	}

	/**
	 * 新增消息
	 *
	 * @param sysWxReplyMessage
	 * @return
	 */
	@PostMapping(value = "/addMessage")
	@PreAuthorize("@pms.hasPermission('mp_wxsmartqa_add')")
	@ApiOperation(value = "新增消息", notes = "新增消息")
	public R addMessage(@RequestBody SysWxReplyMessage sysWxReplyMessage) {
		log.info("新增消息请求参数：{}", JSON.toJSONString(sysWxReplyMessage));
		if (StringUtils.isBlank(sysWxReplyMessage.getKeyword()) || sysWxReplyMessage.getType() == null
				|| sysWxReplyMessage.getMediaList() == null || sysWxReplyMessage.getMediaList().isEmpty()) {
			return R.failed("必传参数不能为空");
		}
		// 校验文本内容是否超出限制
		if (SysWxReplyMessageEnum.MESSAGE_TYPE_TEXT.getType().equals(sysWxReplyMessage.getType())
				|| SysWxReplyMessageEnum.MESSAGE_TYPE_MULTI.getType().equals(sysWxReplyMessage.getType())) {
			for (SysWxReplyMessageMedia media : sysWxReplyMessage.getMediaList()) {
				if (SysWxReplyMessageEnum.MESSAGE_MEDIA_TYPE_TEXT.getType().equals(media.getMediaType())) {
					if (StringUtils.isBlank(media.getContent())) {
						return R.failed("文本内容不能为空");
					}
					if (media.getContent().length() > LIMIT_TEXT_LENGTH) {
						return R.failed("超出了最大字符数限制：" + LIMIT_TEXT_LENGTH);
					}
				}
			}
		}
		boolean result = sysWxReplyMessageService.saveMessage(sysWxReplyMessage);
		if (result) {
			return R.ok();
		}
		return R.failed("新增消息失败");
	}

	/**
	 * 修改消息
	 *
	 * @param sysWxReplyMessage
	 * @return
	 */
	@PostMapping(value = "/updateMessage")
	@PreAuthorize("@pms.hasPermission('mp_wxsmartqa_edit')")
	@ApiOperation(value = "修改消息", notes = "修改消息")
	public R updateMessage(@RequestBody SysWxReplyMessage sysWxReplyMessage) {
		log.info("修改消息请求参数：{}", JSON.toJSONString(sysWxReplyMessage));
		if (sysWxReplyMessage == null || sysWxReplyMessage.getId() == null) {
			return R.failed("id不能为空");
		}
		// 校验文本内容是否超出限制
		if (SysWxReplyMessageEnum.MESSAGE_TYPE_TEXT.getType().equals(sysWxReplyMessage.getType())
				|| SysWxReplyMessageEnum.MESSAGE_TYPE_MULTI.getType().equals(sysWxReplyMessage.getType())) {
			for (SysWxReplyMessageMedia media : sysWxReplyMessage.getMediaList()) {
				if (SysWxReplyMessageEnum.MESSAGE_MEDIA_TYPE_TEXT.getType().equals(media.getMediaType())) {
					if (StringUtils.isBlank(media.getContent())) {
						return R.failed("文本内容不能为空");
					}
					if (media.getContent().length() > LIMIT_TEXT_LENGTH) {
						return R.failed("超出了最大字符数限制：" + LIMIT_TEXT_LENGTH);
					}
				}
			}
		}
		boolean result = sysWxReplyMessageService.updateMessageById(sysWxReplyMessage);
		if (result) {
			return R.ok();
		}
		return R.failed("修改消息失败");
	}

	/**
	 * 删除消息
	 *
	 * @param id
	 * @return
	 */
	@PostMapping(value = "/deleteMessageById/{id}")
	@PreAuthorize("@pms.hasPermission('mp_wxsmartqa_del')")
	@ApiOperation(value = "删除消息", notes = "删除消息")
	public R deleteMessageById(@PathVariable Integer id) {
		log.info("删除消息请求参数：id={}", id);
		if (id == null) {
			return R.failed("id不能为空");
		}
		boolean result = sysWxReplyMessageService.deleteMessageById(id);
		if (result) {
			return R.ok();
		}
		return R.failed("删除消息失败");
	}

}
