package com.czg.service.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.czg.account.dto.ShopActivateDTO;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.entity.ShopActivate;
import com.czg.account.entity.ShopActivateCouponRecord;
import com.czg.account.entity.ShopCoupon;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.*;
import com.czg.enums.ShopUserFlowBizEnum;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.ShopActivateMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 活动 服务层实现。
 *
 * @author ww
 * @since 2025-02-17
 */
@Slf4j
@DubboService
public class ShopActivateServiceImpl extends ServiceImpl<ShopActivateMapper, ShopActivate> implements ShopActivateService {

    @Resource
    private ShopCouponService couponService;
    @Resource
    private ShopActivateCouponRecordService inRecordService;
    @Resource
    private ShopUserService shopUserService;
    @Resource
    private MemberPointsService pointsService;

    @Override
    public List<ShopActivateDTO> getList(Long shopId) {
        List<ShopActivateDTO> activateDtoS = queryChain().select()
                .eq(ShopActivate::getShopId, shopId == null ? StpKit.USER.getShopId() : shopId)
                .orderBy(ShopActivate::getAmount, true)
                .listAs(ShopActivateDTO.class);
        for (ShopActivateDTO activateDTO : activateDtoS) {
            if (StrUtil.isNotBlank(activateDTO.getCoupons())) {
                //组装优惠券
                activateDTO.setCouponList(getCoupons(activateDTO.getCoupons()));
            }
        }
        return activateDtoS;
    }

    @Override
    public Boolean add(ShopActivateDTO activateDTO) {
        ShopActivate shopActivate = new ShopActivate();
        BeanUtil.copyProperties(activateDTO, shopActivate);
        return save(shopActivate);
    }

    @Override
    public Boolean edit(ShopActivateDTO activateDTO) {
        ShopActivate shopActivate = new ShopActivate();
        BeanUtil.copyProperties(activateDTO, shopActivate);
        return updateById(shopActivate);
    }

    @Override
    public void giveActivate(ShopUser shopUser, BigDecimal memAmount, Long activateId, Long relationId) {
        if (activateId == null) {
            return;
        }
        ShopActivate activate = getById(activateId);
        if (ObjectUtil.isNull(activate)) {
            return;
        }
        //赠送优惠券
        if (activate.getIsGiftCoupon() == 1 && StrUtil.isNotBlank(activate.getCoupons())) {
            Map<Long, Integer> couponUseMap = JSONObject.parseObject(activate.getCoupons(), new TypeReference<>() {
            });
            Map<Long, ShopCoupon> couponMap = new HashMap<>();
            couponUseMap.forEach((couponId, giftNumber) -> {
                ShopCoupon shopCoupon;
                if (couponMap.containsKey(couponId)) {
                    shopCoupon = couponMap.get(couponId);
                } else {
                    shopCoupon = couponService.queryChain().select().eq(ShopCoupon::getId, couponId).one();
                    couponMap.put(couponId, shopCoupon);
                }
                if (shopCoupon != null && shopCoupon.getStatus().equals(1) && shopCoupon.getLeftNumber() > giftNumber) {
                    LocalDateTime start = LocalDateTime.now().with(LocalTime.MIN);
                    LocalDateTime end = null;
                    if ("fixed".equals(shopCoupon.getValidityType())) {
                        //固定时间
                        end = LocalDateTimeUtil.offset(start, shopCoupon.getValidDays(), ChronoUnit.DAYS).with(LocalTime.MAX);
                    } else if ("custom".equals(shopCoupon.getValidityType())) {
                        //自定义时间
                        start = shopCoupon.getValidStartTime();
                        end = shopCoupon.getValidEndTime();
                    }
                    List<ShopActivateCouponRecord> actGiveRecords = new ArrayList<>();
                    ShopActivateCouponRecord record = new ShopActivateCouponRecord();
                    record.setShopUserId(shopUser.getId());
                    record.setCouponId(shopCoupon.getId());
                    record.setShopId(shopUser.getShopId());
                    record.setSourceActId(activate.getId());
                    record.setSourceFlowId(relationId);
                    record.setUseStartTime(start);
                    record.setUseEndTime(end);
                    record.setSource("activate");
                    record.setName(shopCoupon.getTitle());
                    record.setCouponJson(getCouponJson(activate, shopCoupon));
                    if (shopCoupon.getType() == 1) {
                        record.setType(1);
                        record.setFullAmount(shopCoupon.getFullAmount());
                        record.setDiscountAmount(shopCoupon.getDiscountAmount());
                    } else if (shopCoupon.getType() == 2) {
                        record.setType(2);
                        record.setProId(shopCoupon.getProId());
                    }
                    for (int i = 0; i < giftNumber; i++) {
                        actGiveRecords.add(record);
                    }
                    inRecordService.saveBatch(actGiveRecords);
                    couponService.updateChain()
                            .set(ShopCoupon::getLeftNumber, shopCoupon.getLeftNumber() - giftNumber)
                            .eq(ShopCoupon::getId, shopCoupon.getId())
                            .update();
                }
            });
        }
        //赠送金额
        if (activate.getGiftAmount() != null && activate.getGiftAmount().compareTo(BigDecimal.ZERO) > 0) {
            ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
                    .setId(shopUser.getId())
                    .setMoney(activate.getGiftAmount())
                    .setType(1)
                    .setRemark("充值活动赠送")
                    .setRelationId(relationId)
                    .setBizEnum(ShopUserFlowBizEnum.AWARD_IN);
            //更新会员余额 并生成流水
            shopUserService.updateMoney(shopUser.getShopId(), shopUserMoneyEditDTO);
        }
        if (activate.getGiftPoints() != null && activate.getGiftPoints() > 0) {
            pointsService.addPoints(shopUser.getId(), activate.getGiftPoints(), "储值赠送积分", null);
        }
    }

    /**
     * 获取优惠券详细信息 目前仅返回 id 名称 剩余数量 赠送数量
     */
    private List<ShopCoupon> getCoupons(String couponJson) {
        Map<String, Integer> couponMap;
        try {
            couponMap = JSONObject.parseObject(couponJson, new TypeReference<>() {
            });
        } catch (Exception e) {
            return new ArrayList<>();
        }

        if (couponMap.isEmpty()) {
            return new ArrayList<>();
        }
        List<ShopCoupon> list = couponService.queryChain()
                .select(ShopCoupon::getId, ShopCoupon::getTitle, ShopCoupon::getLeftNumber)
                .in(ShopCoupon::getId, couponMap.keySet())
                .list();
        list.forEach(coupon -> coupon.setNumber(couponMap.get(coupon.getId().toString())));
        return list;
    }

    private String getCouponJson(ShopActivate activate, ShopCoupon tbShopCoupon) {
        JSONObject result = new JSONObject();
        result.put("activate", JSONObject.toJSONString(activate));
        result.put("coupon", JSONObject.toJSONString(tbShopCoupon));
        return result.toJSONString();
    }
}
