/*
 *      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 com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.common.enums.GoodsStateEnum;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.modules.mall.entity.GoodsInfo;
import org.springblade.modules.mall.entity.GoodsSpec;
import org.springblade.modules.mall.mapper.GoodsSpecMapper;
import org.springblade.modules.mall.service.IGoodsSpecService;
import org.springblade.modules.mall.vo.GoodsSpecVO;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品规格表 服务实现类
 *
 * @author BladeX
 * @since 2022-05-07
 */
@Service
public class GoodsSpecServiceImpl extends ServiceImpl<GoodsSpecMapper, GoodsSpec> implements IGoodsSpecService {

	private final static String GOODS_SPEC_NO_PREFIX = "re:goods:spec:no";

	@Resource
	private GoodsInfoServiceImpl goodsInfoService;
	@Resource
	private RedisTemplate redisTemplate;

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

	@Override
	public void reduceStock(GoodsSpec goodsSpec, Integer num) {
		goodsSpec.setStock(goodsSpec.getStock() - num);
		if (goodsSpec.getStock() < 0) {
			throw new ServiceException("库存异常");
		}
		this.updateById(goodsSpec);
	}

	@Override
	public void addStock(Long goodsSpecId, Integer stock) {
		GoodsSpec goodsSpec = this.get(goodsSpecId);
		Assert.notNull(goodsSpec, "未查询到商品规格数据_" + goodsSpecId);
		goodsSpec.setStock(goodsSpec.getStock() + stock);
		this.updateById(goodsSpec);
	}

	@Override
	public IPage<GoodsSpecVO> selectGoodsSpecPage(IPage<GoodsSpecVO> page, GoodsSpec goodsSpec) {
		return page.setRecords(baseMapper.selectGoodsSpecPage(page, goodsSpec));
	}


	@Override
	public void submit(GoodsSpec goodsSpec) {
		if (goodsSpec.getId() == null) {
			GoodsInfo goodsInfo = goodsInfoService.get(goodsSpec.getGoodsId());
			if (goodsInfo == null) {
				throw new ServiceException("商品信息不存在");
			}
			goodsSpec.setGoodsId(goodsInfo.getId());
//			goodsSpec.setSpceNo(generateGoodsSpecNo());
			// 商品添加的第一个规格设置成默认规格
			Integer count = baseMapper.selectCount(Wrappers.lambdaQuery(GoodsSpec.class).eq(GoodsSpec::getGoodsId, goodsInfo.getId()));
			if (count == 0) {
				goodsSpec.setIsDefault(1);
			} else {
				if (goodsSpec.getIsDefault() == 1) {
					this.update(Wrappers.lambdaUpdate(GoodsSpec.class).set(GoodsSpec::getIsDefault, 0).eq(GoodsSpec::getGoodsId, goodsInfo.getId()));
				}
			}
		} else {
			GoodsSpec spec = baseMapper.selectOne(Wrappers.lambdaQuery(GoodsSpec.class).eq(GoodsSpec::getGoodsId, goodsSpec.getGoodsId()).eq(GoodsSpec::getIsDefault, 1));
			if (!spec.getId().equals(goodsSpec.getId()) && goodsSpec.getIsDefault() == 1) {
				spec.setIsDefault(0);
				baseMapper.updateById(spec);
			}
			if (spec.getId().equals(goodsSpec.getId()) && goodsSpec.getIsDefault() == 0) {
				goodsSpec.setIsDefault(1);
			}
		}
		this.saveOrUpdate(goodsSpec);
	}

	@Override
	public void deleteByGoodsIds(List<Long> goodsIds) {
		baseMapper.delete(Wrappers.lambdaQuery(GoodsSpec.class).in(GoodsSpec::getGoodsId, goodsIds));
	}

	@Override
	public List<GoodsSpec> getByGoodsId(Long goodsId) {
		return this.baseMapper.selectList(Wrappers.lambdaQuery(GoodsSpec.class).eq(GoodsSpec::getGoodsId, goodsId).orderByAsc(GoodsSpec::getSort));
	}

	@Override
	public void updateStatus(Long id) {
		GoodsSpec goodsSpec = this.getById(id);
		goodsSpec.setIsDefault(goodsSpec.getIsDefault() == 1 ? 0 : 1);
		this.updateById(goodsSpec);
		this.flashSpecStatus(goodsSpec.getGoodsId());
	}

	@Override
	public void batchOnSale(List<Long> specIds) {
		this.lambdaUpdate().set(GoodsSpec::getIsSale, GoodsStateEnum.ON_SALE.getValue()).in(GoodsSpec::getId, specIds).update();
	}

	@Override
	public void batchShelves(List<Long> specIds) {
		this.lambdaUpdate().set(GoodsSpec::getIsSale, GoodsStateEnum.UNDERCARRIAGE.getValue()).in(GoodsSpec::getId, specIds).update();
		GoodsSpec goodsSpec = this.getById(specIds.get(0));
		this.flashSpecStatus(goodsSpec.getGoodsId());
	}

	@Override
	public GoodsSpec getLastLowPrice(Long goodsInfoId) {
		return baseMapper.getLastLowPrice(goodsInfoId);
	}

	@Override
	public void batchModifyPrice(List<Long> specIds, BigDecimal salePrice) {
		this.lambdaUpdate().set(GoodsSpec::getSalePrice, salePrice).in(GoodsSpec::getId, specIds).update();
	}

	private void flashSpecStatus(Long goodsId) {
		List<GoodsSpec> list = this.lambdaQuery().eq(GoodsSpec::getGoodsId, goodsId).eq(GoodsSpec::getIsSale, GoodsStateEnum.ON_SALE.getValue()).list();
		if (list.size() == 0) {
			goodsInfoService.lambdaUpdate().set(GoodsInfo::getIsSale, GoodsStateEnum.UNDERCARRIAGE.getValue()).eq(GoodsInfo::getId, goodsId).update();
		} else {
			// 上架的规格没有默认的，则取上架的一条设置为默认
			List<GoodsSpec> collect = list.stream().filter(e -> e.getIsDefault() == 1).collect(Collectors.toList());
			if (collect.size() == 0) {
				GoodsSpec goodsSpec1 = list.get(0);
				goodsSpec1.setIsDefault(1);
				this.updateById(goodsSpec1);
			}
		}
	}

	public String generateGoodsSpecNo() {
		RedisAtomicLong redisAtomicLong = new RedisAtomicLong(GOODS_SPEC_NO_PREFIX, redisTemplate.getConnectionFactory());
		long seq = redisAtomicLong.incrementAndGet();
		return "2" + String.format("%08d", seq);
	}

}
