package com.yiqi.app.service.impl;

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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yiqi.activity.domain.ActivityCouponItem;
import com.yiqi.activity.domain.vo.ActivityCouponInfoVO;
import com.yiqi.activity.service.IActivityCouponInfoService;
import com.yiqi.activity.service.IActivityCouponItemService;
import com.yiqi.app.domain.AppCouponType;
import com.yiqi.app.domain.AppCouponTypeApplyOrg;
import com.yiqi.app.domain.AppUser;
import com.yiqi.app.domain.dto.*;
import com.yiqi.app.domain.dto.weapp.AppCouponItemCountQueryDTO;
import com.yiqi.app.domain.vo.AppCouponItemVO;
import com.yiqi.app.service.IAppCouponTypeApplyOrgService;
import com.yiqi.app.service.IAppCouponTypeService;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.common.enums.*;
import com.yiqi.common.exception.ServiceException;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.SecurityUtils;
import com.yiqi.common.utils.StringUtils;
import com.yiqi.order.domain.dto.OrderCouponDTO;
import com.yiqi.system.domain.SysOrg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import com.yiqi.app.mapper.AppCouponItemMapper;
import com.yiqi.app.domain.AppCouponItem;
import com.yiqi.app.service.IAppCouponItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import static com.yiqi.common.utils.DateUtils.YYYY_MM_DD;

/**
 * 优惠券Service业务层处理
 *
 * @author xiaohei
 * @date 2023-09-19
 */
@Service
@Slf4j
public class AppCouponItemServiceImpl extends ServiceImpl<AppCouponItemMapper, AppCouponItem> implements IAppCouponItemService {
    @Autowired
    private IAppCouponTypeService appCouponTypeService;
    @Autowired
    private IAppCouponTypeApplyOrgService appCouponTypeApplyOrgService;
    @Autowired
    private IAppUserService appUserService;
    @Autowired
    private IActivityCouponInfoService activityCouponInfoService;
    @Autowired
    private IActivityCouponItemService activityCouponItemService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public List<SysOrg> orgListByCouponId(Long couponTypeId) {
        return baseMapper.orgListByCouponId(couponTypeId);
    }

    @Override
    public List<AppCouponItemVO> getlistByAppUserId(AppCouponItemQueryByAppUserIdDTO appCouponItemQueryByAppUserIdDTO) {
        return baseMapper.getlistByAppUserId(appCouponItemQueryByAppUserIdDTO);
    }

    /**
     * 查询优惠券
     *
     * @param id 优惠券主键
     * @return 优惠券
     */
    @Override
    public AppCouponItem selectAppCouponItemById(Long id) {
        return baseMapper.selectAppCouponItemById(id);
    }

    /**
     * 查询优惠券列表
     *
     * @param appCouponItemQueryDTO 优惠券
     * @return 优惠券
     */
    @Override
    public List<AppCouponItemVO> selectAppCouponItemList(AppCouponItemQueryDTO appCouponItemQueryDTO) {
        return baseMapper.selectAppCouponItemList(appCouponItemQueryDTO);
    }

    @Override
    public List<AppCouponItemVO> couponSendListByStore(AppCouponItemCountQueryDTO appCouponItemCountQueryDTO) {
        return baseMapper.couponSendListByStore(appCouponItemCountQueryDTO);
    }

    @Override
    public int countCouponSendListByStore(AppCouponItemCountQueryDTO appCouponItemCountQueryDTO) {
        return baseMapper.countCouponSendListByStore(appCouponItemCountQueryDTO);
    }

    /**
     * 总部发放优惠券
     *
     * @param appCouponItemSendDTO 优惠券
     * @return 结果
     */
    @Override
    public int insertAppCouponItemByHQ(AppCouponItemSendDTO appCouponItemSendDTO) {
        AppCouponType appCouponType = appCouponTypeService.getOne(new QueryWrapper<AppCouponType>().lambda()
                .eq(AppCouponType::getId, appCouponItemSendDTO.getCouponTypeId())
                .eq(AppCouponType::getDelFlag, StatusType.OK.getCode())
                .eq(AppCouponType::getStatus, StatusType.OK.getCode())
                .ge(AppCouponType::getEndDate, DateUtils.getNowDate(YYYY_MM_DD)), false);
        if (appCouponType == null) {
            throw new ServiceException("优惠劵不存在或者已过期");
        }
        // 设置 发放数量
        if (appCouponType.getCouponStock().compareTo(appCouponItemSendDTO.getSendNum()) < 0) {
            throw new ServiceException("优惠券库存不足，无法发放");
        }
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda()
                .eq(AppUser::getPhoneNumber, appCouponItemSendDTO.getAppUserPhoneNumber())
                .eq(AppUser::getStatus, StatusType.OK.getCode()), false);
        if (appUser == null) {
            throw new ServiceException("用户不存在或者已禁用");
        }
        Long createById = SecurityUtils.getUserId();
        String createBy = SecurityUtils.getUsername();
        this.buildAppCouponItem(appCouponItemSendDTO, appCouponType, appUser, createBy, createById);
        appCouponTypeService.update(new UpdateWrapper<AppCouponType>().lambda()
                .eq(AppCouponType::getId, appCouponItemSendDTO.getCouponTypeId())
                .setSql("coupon_stock = coupon_stock - " + appCouponItemSendDTO.getSendNum())
                .setSql("coupon_send_num = coupon_send_num + " + appCouponItemSendDTO.getSendNum()));
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertAppCouponItemByStore(AppCouponItemSendDTO appCouponItemSendDTO) {
        ActivityCouponInfoVO activityCouponInfoVO = activityCouponInfoService.selectActivityCouponInfoBySendCoupon(appCouponItemSendDTO.getActivityId(), appCouponItemSendDTO.getCouponTypeId());
        if (activityCouponInfoVO == null) {
            throw new ServiceException("活动不存在");
        }
        // 如果活动优惠券设置了自定义有效期， 就用自定义有效期校验
        if (SysBoolType.YES.getCode().equals(activityCouponInfoVO.getIsCustomValidityPeriod())) {
            int compare = activityCouponInfoVO.getItemEndDate().compareTo(DateUtils.getNowDate(YYYY_MM_DD));
            if (compare < 0) {
                throw new ServiceException("活动优惠券不在有效期范围内，无法发放");
            }
        }
        AppCouponType appCouponType = appCouponTypeService.getOne(new QueryWrapper<AppCouponType>().lambda()
                .eq(AppCouponType::getId, appCouponItemSendDTO.getCouponTypeId())
                .eq(AppCouponType::getStatus, StatusType.OK.getCode())
                .eq(AppCouponType::getDelFlag, DeleteStatus.OK.getCode()));
        if (appCouponType == null) {
            throw new ServiceException("优惠劵不存在或者已过期");
        }
        // 如果活动优惠券没有设置了自定义有效期， 就用优惠券本身有效期校验
        if (SysBoolType.NO.getCode().equals(activityCouponInfoVO.getIsCustomValidityPeriod())) {
            int compare = appCouponType.getEndDate().compareTo(DateUtils.getNowDate(YYYY_MM_DD));
            if (compare < 0) {
                throw new ServiceException("优惠券不在有效期范围内，无法发放");
            }
        }
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda()
                .eq(AppUser::getPhoneNumber, appCouponItemSendDTO.getAppUserPhoneNumber())
                .eq(AppUser::getStatus, StatusType.OK.getCode()), false);
        if (appUser == null) {
            throw new ServiceException("用户不存在或者已禁用");
        }
        Long createById = SecurityUtils.getUserId();
        String createBy = SecurityUtils.getUsername();
        // 设置 发放数量
        if (activityCouponInfoVO.getCouponStock().compareTo(Long.valueOf(appCouponItemSendDTO.getSendNum())) < 0) {
            throw new ServiceException("优惠券库存不足，无法发放");
        }
        this.buildAppCouponItem(appCouponItemSendDTO, appCouponType, appUser, createBy, createById);
        activityCouponItemService.update(new UpdateWrapper<ActivityCouponItem>().lambda()
                .eq(ActivityCouponItem::getCouponTypeId, appCouponItemSendDTO.getCouponTypeId())
                .eq(ActivityCouponItem::getActivityId, appCouponItemSendDTO.getActivityId())
                .setSql("coupon_stock = coupon_stock - " + appCouponItemSendDTO.getSendNum())
                .setSql("coupon_send_num = coupon_send_num + " + appCouponItemSendDTO.getSendNum()));
        return 1;
    }

    @Override
    public int receiveCouponItemByUser(Long couponId, Long appUserId) {
        AppCouponType appCouponType = appCouponTypeService.getOne(new QueryWrapper<AppCouponType>().lambda()
                .eq(AppCouponType::getId, couponId)
                .eq(AppCouponType::getStatus, StatusType.OK.getCode())
                .eq(AppCouponType::getDelFlag, DeleteStatus.OK.getCode()));
        if (appCouponType == null) {
            throw new ServiceException("优惠劵不存在或者已过期");
        }
        AppUser appUser = appUserService.selectAppUserById(appUserId);
        if (appUser == null) {
            throw new ServiceException("用户不存在或者已禁用");
        }
        // 设置 发放数量
        if (appCouponType.getCouponStock() < 1) {
            throw new ServiceException("优惠券库存不足，无法发放");
        }

        AppCouponItem appCouponItem = new AppCouponItem();
        BeanUtils.copyProperties(appCouponType, appCouponItem);
        appCouponItem.setId(null);
        appCouponItem.setCouponTypeId(appCouponType.getId());
        appCouponItem.setCouponTypeTitle(appCouponType.getTitle());
        appCouponItem.setSource("activeSend");
        appCouponItem.setAppUserId(appUserId);
        appCouponItem.setIsUnique(appCouponType.getIsUnique());
        appCouponItem.setStoreScope(2);
        appCouponItem.setIsUsed("N");
        //获取优惠券的适用门店
        List<AppCouponTypeApplyOrg> orgList = appCouponTypeApplyOrgService.selectAppCouponTypeApplyOrgList(appCouponType.getId());
        //设置适用门店，对象转成id集合
        List<Long> ids = orgList.stream().map(AppCouponTypeApplyOrg::getOrgId).collect(Collectors.toList());
        appCouponItem.setStoreIds(StringUtils.join(ids, ","));
        appCouponItem.buildCreateData();
        this.save(appCouponItem);
        //更新优惠券数量
        appCouponTypeService.update(new UpdateWrapper<AppCouponType>().lambda()
                .eq(AppCouponType::getId, appCouponType.getId())
                .setSql("coupon_stock = coupon_stock - 1")
                .setSql("coupon_send_num = coupon_send_num + 1"));
        return 1;
    }


    private void buildAppCouponItem(AppCouponItemSendDTO appCouponItemSendDTO, AppCouponType appCouponType, AppUser appUser, String createBy, Long createById) {
        List<AppCouponItem> appCouponItems = new ArrayList<>();
        for (int i = 0; i < appCouponItemSendDTO.getSendNum(); i++) {
            AppCouponItem appCouponItem = new AppCouponItem();
            BeanUtils.copyProperties(appCouponType, appCouponItem);
            appCouponItem.setStoreId(appCouponItemSendDTO.getOrgId());

            appCouponItem.setId(null);
            if (appCouponItemSendDTO.getActivityId() != null) {
                appCouponItem.setActivityInfoId(appCouponItemSendDTO.getActivityId());
            }
            Integer storeScope = 1;
            if (appCouponItemSendDTO.getSourceType().equals(SourceType.MANAGER.getCode())) {
                //总部
                storeScope = 2;
                appCouponItem.setSource("platformSend");
                //获取优惠券的适用门店
                List<AppCouponTypeApplyOrg> orgList = appCouponTypeApplyOrgService.selectAppCouponTypeApplyOrgList(appCouponType.getId());
                //设置适用门店，对象转成id集合
                List<Long> ids = orgList.stream().map(AppCouponTypeApplyOrg::getOrgId).collect(Collectors.toList());
                appCouponItem.setStoreIds(StringUtils.join(ids, ","));
            }
            //设置适用门店 1：适用领取本店 2：参与门店
            if (appCouponItemSendDTO.getSourceType().equals(SourceType.STORE.getCode())) {
                //门店
                appCouponItem.setSource("storeSend");
                //只适用于本店
                appCouponItem.setStoreIds(appCouponItemSendDTO.getOrgId() + "");
            }
            appCouponItem.setCouponTypeTitle(appCouponType.getTitle());
            appCouponItem.setIsUsed(SysBoolType.NO.getCode());
            appCouponItem.setCouponTypeId(appCouponType.getId());
            appCouponItem.setIsUnique(appCouponType.getIsUnique());
            appCouponItem.setStoreScope(storeScope);
            appCouponItem.setAppUserId(appUser.getId());
            appCouponItem.setCreateById(createById);
            appCouponItem.setCreateBy(createBy);
            appCouponItem.setCreateTime(DateUtils.getNowDate());
            appCouponItems.add(appCouponItem);
        }
        this.saveBatch(appCouponItems);
        //更新优惠券数量
        appCouponTypeService.update(new UpdateWrapper<AppCouponType>().lambda()
                .eq(AppCouponType::getId, appCouponType.getId())
                .setSql("coupon_stock = coupon_stock - " + appCouponItemSendDTO.getSendNum())
                .setSql("coupon_send_num = coupon_send_num + " + + appCouponItemSendDTO.getSendNum()));
    }

    /**
     * 修改优惠券
     *
     * @param appCouponItem 优惠券
     * @return 结果
     */
    @Override
    public int updateAppCouponItem(AppCouponItem appCouponItem) {
        appCouponItem.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateById(appCouponItem);
    }

    @Override
    public int checkCouponItem(Long couponId, Long appUserId) {
        //优惠券使用完后，将优惠券修改为已使用状态
        update(new UpdateWrapper<AppCouponItem>()
                .lambda().set(AppCouponItem::getIsUsed, SysBoolType.YES.getCode())
                .set(AppCouponItem::getUsedStoreId, SecurityUtils.getLoginUser().getOrgId())
                .set(AppCouponItem::getUsedTime, DateUtils.getNowDate())
                .eq(AppCouponItem::getAppUserId, appUserId)
                .eq(AppCouponItem::getId, couponId));
        //记录使用日志
        log.info("优惠券使用成功，优惠券id：{}", couponId);
        return 0;
    }

    @Override
    public int resetCouponItem(Long couponId, Long appUserId) {
        update(new UpdateWrapper<AppCouponItem>()
                .lambda().set(AppCouponItem::getIsUsed, SysBoolType.NO.getCode())
                .set(AppCouponItem::getUsedStoreId, null)
                .set(AppCouponItem::getUsedTime, null)
                .eq(AppCouponItem::getAppUserId, appUserId)
                .eq(AppCouponItem::getId, couponId));
        return 0;
    }

    /**
     * 批量删除优惠券
     *
     * @param ids 需要删除的优惠券主键
     * @return 结果
     */
    @Override
    public int deleteAppCouponItemByIds(Long[] ids) {
        return baseMapper.deleteAppCouponItemByIds(ids);
    }

    /**
     * 删除优惠券信息
     *
     * @param id 优惠券主键
     * @return 结果
     */
    @Override
    public int deleteAppCouponItemById(Long id) {
        return baseMapper.deleteAppCouponItemById(id);
    }

    @Override
    public List<AppCouponItem> getMemberCouponInfoByRecharge(MemberCouponItemQueryDTO memberCouponItemQueryDTO) {
        return baseMapper.getMemberCouponInfoByRecharge(memberCouponItemQueryDTO,
                DateUtils.getNowDate(YYYY_MM_DD),
                SecurityUtils.getLoginUser().getOrgId(),
                SecurityUtils.getLoginUser().getSourceType());
    }

    @Override
    public int countMemberCouponInfoByRecharge(MemberCouponItemQueryDTO memberCouponItemQueryDTO) {
        return baseMapper.countMemberCouponInfoByRecharge(memberCouponItemQueryDTO, DateUtils.getNowDate(YYYY_MM_DD));
    }

    @Override
    public int countTodaySendNumber(String dateTimeNow) {
        return baseMapper.countTodaySendNumber(SecurityUtils.getLoginUser().getStoreId(),
                SecurityUtils.getLoginUser().getSourceType(),
                dateTimeNow);
    }

    @Override
    public int countTodayHxNumber(String dateTimeNow) {
        return baseMapper.countTodayHxNumber(SecurityUtils.getLoginUser().getStoreId(),
                SecurityUtils.getLoginUser().getSourceType(),
                dateTimeNow);
    }


}
