package com.czg.service.market.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.czg.PageQueryParam;
import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopInfoService;
import com.czg.exception.CzgException;
import com.czg.market.dto.MkDiscountActivityDTO;
import com.czg.market.entity.MkDiscountActivity;
import com.czg.market.entity.MkDiscountThreshold;
import com.czg.market.service.MkDiscountActivityService;
import com.czg.service.market.mapper.MkDiscountActivityMapper;
import com.czg.service.market.mapper.MkDiscountThresholdMapper;
import com.czg.utils.AssertUtil;
import com.czg.utils.CzgStrUtils;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 商家满减活动表 服务层实现。
 *
 * @author ww
 * @since 2025-10-13
 */
@Service
public class MkDiscountActivityServiceImpl extends ServiceImpl<MkDiscountActivityMapper, MkDiscountActivity> implements MkDiscountActivityService {

    @Resource
    private MkDiscountThresholdMapper thresholdMapper;
    @DubboReference
    private ShopInfoService shopInfoService;

    @Override
    public Page<MkDiscountActivityDTO> getActivityPage(PageQueryParam param, Long shopId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(MkDiscountActivity::getShopId, shopId)
                .eq(MkDiscountActivity::getIsDel, 0)
                .lt(MkDiscountActivity::getValidStartTime, CzgStrUtils.getStrOrNull(param.getStartTime()))
                .le(MkDiscountActivity::getValidEndTime, CzgStrUtils.getStrOrNull(param.getEndTime()))
                .orderBy(MkDiscountActivity::getSort).desc()
                .orderBy(MkDiscountActivity::getUpdateTime).desc();
        Page<MkDiscountActivityDTO> page = pageAs(PageUtil.buildPage(), queryWrapper, MkDiscountActivityDTO.class);
        page.getRecords().forEach(
                item -> item.setThresholds(thresholdMapper.selectListByQuery(
                        new QueryWrapper()
                                .eq(MkDiscountThreshold::getActivityId, item.getId())
                                .orderBy(MkDiscountThreshold::getFullAmount, true)
                ))
        );
        return page;
    }

    @Override
    public MkDiscountActivityDTO checkDiscountAct(Long discountActId, boolean couponShare, boolean vipShare, boolean limitRateShare, boolean pointsShare) {
        MkDiscountActivityDTO activityDTO = getActivityById(discountActId);
        AssertUtil.isNull(activityDTO, "店铺未配置满减活动");
        //检查是否开启了优惠券抵扣
        if (couponShare && activityDTO.getCouponShare() == 0) {
            throw new CzgException("满减活动与优惠券不可共用");
        }
        //检查是否开启了限时折扣
//        if (limitRateShare && activityDTO.getDiscountShare() == 0) {
//            throw new CzgException("满减活动与限时折扣不可共用");
//        }
        //检查是否开启了会员抵扣
//        if (vipShare && activityDTO.getVipPriceShare() == 0) {
//            throw new CzgException("满减活动与会员价不可共用");
//        }
        //检查是否开启了积分抵扣
        if (pointsShare && activityDTO.getPointsShare() == 0) {
            throw new CzgException("满减活动与积分抵扣不可共用");
        }
        return activityDTO;
    }

    @Override
    public MkDiscountActivityDTO getActivityByShopId(Long shopId) {
        ShopInfo shopInfo = shopInfoService.getById(shopId);
        AssertUtil.isNull(shopInfo, "店铺不存在");
        if (shopInfo.getIsEnableDiscount() == null || shopInfo.getIsEnableDiscount() == 0) {
            return null;
        }
        MkDiscountActivity activity = mapper.selectOneByShopId(shopId, CzgStrUtils.getStrWeek());
        if (activity == null) {
            return null;
        }
        MkDiscountActivityDTO activityDTO = BeanUtil.toBean(activity, MkDiscountActivityDTO.class);
        activityDTO.setThresholds(thresholdMapper.selectListByQuery(
                new QueryWrapper()
                        .eq(MkDiscountThreshold::getActivityId, activity.getId())
                        .orderBy(MkDiscountThreshold::getFullAmount, false)
        ));
        return activityDTO;
    }


    private MkDiscountActivityDTO getActivityById(Long discountActId) {
        MkDiscountActivity activity = this.getById(discountActId);
        if (activity == null) {
            return null;
        }
        MkDiscountActivityDTO activityDTO = BeanUtil.toBean(activity, MkDiscountActivityDTO.class);
        activityDTO.setThresholds(thresholdMapper.selectListByQuery(
                new QueryWrapper()
                        .eq(MkDiscountThreshold::getActivityId, activity.getId())
                        .orderBy(MkDiscountThreshold::getFullAmount, false)
        ));
        return activityDTO;
    }


    @Override
    public void addActivity(MkDiscountActivityDTO param) {
        if (CollUtil.isEmpty(param.getThresholds())) {
            throw new IllegalArgumentException("活动必须配置满减阈值");
        }
        validateAndInitStatus(param);
        MkDiscountActivity activity = BeanUtil.toBean(param, MkDiscountActivity.class);
        save(activity);
        for (MkDiscountThreshold threshold : param.getThresholds()) {
            threshold.setActivityId(activity.getId());
            thresholdMapper.insert(threshold);
        }
    }

    @Override
    public void updateActivityById(MkDiscountActivityDTO param) {
        if (CollUtil.isEmpty(param.getThresholds())) {
            throw new IllegalArgumentException("活动必须配置满减阈值");
        }
        validateAndInitStatus(param);
        MkDiscountActivity activity = BeanUtil.toBean(param, MkDiscountActivity.class);
        updateById(activity, true);
        thresholdMapper.deleteByQuery(
                new QueryWrapper().eq(MkDiscountThreshold::getActivityId, activity.getId())
        );
        for (MkDiscountThreshold threshold : param.getThresholds()) {
            threshold.setActivityId(activity.getId());
            thresholdMapper.insert(threshold);
        }
    }

    @Override
    public void deleteActivity(Long id) {
        updateById(new MkDiscountActivity().setIsDel(true).setUpdateTime(LocalDateTime.now()).setId(id));
    }

    /**
     * 校验时间有效性并初始化状态
     */
    private void validateAndInitStatus(MkDiscountActivityDTO param) {
        LocalDate startDate;
        LocalDate endDate;
        LocalDate currentDate = LocalDate.now();

        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            startDate = LocalDate.parse(param.getValidStartTime(), formatter);
            endDate = LocalDate.parse(param.getValidEndTime(), formatter);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("时间格式不正确，请使用yyyy-MM-dd格式");
        }
        // 校验开始时间不能晚于结束时间
        if (currentDate.isAfter(endDate)) {
            throw new CzgException("有效期结束时间不能早于当前时间");
        }
        // 校验开始时间不能晚于结束时间
        if (startDate.isAfter(endDate)) {
            throw new CzgException("有效期开始时间不能晚于结束时间");
        }

        // 根据时间初始化状态
        if (currentDate.isBefore(startDate)) {
            // 当前日期在开始日期之前-未开始
            param.setStatus(1);
        } else {
            // 这里先默认设置为进行中，具体由定时任务根据时段更新
            param.setStatus(2);
        }
    }
}
