package com.cyksj.service.corp.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Jsons;
import com.cyksj.mapper.OrderDonMapper;
import com.cyksj.mapper.UserMapper;
import com.cyksj.mapper.corp.*;
import com.cyksj.model.entity.*;
import com.cyksj.model.excel.CorpUserTagExcelData;
import com.cyksj.model.request.CorpDelTagReq;
import com.cyksj.model.response.corp.CorpUserExternalTagGroupInfo;
import com.cyksj.model.views.*;
import com.cyksj.service.corp.CorpTagService;
import com.cyksj.service.corp.WxCorpOps;
import com.google.common.collect.Maps;
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.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/*
 *项目名: netflix
 *文件名: CorpTagServiceImpl
 *创建者: JavaZou
 *创建时间:2023/6/20 16:06
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class CorpTagServiceImpl implements CorpTagService {
	private final WxCorpOps wxCorpOps;

	private final CorpTagMapper corpTagMapper;

	private final CorpTagGroupMapper corpTagGroupMapper;

	private final CorpTagRuleRelationMapper corpTagRuleRelationMapper;

	private final CorpTagRuleMapper corpTagRuleMapper;

	private final UserMapper userMapper;

	private final CorpUserTagMapper corpUserTagMapper;

	private final OrderDonMapper orderDonMapper;

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public CorpTagGroupView addCorpTagGroup(CorpTagGroupView tagGroup) throws Exception {
		CorpUserExternalTagGroupInfo tagGroupInfoReq = new CorpUserExternalTagGroupInfo();

		CorpUserExternalTagGroupInfo.TagGroup group = new CorpUserExternalTagGroupInfo.TagGroup();
		group.setGroupId(tagGroup.getGroupId());
		group.setGroupName(tagGroup.getGroupName());
		Map<String, CorpTag> corpTagMap = new ConcurrentHashMap<>();
		if (CollUtil.isEmpty(tagGroup.getTagList())) {
			throw BusinessRuntimeException.getInstance("标签不能为空");
		}
		List<CorpUserExternalTagGroupInfo.Tag> tagList = tagGroup.getTagList().stream().map((corpTag) -> {
			if (StrUtil.isEmpty(corpTag.getGroupName())) {
				corpTag.setGroupName(tagGroup.getGroupName());
			}
			CorpUserExternalTagGroupInfo.Tag tag = new CorpUserExternalTagGroupInfo.Tag();
			tag.setName(corpTag.getName());
			CorpTag exists = corpTagMapper.selectOne(Wrappers.lambdaQuery(CorpTag.class)
					.eq(CorpTag::getGroupName, corpTag.getGroupName())
					.eq(CorpTag::getName, corpTag.getName()).last("limit 1"));
			if (exists != null) throw BusinessRuntimeException.getInstance("标签组下重复标签");
			corpTagMap.putIfAbsent(corpTag.getName(), corpTag);
			return tag;
		}).collect(Collectors.toList());
		group.setTag(tagList);
		tagGroupInfoReq.setTagGroup(group);
		CorpUserExternalTagGroupInfo corpUserExternalTagGroupInfo = wxCorpOps.addCorpTag(tagGroupInfoReq, null);

		CorpUserExternalTagGroupInfo.TagGroup corp_tagGroup = corpUserExternalTagGroupInfo.getTagGroup();

		corpUserExternalTagGroupInfo.getTagGroup().getTag().forEach(tag -> {
			try {
				CorpTag corpTag = corpTagMap.get(tag.getName());
				if (corpTag == null) return;
				corpTag.setGroupId(corp_tagGroup.getGroupId());
				corpTag.setGroupName(corp_tagGroup.getGroupName());
				corpTag.setOrdered(tag.getOrder());
				corpTag.setTagId(tag.getId());
				corpTag.setName(tag.getName());
				if (CollUtil.isNotEmpty(corpTag.getRuleNameList())) {
					try {
						corpTag.setRuleNameListStr(Jsons.toJson(corpTag.getRuleNameList()));
					} catch (Exception e) {
					}
				}
				//对应标签入库
				corpTagMapper.insert(corpTag);
				if (corpTag.getType() == 2) {
					corpTag.getRuleRelationList().forEach(data -> {
						data.setTagId(corpTag.getId());
						corpTagRuleRelationMapper.insert(data);
					});
				}
				CorpTagGroup corpTagGroup = Optional.ofNullable(corpTagGroupMapper.selectOne(Wrappers.lambdaQuery(CorpTagGroup.class)
								.eq(CorpTagGroup::getGroupId, corp_tagGroup.getGroupId()).last("limit 1")))
						.orElseGet(() -> {
							CorpTagGroup corpTagGroup2 = new CorpTagGroup();
							corpTagGroup2.setGroupId(corp_tagGroup.getGroupId());
							corpTagGroup2.setGroupName(corp_tagGroup.getGroupName());
							corpTagGroup2.setOrdered(corp_tagGroup.getOrder());
							return corpTagGroup2;
						});
				corpTagGroup.setRemark(tagGroup.getRemark());
				if (corpTagGroup.getId() == null) corpTagGroupMapper.insert(corpTagGroup);
				corpTagGroupMapper.updateById(corpTagGroup);
			} catch (DuplicateKeyException e) {

			}
		});
		CorpTagGroupView corpTagGroupView = corpTagGroupMapper.getOneCorpGroupTag(tagGroup.getGroupId(), tagGroup.getGroupName());
		return corpTagGroupView;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void editCorpTag(CorpTagGroupView tagGroup) throws Exception {
		String groupId = tagGroup.getGroupId();
		CorpTagGroup corpTagGroup = corpTagGroupMapper.selectOne(Wrappers.lambdaQuery(CorpTagGroup.class)
				.eq(CorpTagGroup::getGroupId, groupId).last("limit 1"));
		if (corpTagGroup != null && !StrUtil.equals(tagGroup.getGroupName(), corpTagGroup.getGroupName())) {
			//编辑标签组名称
			JSONObject params = new JSONObject();
			params.putOpt("id", tagGroup.getGroupId());
			params.putOpt("name", tagGroup.getGroupName());
			wxCorpOps.editCorpTag(params);

			corpTagMapper.update(null, Wrappers.lambdaUpdate(CorpTag.class)
					.set(CorpTag::getGroupName, tagGroup.getGroupName())
					.eq(CorpTag::getGroupId, tagGroup.getGroupId()));
		}
		corpTagGroup.setGroupName(tagGroup.getGroupName());
		corpTagGroup.setRemark(tagGroup.getRemark());
		corpTagGroupMapper.updateById(corpTagGroup);

		List<CorpUserExternalTagGroupInfo.Tag> newTagsList = new ArrayList<>();
		Map<String, CorpTag> corpTagMap = new ConcurrentHashMap<>();
		for (CorpTag tagDto : tagGroup.getTagList()) {
			Long corpTagId = tagDto.getId();
			if (CollUtil.isNotEmpty(tagDto.getRuleNameList())) {
				tagDto.setRuleNameListStr(Jsons.toJson(tagDto.getRuleNameList()));
			}
			if (corpTagId != null) {
				CorpTag dbCorpTag = corpTagMapper.getCorpTagById(corpTagId);
				if (dbCorpTag != null) {
					if (!StrUtil.equals(dbCorpTag.getName(), tagDto.getName())) {
						JSONObject params = new JSONObject();
						params.putOpt("id", tagDto.getTagId());
						params.putOpt("name", tagDto.getName());
						wxCorpOps.editCorpTag(params);

						dbCorpTag.setName(tagDto.getName());
						corpTagMapper.updateById(dbCorpTag);
					}

					List<CorpTagRuleRelation> ruleRelationList = dbCorpTag.getRuleRelationList();

					List<CorpTagRuleRelation> updateRuleRelationList = tagDto.getRuleRelationList();
					Map<Long, List<CorpTagRuleRelation>> collect = null;
					if (CollUtil.isNotEmpty(updateRuleRelationList)) {
						collect = updateRuleRelationList.stream().filter(dto -> {
							if (dto.getId() == null) {
								dto.setTagId(tagDto.getId());
								corpTagRuleRelationMapper.insert(dto);
								return false;
							}
							return true;
						}).collect(Collectors.groupingBy(CorpTagRuleRelation::getId));
					}

					final Map<Long, List<CorpTagRuleRelation>> updateMap = Optional.ofNullable(collect).orElse(Maps.newHashMap());

					if (CollUtil.isNotEmpty(ruleRelationList)) {
						ruleRelationList.forEach(dbRule -> {
							List<CorpTagRuleRelation> existsRules = updateMap.get(dbRule.getId());
							if (CollUtil.isEmpty(existsRules)) {
								corpTagRuleRelationMapper.deleteById(dbRule.getId());
								return;
							}
							corpTagRuleRelationMapper.updateById(existsRules.get(0));
						});
					}
				}
				corpTagMapper.updateById(tagDto);
				continue;
			}

			if (StrUtil.isEmpty(tagDto.getGroupName())) {
				tagDto.setGroupName(tagGroup.getGroupName());
			}
			CorpTag exists = corpTagMapper.selectOne(Wrappers.lambdaQuery(CorpTag.class)
					.eq(CorpTag::getGroupName, tagDto.getGroupName())
					.eq(CorpTag::getName, tagDto.getName()).last("limit 1"));
			if (exists != null) throw BusinessRuntimeException.getInstance("标签组下重复标签");
			corpTagMap.putIfAbsent(tagDto.getName(), tagDto);
			CorpUserExternalTagGroupInfo.Tag newTag = new CorpUserExternalTagGroupInfo.Tag();
			newTag.setName(tagDto.getName());
			newTagsList.add(newTag);
		}

		//添加新标签
		if (newTagsList.size() > 0) {
			CorpUserExternalTagGroupInfo tagGroupInfoReq = new CorpUserExternalTagGroupInfo();
			CorpUserExternalTagGroupInfo.TagGroup group = new CorpUserExternalTagGroupInfo.TagGroup();
			group.setGroupId(tagGroup.getGroupId());
			group.setGroupName(tagGroup.getGroupName());
			group.setTag(newTagsList);
			tagGroupInfoReq.setTagGroup(group);
			CorpUserExternalTagGroupInfo corpUserExternalTagGroupInfo = wxCorpOps.addCorpTag(tagGroupInfoReq, null);

			CorpUserExternalTagGroupInfo.TagGroup corp_tagGroup = corpUserExternalTagGroupInfo.getTagGroup();
			corpUserExternalTagGroupInfo.getTagGroup().getTag().forEach(tag -> {
				try {
					CorpTag corpTag = corpTagMap.get(tag.getName());
					if (corpTag == null) return;
					corpTag.setGroupId(corp_tagGroup.getGroupId());
					corpTag.setGroupName(corp_tagGroup.getGroupName());
					corpTag.setOrdered(tag.getOrder());
					corpTag.setTagId(tag.getId());
					corpTag.setName(tag.getName());
					if (CollUtil.isNotEmpty(corpTag.getRuleNameList())) {
						try {
							corpTag.setRuleNameListStr(Jsons.toJson(corpTag.getRuleNameList()));
						} catch (Exception e) {
						}
					}
					//对应标签入库
					corpTagMapper.insert(corpTag);
					if (corpTag.getType() == 2) {
						corpTag.getRuleRelationList().forEach(data -> {
							data.setTagId(corpTag.getId());
							corpTagRuleRelationMapper.insert(data);
						});
					}
				} catch (DuplicateKeyException e) {

				}
			});
		}
	}

	@Override
	public Page<CorpTagGroupView> getCorpTagList(String groupName, Integer start, Integer limit) {
		Page<CorpTagGroupView> tagGroupListPage = corpTagGroupMapper.getCorpTagList(groupName, new Page<>(start, limit));
		tagGroupListPage.getRecords().forEach(tagGrous -> {
			tagGrous.getTagList().forEach(tag -> {
				if (tag.getType() == 2) {
					Optional.ofNullable(corpTagRuleRelationMapper.selectList(Wrappers.lambdaQuery(CorpTagRuleRelation.class)
									.eq(CorpTagRuleRelation::getTagId, tag.getId())))
							.ifPresent(rules -> {
								tag.setRuleRelationList(rules);
								if (StrUtil.isNotEmpty(tag.getRuleNameListStr())) {
									try {
										tag.setRuleNameList(Jsons.parseList(tag.getRuleNameListStr(), String.class));
									} catch (Exception e) {
									}
								}
							});
				}
			});
		});
		return tagGroupListPage;
	}

	@Override
	public void saveOrUpdateRule(CorpTagRule rule) {
		Long id = rule.getId();
		if (id == null) corpTagRuleMapper.insert(rule);
		corpTagRuleMapper.updateById(rule);
	}

	@Override
	public Page<CorpTagBackView> getCorpTagBackView(Integer start, Integer limit, Integer type, String name, String[] groupIds, String sort, String order, String tagIdStr) throws Exception {
		Long wxCorpId = 2l;
		if (type == 1) {
			Page<CorpTagBackView> corpTagBackViewPage = corpTagMapper.getCorpTagBackView(new Page<>(start, limit), name, groupIds, sort, order, wxCorpId, tagIdStr);
			corpTagBackViewPage.getRecords().forEach(view -> {
				if (StrUtil.isNotEmpty(view.getRuleNameListStr())) {
					try {
						view.setRuleNameList(Jsons.parseList(view.getRuleNameListStr(), String.class));
					} catch (Exception e) {
					}
				}
				view.setNumOfCustomer(corpTagMapper.selectCountOfCustomer(view.getTagIdStr(), wxCorpId));
			});
			return corpTagBackViewPage;
		}
		Page<CorpTagBackView> corpTagBackView = corpTagGroupMapper.getCorpTagBackView(new Page<>(start, limit), name, sort, order, wxCorpId);
		corpTagBackView.getRecords().forEach(data -> {
			CorpTagBackView info = corpTagGroupMapper.fillCorpGroupTagInfo(data.getGroupIdStr(), wxCorpId);
			data.setTagSize(info.getTagSize());
			data.setNumOfCustomer(info.getNumOfCustomer());
		});
		return corpTagBackView;
	}

	@Override
	public List<CorpTag> getGroupTagDetail(String groupId) {
		List<CorpTag> corpTags = corpTagMapper.selectList(Wrappers.lambdaQuery(CorpTag.class).eq(CorpTag::getGroupId, groupId));
		return corpTags;
	}

	@Override
	public Page<CorpUserView> getCorpUserDetail(String tagId, String groupId, Integer start, Integer limit) {
		Long wxCorpId = 2l;
		Page<CorpUserView> page = corpUserTagMapper.selectCorpUserDetailByCondition(new Page<>(start, limit), groupId, tagId, wxCorpId);
		page.getRecords().forEach(data -> {
			Optional.ofNullable(userMapper.selectOne(Wrappers.lambdaQuery(User.class)
							.eq(User::getUnionid, data.getUnionId())
							.last("limit 1")))
					.ifPresent(user -> {
						data.setUserId(user.getId());
						data.setNickname(user.getNickname());
						data.setHeadimgurl(user.getHeadimgurl());
					});
		});
		return page;
	}

	@Override
	public List<CorpUserTagExcelData> exportUserTagDetail(String[] tagIds, String[] groupIds) {
		Long wxCorpId = 2l;
		return corpUserTagMapper.exportUserTagDetail(tagIds, groupIds, wxCorpId);
	}

	@Override
	public List<CorpTagRuleRelation> getCorpTagRuleDetail(Long tagId) {
		List<CorpTagRuleRelation> ruleRelationList = corpTagRuleRelationMapper.selectList(Wrappers.lambdaQuery(CorpTagRuleRelation.class)
				.eq(CorpTagRuleRelation::getTagId, tagId));
		return ruleRelationList;
	}

	@Override
	public CorpTagHeadDataView getCorpTagHeadDataView() {
		CorpTagHeadDataView dataView = corpTagMapper.getCorpTagHeadDataView();
		return dataView;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void delTags(CorpDelTagReq req) throws Exception {
		String tagId = req.getTagId();
		String groupId = req.getGroupId();
		if (StrUtil.isEmpty(tagId) && StrUtil.isEmpty(groupId)) {
			throw BusinessRuntimeException.getInstance("请选择指定要删除的标签或组");
		}
		String[] tagIds = null;
		String[] groupIds = null;
		List<CorpTag> corpTags = null;
		if (StrUtil.isNotEmpty(tagId)) {
			corpTags = corpTagMapper.selectList(Wrappers.lambdaQuery(CorpTag.class)
					.eq(CorpTag::getTagId, tagId));
			tagIds = corpTags.stream().filter(tag -> StrUtil.isNotBlank(tag.getTagId())).map(CorpTag::getTagId).toArray(String[]::new);
		}

		if (StrUtil.isNotEmpty(groupId)) {
			List<CorpTagGroup> corpTagGroups = corpTagGroupMapper.selectList(Wrappers.lambdaQuery(CorpTagGroup.class)
					.eq(CorpTagGroup::getGroupId, groupId));
			groupIds = corpTagGroups.stream().filter(group -> StrUtil.isNotBlank(group.getGroupId())).map(CorpTagGroup::getGroupId).toArray(String[]::new);
		}

		if (tagIds != null || groupIds != null) {
			try {
				wxCorpOps.delCorpTag(tagIds, groupIds);
			} catch (Exception e) {
			}
		}
		if (StrUtil.isNotBlank(tagId)) {
			corpTagMapper.delete(Wrappers.lambdaQuery(CorpTag.class).eq(CorpTag::getTagId, tagId));
			if (CollUtil.isNotEmpty(corpTags)) {
				groupIds = corpTags.stream().filter(tag -> StrUtil.isNotEmpty(tag.getGroupId())).map(CorpTag::getGroupId).toArray(String[]::new);
				Integer count = corpTagMapper.selectCount(Wrappers.lambdaQuery(CorpTag.class).in(CorpTag::getGroupId, groupIds));
				if (count == 0) {
					corpTagGroupMapper.delete(Wrappers.lambdaQuery(CorpTagGroup.class).in(CorpTagGroup::getGroupId, groupIds));
				}
			}
		}

		if (StrUtil.isNotBlank(groupId)) {
			corpTagGroupMapper.delete(Wrappers.lambdaQuery(CorpTagGroup.class).eq(CorpTagGroup::getGroupId, groupId));
			corpTagMapper.delete(Wrappers.lambdaQuery(CorpTag.class).eq(CorpTag::getGroupId, groupId));
		}
	}

	@Override
	public CorpTagGroupView addGroup(CorpTagGroupView tagGroup) throws Exception {
		CorpUserExternalTagGroupInfo tagGroupInfoReq = new CorpUserExternalTagGroupInfo();
		if (StrUtil.isAllBlank(tagGroup.getGroupId(), tagGroup.getGroupName())) {
			throw BusinessRuntimeException.getInstance("请输入标签组名");
		}

		CorpUserExternalTagGroupInfo.TagGroup group = new CorpUserExternalTagGroupInfo.TagGroup();
		group.setGroupId(tagGroup.getGroupId());
		group.setGroupName(tagGroup.getGroupName());

		tagGroupInfoReq.setTagGroup(group);
		CorpUserExternalTagGroupInfo corpUserExternalTagGroupInfo = wxCorpOps.addCorpTag(tagGroupInfoReq, null);
		CorpTagGroupView corpTagGroupView = corpTagGroupMapper.getOneCorpGroupTag(tagGroup.getGroupId(), tagGroup.getGroupName());
		return corpTagGroupView;
	}

	@Override
	public Page<UserOrderDetailView> getTagUserData(Integer start, Integer limit, String tagIdStr, String startTime, String endTime, String consumeStTime, String consumeEtTime) {
		Page<UserOrderDetailView> fansRecords = orderDonMapper.getTagUserDataPage(new Page<>(start, limit), tagIdStr, startTime, endTime, consumeStTime, consumeEtTime);
		fansRecords.getRecords().forEach(e->{
			//查询当日订单数
			UserOrderDetailView u2 = orderDonMapper.getFansToDayOrdersView(tagIdStr, e.getDate());

			e.setNumOfOrder(u2.getNumOfOrder());
			e.setOrderMoney(u2.getOrderMoney());
		});
		return fansRecords;
	}

	@Override
	public Page<UserOrderDetailView>  getTagUserPastRecord(Integer start, Integer limit, String tagIdStr, String startTime, String endTime, String consumeStTime, String consumeEtTime) {
		Page<UserOrderDetailView> pastRecords = orderDonMapper.getPastRecord(new Page<>(start, limit), tagIdStr, startTime, endTime, consumeStTime, consumeEtTime);
		return pastRecords;
	}

	@Override
	public Page<CorpTagUserOrderDataView> getTagUserTimeOrderData(Integer start, Integer limit, String tagIdStr, String toDate, String startTime, String endTime) {
		Page<CorpTagUserOrderDataView> records = orderDonMapper.getTagUserTimeOrderData(new Page<>(start, limit), tagIdStr, toDate, startTime, endTime);
		return records;
	}

	@Override
	public UserOrderDetailView tagUserHeadData(String tagIdStr, String startTime, String endTime, String consumeStTime, String consumeEtTime) {
		//被删除用户数，用户数
		UserOrderDetailView userOrderDetailView = orderDonMapper.getNumOfTagFansUser(tagIdStr, startTime, endTime);

		//订单情况
		UserOrderDetailView headView = orderDonMapper.getTagUserOrdersData(tagIdStr, startTime, endTime, consumeStTime, consumeEtTime);

		headView.setNumOfUser(userOrderDetailView.getNumOfUser());
		headView.setDelNumOfUser(userOrderDetailView.getDelNumOfUser());


		headView.setOrderRate(headView.getNumOfUser() == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(headView.getNumOfEpOrder()).divide(BigDecimal.valueOf(headView.getNumOfUser()), 2, RoundingMode.HALF_DOWN));
		return headView;
	}

	@Override
	public UserOrderDetailView getFansUserToMonthOrdersDetail(String tagId, String date) {
		DateTime monthBegin = DateUtil.beginOfMonth(DateTime.now());
		DateTime nextMonth = DateUtil.offsetMonth(monthBegin, 1);
		UserOrderDetailView detailView = corpUserTagMapper.getFansUserToMonthOrdersDetai(tagId, date, monthBegin, nextMonth);
		return detailView;
	}
}
