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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.entity.AcUserMsg;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.AcUserMsgService;
import com.czg.account.service.ShopConfigService;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.enums.ShopUserFlowBizEnum;
import com.czg.market.dto.MkConsumeCashbackDTO;
import com.czg.market.entity.MkConsumeCashback;
import com.czg.market.entity.MkConsumeCashbackRecord;
import com.czg.market.entity.MkConsumeCashbackStep;
import com.czg.market.service.MkConsumeCashbackRecordService;
import com.czg.market.service.MkConsumeCashbackService;
import com.czg.market.service.OrderInfoService;
import com.czg.market.vo.MkConsumeCashbackVO;
import com.czg.order.entity.OrderInfo;
import com.czg.service.market.enums.OrderStatusEnums;
import com.czg.service.market.mapper.MkConsumeCashbackMapper;
import com.czg.utils.AssertUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 服务层实现。
 *
 * @author zs
 * @since 2025-10-13
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "consumeCashback")
public class MkConsumeCashbackServiceImpl extends ServiceImpl<MkConsumeCashbackMapper, MkConsumeCashback> implements MkConsumeCashbackService {
    @DubboReference
    private ShopInfoService shopInfoService;
    @DubboReference
    private ShopUserService shopUserService;
    @Resource
    private OrderInfoService orderInfoService;
    @DubboReference
    private ShopConfigService shopConfigService;
    BigDecimal bili = BigDecimal.valueOf(100);
    @Resource
    private MkConsumeCashbackRecordService consumeCashbackRecordService;

    @DubboReference
    private AcUserMsgService acUserMsgService;

    @Override
    @Cacheable(key = "#shopId")
    public MkConsumeCashbackVO detail(Long shopId) {
        MkConsumeCashback consumeCashback = getOne(new QueryWrapper().eq(MkConsumeCashback::getMainShopId, shopId));
        if (consumeCashback == null) {
            consumeCashback = new MkConsumeCashback();
            consumeCashback.setMainShopId(shopId);
            save(consumeCashback);
            consumeCashback = getOne(new QueryWrapper().eq(MkConsumeCashback::getMainShopId, shopId));
        }
        MkConsumeCashbackVO consumeCashbackVO = BeanUtil.copyProperties(consumeCashback, MkConsumeCashbackVO.class, "cashbackInfo", "shopIdList", "cashbackStepList");
        if (StrUtil.isNotBlank(consumeCashback.getCashbackStepList())) {
            consumeCashbackVO.setCashbackStepList(JSONArray.parseArray(consumeCashback.getCashbackStepList()).toList(MkConsumeCashbackStep.class));
        }

        if (StrUtil.isNotBlank(consumeCashback.getShopIdList())) {
            consumeCashbackVO.setShopIdList(JSONArray.parseArray(consumeCashback.getShopIdList()).toList(Long.class));
        }

        return consumeCashbackVO;
    }

    @Override
    @CacheEvict(key = "#shopId")
    public Boolean edit(Long shopId, MkConsumeCashbackDTO consumeDiscountDTO) {
        MkConsumeCashback consumeCashback = getOne(new QueryWrapper().eq(MkConsumeCashback::getMainShopId, shopId));
        BeanUtil.copyProperties(consumeDiscountDTO, consumeCashback);
        // 包含的店铺开启余额支付
        if ("all".equals(consumeDiscountDTO.getUseType())) {
            shopInfoService.update(new ShopInfo().setIsAccountPay(1), new QueryWrapper().eq(ShopInfo::getMainId, shopId));
        } else {
            if (consumeDiscountDTO.getShopIdList() != null) {
                shopInfoService.update(new ShopInfo().setIsAccountPay(1), new QueryWrapper().eq(ShopInfo::getMainId, shopId).in(ShopInfo::getId, consumeDiscountDTO.getShopIdList()));
                consumeCashback.setShopIdList(JSONArray.toJSONString(consumeDiscountDTO.getShopIdList()));
            }
        }

        shopConfigService.editStatusByShopIdList(shopId, consumeDiscountDTO.getIsEnable(), true, "is_account_pay",
                consumeDiscountDTO.getUseType(), consumeDiscountDTO.getShopIdList());

        if (consumeDiscountDTO.getCashbackStepList() != null && !consumeDiscountDTO.getCashbackStepList().isEmpty()) {
            consumeCashback.setCashbackStepList(JSONArray.toJSONString(consumeDiscountDTO.getCashbackStepList()));
        }
        return updateById(consumeCashback);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cashback(Long shopId, Long userId, BigDecimal amount, Long orderId, String orderNo) {
        AssertUtil.isTrue(amount == null || amount.compareTo(BigDecimal.ZERO) == 0, "金额必须大于0");
        Long mainShopId = shopInfoService.getMainIdByShopId(shopId);
        MkConsumeCashbackVO config = detail(mainShopId);
        if (config.getIsEnable() == 0) {
            log.info("消费返现未开启, {}", shopId);
            return;
        }
        ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getMainShopId, mainShopId).eq(ShopUser::getUserId, userId));
        if (StrUtil.isNotBlank(config.getApplicableUser()) && !"all".equals(config.getApplicableUser())) {
            if ("new".equals(config.getApplicableUser())) {
                boolean exists = orderInfoService.exists(new QueryWrapper().eq(OrderInfo::getUserId, shopUser.getUserId())
                        .eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()));
                if (exists) {
                    return;
                }
            } else if ("vip".equals(config.getApplicableUser()) && shopUser.getIsVip() != 1) {
                return;
            }
        }
        List<MkConsumeCashbackStep> cashbackStepList = config.getCashbackStepList();
        if (CollUtil.isNotEmpty(cashbackStepList)) {

            config.setCashbackStepList(cashbackStepList.stream().sorted(Comparator.comparing(MkConsumeCashbackStep::getAmount).reversed()).collect(Collectors.toList()));
            for (MkConsumeCashbackStep cashbackStep : config.getCashbackStepList()) {
                if (cashbackStep.getAmount().compareTo(amount) <= 0) {
                    BigDecimal cashbackAmount;
                    // 固定金额
                    if (TableValueConstant.MkConsumeCashback.CashbackType.FIX.getCode().equals(config.getCashbackType())) {
                        cashbackAmount = cashbackStep.getCashbackAmount();
                    } else {
                        cashbackAmount = amount.multiply(cashbackStep.getCashbackAmount().divide(bili, 2, RoundingMode.DOWN)).setScale(2, RoundingMode.DOWN);
                    }
                    if (cashbackAmount.compareTo(BigDecimal.ZERO) <= 0) {
                        return;
                    }
                    MkConsumeCashbackRecord mkConsumeCashbackRecord = new MkConsumeCashbackRecord().setOrderNo(orderNo).setOrderId(orderId)
                            .setMainShopId(mainShopId).setShopId(shopId).setAmount(amount)
                            .setCashbackAmount(cashbackAmount).setUserId(userId)
                            .setShopUserId(shopUser.getId());
                    consumeCashbackRecordService.save(mkConsumeCashbackRecord);
                    shopUserService.updateMoney(new ShopUserMoneyEditDTO().setId(shopUser.getId()).setType(1)
                            .setRelationId(mkConsumeCashbackRecord.getId()).setMoney(cashbackAmount).setBizEnum(ShopUserFlowBizEnum.CASHBACK)
                            .setRemark(StrUtil.format("订单消费: {}, 返现: {}", amount, cashbackAmount)));
                    log.info("订单返现 订单ID:{}, 店铺用户id: {}, 订单消费: {}, 返现: {}", orderId, shopUser.getId(), amount, cashbackAmount);

                    AcUserMsg msg = new AcUserMsg()
                            .setUserId(userId)
                            .setShopId(shopId)
                            .setSourceId(orderId)
                            .setSourceType("order")
                            .setType("cash")
                            .setTitle("消费返现到账")
                            .setContent(StrUtil.format("返现到账提醒: 你本次消费的{}元返现已存入账户，可直接用于消费，查收这份省钱福利", cashbackAmount));
                    acUserMsgService.addUserMsg(msg);
                    break;
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeCashback(Long shopId, Long userId, Long orderId, String orderNo) {
        MkConsumeCashbackRecord record = consumeCashbackRecordService.getOne(query()
                .eq(MkConsumeCashbackRecord::getShopId, shopId)
                .eq(MkConsumeCashbackRecord::getUserId, userId)
                .eq(MkConsumeCashbackRecord::getOrderNo, orderNo)
                .eq(MkConsumeCashbackRecord::getOrderId, orderId));
        if (record == null) {
            return;
        }
        MkConsumeCashbackRecord mkConsumeCashbackRecord = new MkConsumeCashbackRecord()
                .setOrderNo(orderNo)
                .setOrderId(orderId)
                .setMainShopId(record.getMainShopId())
                .setShopId(shopId)
                .setAmount(BigDecimal.ZERO)
                .setCashbackAmount(record.getCashbackAmount().negate())
                .setUserId(userId)
                .setShopUserId(record.getShopUserId());
        consumeCashbackRecordService.save(mkConsumeCashbackRecord);
        shopUserService.updateMoney(new ShopUserMoneyEditDTO()
                .setId(record.getShopUserId())
                .setType(0)
                .setRelationId(mkConsumeCashbackRecord.getId())
                .setMoney(record.getCashbackAmount())
                .setBizEnum(ShopUserFlowBizEnum.CASHBACK_REFUND)
                .setRemark(StrUtil.format("订单退款，扣除返现: {}", record.getCashbackAmount())));
        log.info("订单退款扣除返现 订单ID:{}, 店铺用户id: {},  扣除返现: {}", orderId, record.getShopUserId(), record.getCashbackAmount());

        AcUserMsg msg = new AcUserMsg()
                .setUserId(userId)
                .setShopId(shopId)
                .setSourceId(orderId)
                .setSourceType("order")
                .setType("cash")
                .setTitle("订单退款，消费返现扣除")
                .setContent(StrUtil.format("返现扣除提醒: 订单退款扣除的{}元返现。订单编号：{}", record.getCashbackAmount(), orderNo));
        acUserMsgService.addUserMsg(msg);
    }
}
