package com.sqx.modules.activity.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sqx.common.constant.MyConstant;
import com.sqx.common.exception.SqxException;
import com.sqx.common.query.PageQuery;
import com.sqx.common.utils.Constant;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.SpringContextUtils;
import com.sqx.modules.activity.bo.ShopActivityBO;
import com.sqx.modules.activity.dao.ActivityShopDao;
import com.sqx.modules.activity.dto.ActivityGoodsDTO;
import com.sqx.modules.activity.dto.JoinActivityDTO;
import com.sqx.modules.activity.dto.QuitActivityDTO;
import com.sqx.modules.activity.entity.ActivityShop;
import com.sqx.modules.activity.enums.ActivityTypeEnum;
import com.sqx.modules.activity.enums.LimitTypeEnum;
import com.sqx.modules.activity.service.ActivityGoodsService;
import com.sqx.modules.activity.service.ActivityService;
import com.sqx.modules.activity.service.ActivityShopService;
import com.sqx.modules.activity.util.ActivityUtil;
import com.sqx.modules.activity.vo.ActivityShopVO;
import com.sqx.modules.activity.vo.ActivityVO;
import com.sqx.modules.activity.vo.ShopActivityGroupVO;
import com.sqx.modules.activity.vo.ShopActivityVO;
import com.sqx.modules.datacentre.entity.SysUserShop;
import com.sqx.modules.goods.service.GoodsService;
import com.sqx.modules.sys.entity.SysUserEntity;
import com.sqx.modules.sys.service.SysUserShopService;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 活动商家
 * @author : codingliang
 * @date : 2024-6-17
 */
@Service
@RequiredArgsConstructor
public class ActivityShopServiceImpl extends ServiceImpl<ActivityShopDao, ActivityShop> implements ActivityShopService {

    private final ActivityGoodsService activityGoodsService;
    private final SysUserShopService sysUserShopService;

    @Override
    @Transactional
    public List<Long> joinActivity(JoinActivityDTO dto) {
        Long activityId = dto.getActivityId();

        // 检查活动
        ActivityService activityService = SpringContextUtils.applicationContext.getBean(ActivityService.class);
        ActivityVO activity = activityService.getActivityById(activityId);
        if (ObjectUtil.isNull(activity)) {
            throw new SqxException("无效的活动id");
        }

        // 权限校验
        checkAuth(dto.getShopIds(), activityId);

        // 校验参数
        checkParam(dto);

        List<ActivityShop> activityShops = new ArrayList<>();
        for (Long shopId : dto.getShopIds()) {
            // 自动退出活动
            autoExitActivity(shopId);

            // 判断当前店铺已经加入的活动数量
            LambdaQueryWrapper<ActivityShop> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(ActivityShop::getShopId, shopId);
            List<ActivityShop> oldActivityShops = list(queryWrapper);
            if (oldActivityShops.size() >= MyConstant.MAX_NUM_OF_SHOP_JOIN) {
                throw new SqxException("店铺【" + shopId + "】参与活动数量达到上限，请退出其他活动后再次尝试加入活动");
            }

            // 判断当前店铺是否已参加当前活动
            if (oldActivityShops.stream().map(ActivityShop::getActivityId).filter(e -> e.equals(dto.getActivityId())).findFirst().isPresent()) {
                throw new SqxException("店铺【" + shopId + "】已经参与当前活动，不能重复参与");
            }

            // 保存数据
            ActivityShop activityShop = new ActivityShop();
            BeanUtils.copyProperties(dto, activityShop);
            activityShop.setShopId(shopId);

            activityShops.add(activityShop);
        }

        saveBatch(activityShops);

        // 满减活动默认添加店铺所有商品
        if (ActivityTypeEnum.FULL.getTypeCode().equals(activity.getType())) {
            GoodsService goodsService = SpringContextUtils.applicationContext.getBean(GoodsService.class);
            for (ActivityShop activityShop : activityShops) {
                // 查询店铺所有商品
                List<Long> goodsIds = goodsService.getByAllGoodsIdByShopId(activityShop.getShopId());

                if (CollUtil.isNotEmpty(goodsIds)) {
                    ActivityGoodsDTO activityGoodsDTO = new ActivityGoodsDTO();
                    activityGoodsDTO.setActivityShopId(activityShop.getId());
                    activityGoodsDTO.setGoodsIds(goodsIds);

                    activityGoodsService.updateActivityGoods(activityGoodsDTO);
                }
            }
        }

        return activityShops.stream().map(ActivityShop::getId).collect(Collectors.toList());
    }

    /**
     * 自动退出活动
     * @param shopId 店铺id
     */
    private void autoExitActivity(Long shopId) {
        LambdaQueryWrapper<ActivityShop> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ActivityShop::getShopId, shopId);
        List<ActivityShop> oldActivityShops = list(queryWrapper);

        if (oldActivityShops.size() > 0) {
            ActivityService activityService = SpringContextUtils.applicationContext.getBean(ActivityService.class);
            List<ActivityVO> activityVOS = activityService.getActivityByIds(oldActivityShops.stream().map(ActivityShop::getActivityId).collect(Collectors.toList()));

            Date currentDate = new Date();
            activityVOS = activityVOS.stream().filter(e -> currentDate.after(e.getStartTime()) && currentDate.before(e.getEndTime())).collect(Collectors.toList());

            // 目前还未被删除的活动、且在有效期内的活动id集合
            List<Long> existActivityIds = activityVOS.stream().map(ActivityVO::getId).collect(Collectors.toList());

            List<ActivityShop> waitDelList = oldActivityShops.stream().filter(e -> !existActivityIds.contains(e.getActivityId())).collect(Collectors.toList());

            if (waitDelList.size() > 0) {
                this.removeByIds(waitDelList.stream().map(ActivityShop::getId).collect(Collectors.toList()));
            }
        }

    }

    @Transactional
    @Override
    public void quitActivity(QuitActivityDTO dto) {
        checkAuth(Arrays.asList(dto.getShopId()), null);

        LambdaQueryWrapper<ActivityShop> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ActivityShop::getShopId, dto.getShopId());
        queryWrapper.eq(ActivityShop::getActivityId, dto.getActivityId());

        ActivityShop activityShop = this.getOne(queryWrapper);

        if (ObjectUtil.isNotNull(activityShop)) {
            removeById(activityShop);

            // 同时删除商品
            activityGoodsService.deleteByActivityShopId(activityShop.getId());
        }

    }

    @Override
    public void quitByActivityShopId(Long activityShopId) {
        ActivityShop activityShop = this.getById(activityShopId);

        if (ObjectUtil.isNotNull(activityShop)) {
            checkAuth(Arrays.asList(activityShop.getShopId()), null);

            this.removeById(activityShopId);

            // 同时删除商品
            activityGoodsService.deleteByActivityShopId(activityShop.getId());
        }
    }

    @Override
    public List<ActivityShop> getByActivityIds(List<Long> activityIds) {
        LambdaQueryWrapper<ActivityShop> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(ActivityShop::getActivityId, activityIds);
        return list(queryWrapper);
    }

    @Override
    public PageUtils getShopByActivityId(Long activityId, PageQuery queryDTO) {
        Page<ActivityShop> pages = new Page<>(queryDTO.getPage(), queryDTO.getLimit());
        IPage<ActivityShopVO> page = baseMapper.pageShopByActivityId(pages, activityId);

        PageUtils pageUtils = new PageUtils(page);
        return pageUtils;
    }

    @Override
    public ShopActivityGroupVO getShopActivityGroup(Long shopId) {
        return baseMapper.getShopActivityGroup(shopId);
    }

    @Override
    public List<ShopActivityVO> getActivityByShopIds(List<Long> shopIds) {
        List<ShopActivityVO> activityByShopIds = baseMapper.getActivityByShopIds(shopIds);

        Date currentDate = new Date();
        return activityByShopIds.stream()
                .filter(e -> currentDate.after(e.getStartTime()) && currentDate.before(e.getEndTime()))
                .collect(Collectors.toList());
    }

    @Override
    public List<ShopActivityBO> getShopActivityBOByShopId(Long shopId) {
        List<ShopActivityBO> shopActivityBOS = baseMapper.getShopActivityBOByShopId(shopId);

        Date currentDate = new Date();
        return shopActivityBOS.stream()
                .map(ActivityUtil::parseActivityConfig)
                // 过滤出当前时间范围内的活动
                .filter(e -> currentDate.after(e.getStartTime()) && currentDate.before(e.getEndTime()))
                // 时段优惠活动过滤
                .filter(ActivityUtil::judgeActivitySuitCurTime)
                .collect(Collectors.toList());
    }

    /**
     * 参数校验
     * @param dto 加入活动参数
     */
    private void checkParam(JoinActivityDTO dto) {
        String limitType = dto.getLimitType();
        if (StrUtil.equals(limitType, LimitTypeEnum.NUM_LIMIT.getTypeCode())) {
            if (ObjectUtil.isNull(dto.getLimitValue())) {
                throw new SqxException("限制数量不能为空");
            }
        }
    }

    /**
     * 检查权限
     *  判断当前用户对相关的店铺有没有操作权限
     * @param shopIds 店铺列表
     * @param activityId 活动id，退出活动时可以不传
     */
    private void checkAuth(List<Long> shopIds, Long activityId) {
        SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
        // 1平台管理员、2商户管理员
        Integer userType = user.getUserType();
        if (userType.intValue() == 2) {
            if (shopIds.size() > 1) {
                throw new SqxException("权限不足：商户管理员只能操作自己的店铺加入或退出活动");
            }

            Long curShopId = shopIds.get(0);
            SysUserShop userShop = sysUserShopService.getByUserId(user.getUserId());
            if (ObjectUtil.notEqual(curShopId, userShop.getShopId())) {
                throw new SqxException("权限不足：商户管理员只能操作自己的店铺加入或退出活动");
            }

            // activityId不为null表示加入活动时需验证活动是否允许商户自行加入
            if (ObjectUtil.isNotNull(activityId)) {
                ActivityService activityService = SpringContextUtils.applicationContext.getBean(ActivityService.class);
                ActivityVO activity = activityService.getActivityById(activityId);
                if (ObjectUtil.isNull(activity)) {
                    throw new SqxException("无效的活动id");
                }

                if (!StrUtil.equals(activity.getAllowShop(), Constant.YES)) {
                    throw new SqxException("当前活动不允许商户主动加入，请联系平台管理员加入");
                }
            }
        }
    }
}
