package cn.iocoder.yudao.module.member.service.activitypaytable;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.admin.activitypaytable.vo.ActivityPayTablePageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.activitypaytable.vo.ActivityPayTableRespVO;
import cn.iocoder.yudao.module.member.controller.admin.activitypaytable.vo.ActivityPayTableSaveReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.activitymerchant.ActivityMerchantDO;
import cn.iocoder.yudao.module.member.dal.dataobject.activitypaytable.ActivityPayTableDO;
import cn.iocoder.yudao.module.member.dal.dataobject.activitytabledish.ActivityTableDishDO;
import cn.iocoder.yudao.module.member.dal.mysql.activitypaytable.ActivityPayTableMapper;
import cn.iocoder.yudao.module.member.service.activitymerchant.ActivityMerchantService;
import cn.iocoder.yudao.module.member.service.activitytabledish.ActivityTableDishService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ACTIVITY_PAY_TABLE_NOT_EXISTS;

/**
 * 活动付款 Service 实现类
 *
 * @author 我是秦俊旗
 */
@Service
@Validated
public class ActivityPayTableServiceImpl implements ActivityPayTableService {

    @Resource
    private ActivityPayTableMapper activityPayTableMapper;
    @Resource
    @Lazy
    private ActivityTableDishService activityTableDishService;
    @Resource
    @Lazy
    private ActivityMerchantService activityMerchantService;

    @Override
    public Long createActivityPayTable(ActivityPayTableSaveReqVO createReqVO) {
        // 插入
        ActivityPayTableDO activityPayTable = BeanUtils.toBean(createReqVO, ActivityPayTableDO.class);
        activityPayTableMapper.insert(activityPayTable);
        // 返回
        return activityPayTable.getId();
    }

    @Override
    public void updateActivityPayTable(ActivityPayTableSaveReqVO updateReqVO) {
        // 校验存在
        validateActivityPayTableExists(updateReqVO.getId());
        // 更新
        ActivityPayTableDO updateObj = BeanUtils.toBean(updateReqVO, ActivityPayTableDO.class);
        activityPayTableMapper.updateById(updateObj);
    }

    @Override
    public void deleteActivityPayTable(Long id) {
        // 校验存在
        validateActivityPayTableExists(id);
        // 删除
        activityPayTableMapper.deleteById(id);
    }

    private void validateActivityPayTableExists(Long id) {
        if (activityPayTableMapper.selectById(id) == null) {
            throw exception(ACTIVITY_PAY_TABLE_NOT_EXISTS);
        }
    }

    @Override
    public ActivityPayTableDO getActivityPayTable(Long id) {
        return activityPayTableMapper.selectById(id);
    }

    @Override
    public PageResult<ActivityPayTableDO> getActivityPayTablePage(ActivityPayTablePageReqVO pageReqVO) {
        return activityPayTableMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<ActivityPayTableRespVO> getActivityPayTableGroupPage(ActivityPayTablePageReqVO pageReqVO) {
        List<Integer> collect = new ArrayList<>();
        if(pageReqVO.getMerchantId() != null){
            List<ActivityTableDishDO> listByActivityIdAndMerchantId = activityTableDishService.getListByActivityIdAndMerchantId(pageReqVO.getActivityId(), pageReqVO.getMerchantId());
            if (listByActivityIdAndMerchantId.isEmpty()) {
                return PageResult.empty();
            }
            collect = listByActivityIdAndMerchantId.stream().map(ActivityTableDishDO::getSerialNumber).collect(Collectors.toList());
        }
        PageResult<ActivityPayTableDO> activityPayTableDOPageResult = activityPayTableMapper.selectPage(pageReqVO, new LambdaQueryWrapper<ActivityPayTableDO>()
                .select(ActivityPayTableDO::getSerialNumbers, ActivityPayTableDO::getAllPrice)
                .eq(StrUtil.isNotBlank(pageReqVO.getSerialNumbers()), ActivityPayTableDO::getSerialNumbers, pageReqVO.getSerialNumbers())
                .eq(ActivityPayTableDO::getActivityId, pageReqVO.getActivityId())
                .in(CollectionUtil.isNotEmpty(collect), ActivityPayTableDO::getSerialNumbers, collect)
                .groupBy(ActivityPayTableDO::getSerialNumbers)
        );
        List<ActivityPayTableDO> list = activityPayTableDOPageResult.getList();

        List<ActivityPayTableRespVO> newList = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(list)){
            list.forEach(activityPayTableDO -> {
                ActivityPayTableRespVO bean = BeanUtils.toBean(activityPayTableDO, ActivityPayTableRespVO.class);
                Long merchantIdByActivityIdAndSerialNumber = activityTableDishService.getMerchantIdByActivityIdAndSerialNumber(pageReqVO.getActivityId(), Integer.valueOf(activityPayTableDO.getSerialNumbers()));
                if(merchantIdByActivityIdAndSerialNumber != null){
                    ActivityMerchantDO activityMerchant = activityMerchantService.getActivityMerchant(merchantIdByActivityIdAndSerialNumber);
                    bean.setName(activityMerchant.getName());
                }
                newList.add(bean);
            });
        }
        return new PageResult<>(newList, activityPayTableDOPageResult.getTotal());
    }

    @Override
    public void insertBatch(List<ActivityPayTableDO> list) {
        activityPayTableMapper.insertBatch(list);
    }

    @Override
    public void insertOne(ActivityPayTableDO activityPayTableDO) {
        activityPayTableMapper.insert(activityPayTableDO);
    }

    @Override
    public ActivityPayTableDO getOneByActivityIdAndTimeAndNum(Long activityId, LocalDate time, Integer num) {
        return activityPayTableMapper.selectOne(new LambdaQueryWrapper<ActivityPayTableDO>()
                .eq(ActivityPayTableDO::getActivityId, activityId)
                .eq(ActivityPayTableDO::getReserveTime, time)
                .eq(ActivityPayTableDO::getSerialNumbers, num)
                .select(
                        ActivityPayTableDO::getId,
                        ActivityPayTableDO::getActivityId,
                        ActivityPayTableDO::getReserveTime,
                        ActivityPayTableDO::getSerialNumbers,
                        ActivityPayTableDO::getPrice,
                        ActivityPayTableDO::getUserId,
                        ActivityPayTableDO::getNickName,
                        ActivityPayTableDO::getMobile
                )
                .last("limit 1")
        );
    }

    @Override
    public void updateOne(ActivityPayTableDO activityPayTableDO) {
        activityPayTableMapper.updateById(activityPayTableDO);
    }
}