/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.mall.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.enums.GoodsSourceEnum;
import org.springblade.common.enums.YesOrNoEnum;
import org.springblade.common.enums.ZoneTypeEnum;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.modules.mall.entity.ActivitiesGoods;
import org.springblade.modules.mall.entity.GoodsImg;
import org.springblade.modules.mall.entity.GoodsInfo;
import org.springblade.modules.mall.mapper.GoodsInfoMapper;
import org.springblade.modules.mall.service.IActivitiesGoodsService;
import org.springblade.modules.mall.service.IGoodsInfoService;
import org.springblade.modules.mall.service.IGoodsParamsService;
import org.springblade.modules.mall.vo.GoodsInfoVO;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.*;

/**
 * 商品表 服务实现类
 *
 * @author BladeX
 * @since 2022-05-07
 */
@Slf4j
@Service
public class GoodsInfoServiceImpl extends ServiceImpl<GoodsInfoMapper, GoodsInfo> implements IGoodsInfoService {

	@Resource
	private GoodsImgServiceImpl goodsImgService;
	@Resource
	private IActivitiesGoodsService activitiesGoodsService;
	@Resource
	private IGoodsParamsService goodsParamsService;

	@Override
	public GoodsInfo get(Serializable id) {
		return this.baseMapper.get(id);
	}

	@Override
	public IPage<GoodsInfoVO> selectGoodsInfoPage(IPage<GoodsInfoVO> page, GoodsInfoVO goodsInfo) {
		return page.setRecords(baseMapper.selectGoodsInfoPage(page, goodsInfo));
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void update(@Valid GoodsInfo goodsInfo) {
		GoodsInfo record = this.getById(goodsInfo.getId());
		Assert.notNull(record, "商品信息不存在");
		this.updateById(goodsInfo);

		// 删除老的图片数据
		LambdaQueryWrapper<GoodsImg> wrapper = Wrappers.lambdaQuery(GoodsImg.class).eq(GoodsImg::getGoodsId, goodsInfo.getId());
		List<GoodsImg> list = goodsImgService.list(wrapper);
		if (CollUtil.isNotEmpty(list)) {
			goodsImgService.remove(wrapper);
		}

		// 保存商品图片数据
		List<GoodsImg> goodsImgList = new ArrayList<>();
		List<String> detailImgUrlList = goodsInfo.getDetailImgUrlList();
		if (CollUtil.isNotEmpty(detailImgUrlList)) {
			for (int i = 0; i < detailImgUrlList.size(); i++) {
				String url = detailImgUrlList.get(i);
				goodsImgList.add(new GoodsImg(goodsInfo.getId(), url, 2, 1, i + 1));
			}
		}
		List<String> slideshowList = goodsInfo.getSlideshowList();
		if (StrUtil.isNotBlank(goodsInfo.getVideoUrl())) {
			goodsImgList.add(new GoodsImg(goodsInfo.getId(), goodsInfo.getVideoUrl(), 1, 2, 1));
		}
		if (CollUtil.isNotEmpty(slideshowList)) {
			for (int i = 0; i < slideshowList.size(); i++) {
				String url = slideshowList.get(i);
				goodsImgList.add(new GoodsImg(goodsInfo.getId(), url, 1, 1, i + 2));
			}
		}
		if (CollUtil.isNotEmpty(goodsImgList)) {
			goodsImgService.saveBatch(goodsImgList);
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void submit(@Valid GoodsInfo goodsInfo) {
		goodsInfo.setId(null);
//		goodsInfo.setGoodsNo(generateGoodsNo());
		this.save(goodsInfo);
		// 保存商品图片数据
		List<GoodsImg> goodsImgList = new ArrayList<>();
		List<String> detailImgUrlList = goodsInfo.getDetailImgUrlList();
		if (CollUtil.isNotEmpty(detailImgUrlList)) {
			for (int i = 0; i < detailImgUrlList.size(); i++) {
				String url = detailImgUrlList.get(i);
				goodsImgList.add(new GoodsImg(goodsInfo.getId(), url, 2, 1, i + 1));
			}
		}
		List<String> slideshowList = goodsInfo.getSlideshowList();
		if (StrUtil.isNotBlank(goodsInfo.getVideoUrl())) {
			goodsImgList.add(new GoodsImg(goodsInfo.getId(), goodsInfo.getVideoUrl(), 1, 2, 1));
		}
		if (CollUtil.isNotEmpty(slideshowList)) {
			for (int i = 0; i < slideshowList.size(); i++) {
				String url = slideshowList.get(i);
				goodsImgList.add(new GoodsImg(goodsInfo.getId(), url, 1, 1, i + 2));
			}
		}
		if (CollUtil.isNotEmpty(goodsImgList)) {
			goodsImgService.saveBatch(goodsImgList);
		}
		goodsParamsService.addDefaultParam(goodsInfo.getId());
	}

	@Override
	public GoodsInfo detail(Long id) {
		GoodsInfo detail = this.getById(id);
		Assert.notNull(detail, "商品详情不存在");
		List<GoodsImg> list = goodsImgService.list(Wrappers.lambdaQuery(GoodsImg.class).eq(GoodsImg::getGoodsId, detail.getId()));
		if (CollUtil.isNotEmpty(list)) {
			List<String> slideshowList = new ArrayList<>();
			List<String> detailImgUrlList = new ArrayList<>();
			for (GoodsImg goodsImg : list) {
				if (goodsImg.getFileType() == 2) {
					detail.setVideoUrl(goodsImg.getUrl());
					continue;
				}
				if (goodsImg.getType() == 1) {
					slideshowList.add(goodsImg.getUrl());
				} else {
					detailImgUrlList.add(goodsImg.getUrl());
				}
			}
			detail.setDetailImgUrlList(detailImgUrlList);
			detail.setSlideshowList(slideshowList);
		}
		return detail;
	}

	@Override
	public GoodsInfo getByGoodsNo(String goodsNo) {
		return this.getOne(Wrappers.lambdaQuery(GoodsInfo.class).eq(GoodsInfo::getGoodsNo, goodsNo));
	}

	@Override
	public List<GoodsInfo> getByThirdIds(List<String> thirdIds, GoodsSourceEnum goodsSourceEnum) {
		if (CollUtil.isNotEmpty(thirdIds)) {
			return this.getBaseMapper().selectList(Wrappers.lambdaQuery(GoodsInfo.class).in(GoodsInfo::getThirdId, thirdIds).eq(GoodsInfo::getSource, goodsSourceEnum.getValue()));
		}
		return new ArrayList<>();
	}

	@Override
	public void modifyState(List<Long> ids, Integer state) {
		List<GoodsInfo> goodsInfos = this.getBaseMapper().selectList(Wrappers.lambdaQuery(GoodsInfo.class).in(GoodsInfo::getId, ids));
		if (CollUtil.isNotEmpty(goodsInfos)) {
			List<GoodsInfo> updateList = new ArrayList<>();
			for (GoodsInfo goodsInfo : goodsInfos) {
				GoodsInfo update = new GoodsInfo();
				update.setId(goodsInfo.getId());
				update.setIsSale(state);
				updateList.add(update);
			}
			this.updateBatchById(updateList);
		}
	}

	@Override
	public void modifyCategory(List<Long> ids, String categoryIds) {
		List<GoodsInfo> goodsInfos = this.getBaseMapper().selectList(Wrappers.lambdaQuery(GoodsInfo.class).in(GoodsInfo::getId, ids));
		if (CollUtil.isNotEmpty(goodsInfos)) {
			List<GoodsInfo> updateList = new ArrayList<>();
			for (GoodsInfo goodsInfo : goodsInfos) {
				GoodsInfo update = new GoodsInfo();
				update.setId(goodsInfo.getId());
				update.setGoodsCategoryId(categoryIds + "-");
				updateList.add(update);
			}
			this.updateBatchById(updateList);
		}
	}



	@Transactional(rollbackFor = Exception.class)
	@Override
	public void modifyZoneType(List<Long> ids, Integer zoneType, Date activityDate) {
		List<GoodsInfo> goodsInfos = this.getBaseMapper().selectList(Wrappers.lambdaQuery(GoodsInfo.class).in(GoodsInfo::getId, ids));
		if (CollUtil.isNotEmpty(goodsInfos)) {
			goodsInfos.forEach(e -> e.setZoneType(zoneType));
			this.updateBatchById(goodsInfos);
		}
	}


	@Override
	public List<GoodsInfo> activityGoods(IPage<Object> page, String activityDate) {
		return this.baseMapper.activityGoods(page, activityDate);
	}

	@Async
	@Override
	public void addTotalView(Long goodsInfoId) {
		try {
			GoodsInfo goodsInfo = this.getById(goodsInfoId);
			goodsInfo.setTotalViews(goodsInfo.getTotalViews());
			this.updateById(goodsInfo);
		} catch (Exception e) {}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void setActivityGoods(List<Long> ids, DateTime activityDate) {
		List<GoodsInfo> goodsInfos = this.getBaseMapper().selectList(Wrappers.lambdaQuery(GoodsInfo.class).in(GoodsInfo::getId, ids));
		List<ActivitiesGoods> list = new ArrayList<>();
		for (GoodsInfo goodsInfo : goodsInfos) {
			if (ZoneTypeEnum.CITY_PARTNER.getValue().equals(goodsInfo.getZoneType()) || ZoneTypeEnum.GREEN_INTEGRAL.getValue().equals(goodsInfo.getZoneType()) || ZoneTypeEnum.INTEGRAL_CONVERT.getValue().equals(goodsInfo.getZoneType())) {
				throw new ServiceException("积分兑换专区、绿色积分专区、城市合伙人专区的商品暂不支持添加到活动中");
			}
			ActivitiesGoods record = activitiesGoodsService.lambdaQuery().eq(ActivitiesGoods::getGoodsInfoId, goodsInfo.getId()).one();
			if (record != null && !record.getActivityDate().equals(activityDate)) {
				activitiesGoodsService.removeById(record.getId());
				ActivitiesGoods activitiesGoods = new ActivitiesGoods();
				activitiesGoods.setGoodsInfoId(goodsInfo.getId());
				activitiesGoods.setActivityDate(activityDate);
				activitiesGoods.setStartTime(DateUtil.beginOfDay(activityDate));
				activitiesGoods.setEndTime(DateUtil.endOfDay(activityDate).offset(DateField.MILLISECOND, -999));
				list.add(activitiesGoods);
			}
			if (record == null){
				ActivitiesGoods activitiesGoods = new ActivitiesGoods();
				activitiesGoods.setGoodsInfoId(goodsInfo.getId());
				activitiesGoods.setActivityDate(activityDate);
				activitiesGoods.setStartTime(DateUtil.beginOfDay(activityDate));
				activitiesGoods.setEndTime(DateUtil.endOfDay(activityDate).offset(DateField.MILLISECOND, -999));
				list.add(activitiesGoods);
			}
		}
		activitiesGoodsService.saveBatch(list);
		this.lambdaUpdate().set(GoodsInfo::getIsActivity, YesOrNoEnum.YES.getValue()).in(GoodsInfo::getId, ids).update();
	}

}
