package com.gxwebsoft.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.enums.ShopDealerCapitalUpdateEnum;
import com.gxwebsoft.common.core.enums.ShopDealerTypeEnum;
import com.gxwebsoft.common.core.utils.LoginUserUtil;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.common.system.redis.OrderNoUtils;
import com.gxwebsoft.shop.dto.ShopDealerRefundDto;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.mapper.ShopDealerCapitalMapper;
import com.gxwebsoft.shop.mapper.ShopDealerUserMapper;
import com.gxwebsoft.shop.mapper.ShopOrderMapper;
import com.gxwebsoft.shop.param.ShopDealerUserParam;
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
import com.gxwebsoft.shop.service.ShopDealerUserService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 分销商用户记录表Service实现
 *
 * @author 科技小王子
 * @since 2025-08-11 23:51:41
 */
@Service
@AllArgsConstructor
public class ShopDealerUserServiceImpl extends ServiceImpl<ShopDealerUserMapper, ShopDealerUser> implements ShopDealerUserService {

    private UserMapper userMapper;

    private OrderNoUtils orderNoUtils;

    private ShopDealerCapitalMapper shopDealerCapitalMapper;

    private ShopDealerCapitalService shopDealerCapitalService;

    private ShopOrderMapper shopOrderMapper;

    private static final int TENANT_ID = 10584;

    @Override
    public PageResult<ShopDealerUser> pageRel(ShopDealerUserParam param) {
        PageParam<ShopDealerUser, ShopDealerUserParam> page = new PageParam<>(param);
        page.setDefaultOrder("sort_number asc, create_time desc");
        List<ShopDealerUser> list = baseMapper.selectPageRel(page, param);
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public List<ShopDealerUser> listRel(ShopDealerUserParam param) {
        List<ShopDealerUser> list = baseMapper.selectListRel(param);
        // 排序
        PageParam<ShopDealerUser, ShopDealerUserParam> page = new PageParam<>();
        page.setDefaultOrder("sort_number asc, create_time desc");
        return page.sortRecords(list);
    }

    @Override
    public ShopDealerUser getByIdRel(Integer id) {
        ShopDealerUserParam param = new ShopDealerUserParam();
        param.setUserId(id);
        return param.getOne(baseMapper.selectListRel(param));
    }

  @Override
  public ShopDealerUser getByUserIdRel(Integer userId) {
    ShopDealerUserParam param = new ShopDealerUserParam();
    param.setUserId(userId);
    return param.getOne(baseMapper.selectListRel(param));
  }

  @Override
  public boolean updateByUserId(ShopDealerUser shopDealerUser) {
    final int update = baseMapper.update(shopDealerUser, new LambdaQueryWrapper<ShopDealerUser>().eq(ShopDealerUser::getUserId, shopDealerUser.getUserId()));
    return update > 0;
  }

    @Override
    @Transactional
    public Boolean reduceBalance(ShopDealerUserReduceDto entity) {
        //1.获取入参
        log.error("分销账户资金变更明细：" + entity);
        ShopDealerTypeEnum typeEnum = entity.getTypeEnum();
        ShopDealerCapitalUpdateEnum updateEnum = entity.getUpdateEnum();

        //2.变动类型为 1-操作冻结账户余额 2-操作提现账户余额【直接结算】是需判断金额值问题
        if(ShopDealerTypeEnum.FREEZE_ACCOUNT.equals(typeEnum) || ShopDealerTypeEnum.WITHDRAW_ACCOUNT.equals(typeEnum)){
            //查询分销用户信息
            ShopDealerUser dealerUser = getDealerUser(entity.getUserId());
            BigDecimal price = entity.getPrice();

            switch (updateEnum){
                case DISTRIBUTION_INCOME:
                case MANAGEMENT_INCOME:
                case DIVIDEND_INCOME:
                case PROMOTION_INCOME:
                case TRANSFER_INCOME:
                case DELIVERY_INCOME:{
                    break;
                }
                case WITHDRAW_PAYMENT:
                case TRANSFER_PAYMENT:
                case ORDER_REFUND:{
                    price.negate();
                    break;
                }
                default:{
                    throw new RuntimeException("暂不支持此类型！");
                }
            }

            String no = orderNoUtils.generate("C");
            //3.操作冻结账户余额
            if(ShopDealerTypeEnum.FREEZE_ACCOUNT.equals(typeEnum)){ //操作冻结账户余额
                //3.1 账户变更冻结金额
                dealerUser.setFreezeMoney(dealerUser.getFreezeMoney().add(price));
                dealerUser.setTotalMoney(dealerUser.getTotalMoney().add(price));
                baseMapper.updateById(dealerUser);

                //3.2 生成流水
                ShopDealerCapital dealerCapital = new ShopDealerCapital();
                dealerCapital.setNo(no);
                dealerCapital.setUserId(entity.getUserId());
                dealerCapital.setType(typeEnum.getCode());
                dealerCapital.setOrderNo(entity.getOrderNo());
                dealerCapital.setFlowType(updateEnum.getType());
                dealerCapital.setFreezeMoney(price);
                dealerCapital.setFreezeMoneyAfter(dealerUser.getFreezeMoney());
                dealerCapital.setMoneyAfter(dealerUser.getMoney());
                dealerCapital.setComments(updateEnum.getDescription());
                dealerCapital.setToUserId(entity.getOrderUserId());
                dealerCapital.setTenantId(TENANT_ID);
                dealerCapital.setCreateTime(LocalDateTime.now());
                User loginUser = LoginUserUtil.getLoginUser();
                if(loginUser != null){
                    dealerCapital.setCreator(loginUser.getUserId());
                }
                shopDealerCapitalMapper.insert(dealerCapital);
            }

            //4.操作提现账户余额【直接结算】
            else if(ShopDealerTypeEnum.WITHDRAW_ACCOUNT.equals(typeEnum)){
                //4.1 账户变更冻结金额
                dealerUser.setMoney(dealerUser.getMoney().add(price));
                dealerUser.setTotalMoney(dealerUser.getTotalMoney().add(price));
                baseMapper.updateById(dealerUser);


                //4.2 生成流水
                ShopDealerCapital dealerCapital = new ShopDealerCapital();
                dealerCapital.setNo(no);
                dealerCapital.setUserId(entity.getUserId());
                dealerCapital.setType(typeEnum.getCode());
                dealerCapital.setOrderNo(entity.getOrderNo());
                dealerCapital.setFlowType(updateEnum.getType());
                dealerCapital.setMoney(price);
                dealerCapital.setMoneyAfter(dealerUser.getMoney());
                dealerCapital.setFreezeMoneyAfter(dealerUser.getFreezeMoney());
                dealerCapital.setComments(updateEnum.getDescription());
                dealerCapital.setToUserId(entity.getOrderUserId());
                dealerCapital.setTenantId(TENANT_ID);
                dealerCapital.setCreateTime(LocalDateTime.now());
                User loginUser = LoginUserUtil.getLoginUser();
                if(loginUser != null){
                    dealerCapital.setCreator(loginUser.getUserId());
                }
                shopDealerCapitalMapper.insert(dealerCapital);
            }
        }

        //5.操作解冻业务【按订单号结算，可能一个订单号存在2笔待解冻金额】
        else if(ShopDealerTypeEnum.DEFROST.equals(typeEnum)){
            //5.1 判断是否为指定的解冻业务
            if(!ShopDealerCapitalUpdateEnum.FREEZE_MONEY_THAW.equals(entity.getUpdateEnum())){
                throw new RuntimeException("暂不支持此类型！");
            }

            //5.2 查询订单结算流水
            LambdaQueryWrapper<ShopDealerCapital> capitalLambdaQueryWrapper = new LambdaQueryWrapper<ShopDealerCapital>().eq(ShopDealerCapital::getOrderNo, entity.getOrderNo());
            List<ShopDealerCapital> dealerCapitalList = shopDealerCapitalMapper.selectList(capitalLambdaQueryWrapper);

            //5.3 根据用户遍历查询及执行解冻业务
            if(CollectionUtils.isNotEmpty(dealerCapitalList)){
                List<Integer> userIdList = dealerCapitalList.stream().map(ShopDealerCapital::getUserId).distinct().collect(Collectors.toList());
                List<ShopDealerUser> shopDealerUserList = lambdaQuery().in(ShopDealerUser::getUserId, userIdList).list();

                Map<Integer, List<ShopDealerCapital>> userCapitalMap = dealerCapitalList.stream().collect(Collectors.groupingBy(ShopDealerCapital::getUserId));
                userCapitalMap.forEach((k, value) ->{

                    //5.4 查询是否存在待解冻订单数据
                    ShopDealerCapital userCapital = value.stream().filter(capital -> ShopDealerTypeEnum.FREEZE_ACCOUNT.getCode().equals(capital.getType())).findFirst().orElse(null);
                    if(userCapital != null){

                        //5.5 查询此订单是否已结算
                        ShopDealerCapital alreadyCapital = value.stream().filter(capital -> ShopDealerTypeEnum.DEFROST.getCode().equals(capital.getType())).findFirst().orElse(null);
                        if(alreadyCapital == null){
                            ShopDealerUser dealerUser = shopDealerUserList.stream().filter(shopDealerUser -> k.equals(shopDealerUser.getUserId())).findFirst().orElse(null);

                            //5.6 判断分销账户分销金额是否大于解冻金额
                            BigDecimal freezeMoney = userCapital.getFreezeMoney();
                            if(dealerUser != null && dealerUser.getFreezeMoney().compareTo(freezeMoney) >= 0){
                                //5.7 账户解冻金额、可提现增加金额
                                dealerUser.setFreezeMoney(dealerUser.getFreezeMoney().subtract(freezeMoney));
                                dealerUser.setMoney(dealerUser.getMoney().add(freezeMoney));
                                baseMapper.updateById(dealerUser);

                                //5.8 生成流水
                                ShopDealerCapital dealerCapital = new ShopDealerCapital();
                                String no = orderNoUtils.generate("C");
                                dealerCapital.setNo(no);
                                dealerCapital.setUserId(k);
                                dealerCapital.setType(typeEnum.getCode());
                                dealerCapital.setOrderNo(entity.getOrderNo());
                                dealerCapital.setFlowType(updateEnum.getType());
                                dealerCapital.setFreezeMoney(freezeMoney.negate());
                                dealerCapital.setFreezeMoneyAfter(dealerUser.getFreezeMoney());
                                dealerCapital.setMoney(freezeMoney);
                                dealerCapital.setMoneyAfter(dealerUser.getMoney());
                                dealerCapital.setComments(updateEnum.getDescription());
                                dealerCapital.setToUserId(entity.getOrderUserId());
                                dealerCapital.setTenantId(TENANT_ID);
                                dealerCapital.setCreateTime(LocalDateTime.now());
                                User loginUser = LoginUserUtil.getLoginUser();
                                if (loginUser != null) {
                                    dealerCapital.setCreator(loginUser.getUserId());
                                }
                                shopDealerCapitalMapper.insert(dealerCapital);
                            }
                        }
                    }
                });
            }else {
                log.error("未查询到待解冻订单信息:" + entity.getOrderNo());
            }
        }else {
            throw new RuntimeException("暂不支持此变动类型业务！");
        }
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean refundOrder(ShopDealerRefundDto entity) {
        //1.查询订单分销数据
        List<ShopDealerCapital> dealerCapitalList = shopDealerCapitalMapper.selectList(
                new LambdaQueryWrapper<ShopDealerCapital>()
                        .eq(ShopDealerCapital::getTenantId, entity.getTenantId())
                        .eq(ShopDealerCapital::getOrderNo, entity.getOrderNo())
                        .in(ShopDealerCapital::getFlowType, Arrays.asList(ShopDealerCapitalUpdateEnum.DISTRIBUTION_INCOME.getType(),
                                ShopDealerCapitalUpdateEnum.MANAGEMENT_INCOME.getType(), ShopDealerCapitalUpdateEnum.DIVIDEND_INCOME.getType(),
                                ShopDealerCapitalUpdateEnum.PROMOTION_INCOME.getType(), ShopDealerCapitalUpdateEnum.FREEZE_MONEY_THAW.getType(),
                                ShopDealerCapitalUpdateEnum.DELIVERY_INCOME.getType()))
                        .isNotNull(ShopDealerCapital::getUserId)
        );

        if(CollectionUtils.isNotEmpty(dealerCapitalList)){
            //2.查询订单信息
            ShopOrder order = shopOrderMapper.selectOne(new LambdaQueryWrapper<ShopOrder>().select(ShopOrder::getOrderId, ShopOrder::getPayPrice, ShopOrder::getUserId)
                    .eq(ShopOrder::getOrderNo, entity.getOrderNo()));

            //3.订单不存在则回退
            if(order == null){
                throw new RuntimeException("退款查询订单信息失败！");
            }

            //4.订单实付金额为0则不执行退款业务
            if(order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0){
                return Boolean.TRUE;
            }

            //5.退款金额不能大于实付金额
            if(entity.getRefundAmount().compareTo(order.getPayPrice()) > 0){
                throw new RuntimeException("退款金额不能大于实付金额！");
            }

            //6.查询分销用户信息
            List<ShopDealerUser> shopDealerUserList = new ArrayList<>();
            List<Integer> userIdList = dealerCapitalList.stream().map(ShopDealerCapital::getUserId).distinct().collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(userIdList)){
                shopDealerUserList = lambdaQuery().in(ShopDealerUser::getUserId, userIdList).list();
            }

            //7.创建批量更新用户钱包、批量信息分销明细集合对象
            List<ShopDealerUser> shopDealerUserUpdateList = new ArrayList<>();
            List<ShopDealerCapital> newCapitalList = new ArrayList<>();

            //8.以用户分组，对结算订单进行业务操作
            Map<Integer, List<ShopDealerCapital>> userDealerMap = dealerCapitalList.stream().collect(Collectors.groupingBy(ShopDealerCapital::getUserId));

            //9.计算退款比率【退款金额/实付金额】
            BigDecimal rate = entity.getRefundAmount().divide(order.getPayPrice(), 3, RoundingMode.HALF_UP);;

            //10.遍历用户分销对象数据执行业务
            List<ShopDealerUser> finalShopDealerUserList = shopDealerUserList;
            BigDecimal finalRate = rate;
            userDealerMap.forEach((k, value) ->{
                BigDecimal money = value.stream().map(ShopDealerCapital::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add).multiply(finalRate);
                BigDecimal freezeMoney = value.stream().map(ShopDealerCapital::getFreezeMoney).reduce(BigDecimal.ZERO, BigDecimal::add).multiply(finalRate);

                ShopDealerUser dealerUser = finalShopDealerUserList.stream().filter(shopDealerUser -> k.equals(shopDealerUser.getUserId())).findFirst().orElse(null);
                if(dealerUser != null){
                    //11.修改分销用户账户信息
                    dealerUser.setMoney(dealerUser.getMoney().subtract(money));
                    dealerUser.setFreezeMoney(dealerUser.getFreezeMoney().subtract(freezeMoney));
                    dealerUser.setTotalMoney(dealerUser.getTotalMoney().subtract(money.add(freezeMoney)));
                    dealerUser.setUpdateTime(LocalDateTime.now());
                    shopDealerUserUpdateList.add(dealerUser);

                    //12.新增退单分销记录
                    ShopDealerCapital capital = new ShopDealerCapital();
                    String no = orderNoUtils.generate("R");
                    capital.setNo(no);
                    capital.setUserId(k);
                    capital.setType(ShopDealerTypeEnum.ORDER_REFUND.getCode());
                    capital.setOrderNo(entity.getOrderNo());
                    capital.setFlowType(ShopDealerCapitalUpdateEnum.ORDER_REFUND.getType());
                    capital.setMoney(money.negate());
                    capital.setMoneyAfter(dealerUser.getMoney());
                    capital.setFreezeMoney(freezeMoney.negate());
                    capital.setFreezeMoneyAfter(dealerUser.getFreezeMoney());
                    capital.setComments(ShopDealerCapitalUpdateEnum.ORDER_REFUND.getDescription());
                    capital.setToUserId(order.getUserId());
                    capital.setTenantId(entity.getTenantId());
                    User loginUser = LoginUserUtil.getLoginUser();
                    if(loginUser != null){
                        capital.setCreator(loginUser.getUserId());
                    }
                    capital.setCreateTime(LocalDateTime.now());
                    newCapitalList.add(capital);
                }
            });

            //13.批量修改分销用户钱包余额
            if(CollectionUtils.isNotEmpty(shopDealerUserUpdateList)){
                updateBatchById(shopDealerUserUpdateList);
            }

            //14.批量生成分销记录数据
            if(CollectionUtils.isNotEmpty(newCapitalList)){
                shopDealerCapitalService.saveBatch(newCapitalList);
            }
            return Boolean.TRUE;
        }else {
            return Boolean.TRUE;
        }
    }

    public ShopDealerUser getDealerUser(Integer userId){
        ShopDealerUser shopDealerUser = baseMapper.selectOne(new LambdaQueryWrapper<ShopDealerUser>().eq(ShopDealerUser::getUserId, userId));
        if(shopDealerUser == null){
            User user = userMapper.getById(userId);
            if(user == null){
                throw new RuntimeException("用户信息不存在！");
            }

            ShopDealerUser dealerUser = new ShopDealerUser();
            dealerUser.setType(0);
            dealerUser.setUserId(userId);
            dealerUser.setAvatar(user.getAvatar());
            dealerUser.setRealName(user.getRealName());
            dealerUser.setMobile(user.getMobile());
            dealerUser.setMoney(BigDecimal.ZERO);
            dealerUser.setFreezeMoney(BigDecimal.ZERO);
            dealerUser.setTotalMoney(BigDecimal.ZERO);
            dealerUser.setTenantId(TENANT_ID);
            dealerUser.setCreateTime(LocalDateTime.now());
            dealerUser.setDealerLevel(0);
            baseMapper.insert(dealerUser);

            shopDealerUser = dealerUser;
        }
        return shopDealerUser;
    }



}
