package com.cyksj.service.mini.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Times;
import com.cyksj.config.TgMiniConfig;
import com.cyksj.config.YhCertMiniConfig;
import com.cyksj.config.YhMiniConfig;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.UserMapper;
import com.cyksj.mapper.mini.ArticleMapper;
import com.cyksj.mapper.mini.ArticleUserMarkMapper;
import com.cyksj.mapper.mini.MiniPopularizeUserMapper;
import com.cyksj.model.dto.MiniProgramSession;
import com.cyksj.model.entity.Article;
import com.cyksj.model.entity.ArticleUserMark;
import com.cyksj.model.entity.MiniPopularizeUser;
import com.cyksj.model.entity.User;
import com.cyksj.model.request.MiniArticleReq;
import com.cyksj.model.request.MiniSchemaReq;
import com.cyksj.model.request.TargetAppletSchemeReq;
import com.cyksj.model.views.ArticleDetailView;
import com.cyksj.model.wechat.MiniURLLink;
import com.cyksj.redis.RedisService;
import com.cyksj.service.mini.MiniService;
import com.cyksj.service.wechat.WeChatService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/*
 *项目名: netflix
 *文件名: MiniServiceImpl
 *创建者: JavaZou
 *创建时间:2023/5/11 18:07
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MiniServiceImpl implements MiniService {
	private final WeChatService weChatService;

	private final YhMiniConfig yhMiniConfig;

	private final UserMapper userMapper;

	private final ArticleUserMarkMapper articleUserMarkMapper;

	private final ArticleMapper articleMapper;

	private final YhCertMiniConfig certMiniConfig;

	private final RedisService redisService;

	private final MiniPopularizeUserMapper miniPopularizeUserMapper;

	private final TgMiniConfig tgMiniConfig;

	@Override
	public String getMiniURLLink(String path, String query) throws Exception {
		MiniURLLink miniURLLink = new MiniURLLink();
		miniURLLink.setPath(path);
		miniURLLink.setQuery(query);
		String accessToken = weChatService.getAccessToken(yhMiniConfig.getAppId());
		String linkUrl = weChatService.getMiniURLLink(accessToken, miniURLLink);
		return linkUrl;
	}

	@Override
	public User wxlogin(String code, String appId) throws Exception {
		MiniProgramSession code2Session = weChatService.code2Session(appId, code);
		String unionId = code2Session.getUnionid();
		String openId = code2Session.getOpenid();
		User user = Optional.ofNullable(
				userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUnionid, unionId)
						.last("limit 1")))
				.orElseGet(() -> userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, openId)
						.last("limit 1")));

		user = Optional.ofNullable(user).orElseGet(() -> new User().setOpenId(openId).setUnionid(unionId));
		user.setUnionid(unionId);
		user.setOpenId(openId);
		user.setRegisterEnv(User.RegisterEnv.h5.name());
		if (user.getId() == null) {
			user.setNickname(String.format("银河小程序用户%s", RandomUtil.randomString(5)));
			userMapper.insert(user);
		} else {
			userMapper.updateById(user);
		}
		//推广小程序用户 新注册发送GPT画图使用额度
		sendGptMirrorImageNumIfPopularizeMini(user.getId(), appId);
		return user;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public Result<String> markArticle(MiniArticleReq miniArticleReq) {
		Long userId = miniArticleReq.getUserId();
		Long articleId = miniArticleReq.getId();
		Integer type = miniArticleReq.getType();
		ArticleUserMark mark = articleUserMarkMapper.selectOne(Wrappers.lambdaQuery(ArticleUserMark.class)
				.eq(ArticleUserMark::getUserId, userId)
				.eq(ArticleUserMark::getArticleId, articleId).last("limit 1"));
		if (mark == null) {
			mark = new ArticleUserMark();
			mark.setUserId(userId);
			mark.setArticleId(articleId);
			if (type == 1) mark.setIsDz(true);
			if (type == 2) mark.setIsCol(true);
			try {
				articleUserMarkMapper.insert(mark);
				updateArticleMarkNum(type, articleId, 1);
			} catch (DuplicateKeyException e) {

			}
			if (type == 1) return GatewayResponse.SUCCESS.newBuilder().toResult("点赞成功");
			if (type == 2) return GatewayResponse.SUCCESS.newBuilder().toResult("收藏成功");
		}
		if (type == 1) {
			Boolean isDz = mark.getIsDz();

			mark.setIsDz(!isDz);
			articleUserMarkMapper.updateById(mark);
			if (!isDz) {
				updateArticleMarkNum(type, articleId, 1);
				return GatewayResponse.SUCCESS.newBuilder().toResult("点赞成功");
			}
			updateArticleMarkNum(type, articleId, -1);
			return GatewayResponse.SUCCESS.newBuilder().toResult("取消成功");
		}
		if (type == 2) {
			Boolean isCol = mark.getIsCol();

			mark.setIsCol(!isCol);
			articleUserMarkMapper.updateById(mark);
			if (!isCol) {
				updateArticleMarkNum(type, articleId, 1);
				return GatewayResponse.SUCCESS.newBuilder().toResult("收藏成功");
			}
			updateArticleMarkNum(type, articleId, -1);
			return GatewayResponse.SUCCESS.newBuilder().toResult("取消成功");
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	@Override
	public ArticleDetailView getArticleDetailView(Long articleId, Long userId) {
		ArticleDetailView detailView = articleMapper.getArticleDetailById(articleId);
		if (userId != null) {
			Optional.ofNullable(articleUserMarkMapper.selectOne(Wrappers.lambdaQuery(ArticleUserMark.class)
					.eq(ArticleUserMark::getUserId, userId)
					.eq(ArticleUserMark::getArticleId, articleId)
					.last("limit 1"))).ifPresentOrElse(mark -> {
				detailView.setIsDz(mark.getIsDz());
				detailView.setIsCol(mark.getIsCol());
			}, () -> {
				detailView.setIsDz(false);
				detailView.setIsCol(false);
			});
		}
		return detailView;
	}

	@Override
	public void getStudentIdentity(User user, String code) throws Exception {
		weChatService.getMiniStudentIdentity(user.getOpenId(), code);
	}

	@Override
	public String generateSchema(MiniSchemaReq req) throws Exception {
		//跳转路径
		req.setPath("pages/index/index");
		String query = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(req.getDsCode())) {
			query = "dsCode=" + req.getDsCode();
		}
		//调用微信小程序接口
		String accessToken = weChatService.getAccessToken(certMiniConfig.getAppId());
		TargetAppletSchemeReq targetAppletSchemeReq = new TargetAppletSchemeReq();
		targetAppletSchemeReq.setExpireType(0l);
		targetAppletSchemeReq.setExpireTime((System.currentTimeMillis() / 1000) + Times.second_per_day);
		targetAppletSchemeReq.setIsExpired(false);
		TargetAppletSchemeReq.JumpWxa jumpWxa = new TargetAppletSchemeReq.JumpWxa(req.getPath(), query);
		targetAppletSchemeReq.setJumpWxa(jumpWxa);
		String miniSchema = weChatService.generateSchema(accessToken, targetAppletSchemeReq);
		return miniSchema;
	}

	@Override
	public byte[] generateCode(MiniSchemaReq req) throws Exception {
		req.setPath("pages/index/index");
		//调用微信小程序接口
		if (StrUtil.isNotBlank(req.getDsCode())) {
			req.setPath(req.getPath() + "?dsCode=" + req.getDsCode());
		}
		String accessToken = weChatService.getAccessToken(certMiniConfig.getAppId());
		return weChatService.generateCode(accessToken, req.getPath());
	}

	@Override
	public String generateGptMiniSchema(MiniSchemaReq req) throws Exception {
		if (StrUtil.isEmpty(req.getPath())) {
			throw BusinessRuntimeException.getInstance("请传入小程序跳转路径");
		}
		String query = StrUtil.EMPTY;
		if (StrUtil.isNotBlank(req.getDsCode())) {
			query = "dsCode=" + req.getDsCode();
		}
		//调用微信小程序接口
		String accessToken = weChatService.getAccessToken(tgMiniConfig.getAppId());
		TargetAppletSchemeReq targetAppletSchemeReq = new TargetAppletSchemeReq();
		targetAppletSchemeReq.setExpireType(0l);
		targetAppletSchemeReq.setExpireTime((System.currentTimeMillis() / 1000) + Times.second_per_day);
		targetAppletSchemeReq.setIsExpired(false);
		TargetAppletSchemeReq.JumpWxa jumpWxa = new TargetAppletSchemeReq.JumpWxa(req.getPath(), query);
		targetAppletSchemeReq.setJumpWxa(jumpWxa);
		String miniSchema = weChatService.generateSchema(accessToken, targetAppletSchemeReq);
		return miniSchema;
	}

	public void updateArticleMarkNum(Integer type, Long articleId, Integer offset) {
		Integer success = 0;
		while (success != 1) {
			//文章累计点赞数、收藏数
			Article article = articleMapper.selectById(articleId);
			if (article == null) {
				break;
			}
			Integer dzNum = article.getDzNum();
			Integer colNum = article.getColNum();
			if (type == 1) {
				success = articleMapper.updateDzNum(articleId, dzNum, offset);
			} else {
				success = articleMapper.updateColNum(articleId, colNum, offset);
			}
		}
	}

	private void sendGptMirrorImageNumIfPopularizeMini(Long userId, String appId) {
		if (StrUtil.equals(tgMiniConfig.getAppId(), appId)) {
			Integer selectCount = miniPopularizeUserMapper.selectCount(Wrappers.lambdaQuery(MiniPopularizeUser.class).eq(MiniPopularizeUser::getUserId, userId));
			if (selectCount > 0) {
				return;
			}
			MiniPopularizeUser user = new MiniPopularizeUser();
			user.setUserId(userId);
			user.setNum(5);
			try {
				miniPopularizeUserMapper.insert(user);
			} catch (DuplicateKeyException e) {

			}
		}
	}
}
