package com.starry.admin.modules.custom.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.custom.mapper.PlayCustomUserInfoMapper;
import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity;
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
import com.starry.admin.modules.custom.module.vo.PlayCustomRankingQueryVo;
import com.starry.admin.modules.custom.module.vo.PlayCustomRankingReturnVo;
import com.starry.admin.modules.custom.module.vo.PlayCustomUserQueryVo;
import com.starry.admin.modules.custom.module.vo.PlayCustomUserReturnVo;
import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService;
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
import com.starry.admin.modules.order.service.impl.PlayOrderInfoServiceImpl;
import com.starry.admin.modules.personnel.service.IPlayBalanceDetailsInfoService;
import com.starry.common.utils.IdUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 顾客Service业务层处理
 *
 * @author admin
 * @since 2024-04-08
 */
@Slf4j
@Service
public class PlayCustomUserInfoServiceImpl extends ServiceImpl<PlayCustomUserInfoMapper, PlayCustomUserInfoEntity>
        implements
            IPlayCustomUserInfoService {
    @Resource
    private PlayCustomUserInfoMapper playCustomUserInfoMapper;

    @Resource
    private PlayOrderInfoServiceImpl playOrderInfoService;

    @Resource
    private IPlayBalanceDetailsInfoService playBalanceDetailsInfoService;

    @Resource
    private IPlayCustomLevelInfoService playCustomLevelInfoService;

    @Override
    public PlayCustomUserInfoEntity selectByOpenid(String openId) {
        LambdaQueryWrapper<PlayCustomUserInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getOpenid, openId);
        return this.baseMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public BigDecimal getCustomPaymentAmount(BigDecimal rechargeAmount, String customId) {
        // 根据顾客ID，查询顾客对应等级
        MPJLambdaWrapper<PlayCustomUserInfoEntity> lambdaQueryWrapper = new MPJLambdaWrapper<>();
        lambdaQueryWrapper.selectAll(PlayCustomLevelInfoEntity.class);
        lambdaQueryWrapper.leftJoin(PlayCustomLevelInfoEntity.class, PlayCustomLevelInfoEntity::getId,
                PlayCustomUserInfoEntity::getLevelId);
        lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getId, customId);
        PlayCustomLevelInfoEntity entity = this.baseMapper.selectJoinOne(PlayCustomLevelInfoEntity.class,
                lambdaQueryWrapper);
        if (entity == null) {
            log.error("未查询当前顾客的充值优惠金额，支付金额等于充值金额,rechargeAmount={},customId={}", rechargeAmount, customId);
            return rechargeAmount;
        }
        try {
            BigDecimal paymentAmount = BigDecimal.valueOf(entity.getDiscount())
                    .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).multiply(rechargeAmount);
            log.info("等级为{}的顾客{},充值{}元，实际应该支付{}元", entity.getName(), customId, rechargeAmount, paymentAmount);
            return paymentAmount;
        } catch (Exception e) {
            log.error("计算顾客充值优惠金额发生异常，支付金额等于充值金额,rechargeAmount={},customId={}", rechargeAmount, customId);
            return rechargeAmount;
        }
    }

    @Override
    public void customAccountBalanceRecharge(BigDecimal rechargeAmount, String customId, String orderId) {
        PlayCustomUserInfoEntity userInfo = this.selectById(customId);
        // 查询充值赠送金额（暂是设置为0）
        // 此处我想实现：超过50送5，超过100送10，200送20，300送30，400送40，500送50
        BigDecimal giftAmount = calculateGiftMoney(rechargeAmount);
        // 修改用户账户余额
        this.updateAccountBalanceById(customId, userInfo.getAccountBalance(),
                userInfo.getAccountBalance().add(rechargeAmount).add(giftAmount), "0", "充值",
                rechargeAmount.add(giftAmount), giftAmount, orderId);
    }

    private static BigDecimal calculateGiftMoney(BigDecimal rechargeAmount) {
        // 此处我想实现：超过50送5，超过100送10，200送20，300送30，400送40，500送50
        BigDecimal giftAmount = BigDecimal.ZERO;
        if (rechargeAmount.compareTo(new BigDecimal(50)) >= 0) {
            giftAmount = new BigDecimal(5);
        }
        if (rechargeAmount.compareTo(new BigDecimal(100)) >= 0) {
            giftAmount = new BigDecimal(10);
        }
        if (rechargeAmount.compareTo(new BigDecimal(200)) >= 0) {
            giftAmount = new BigDecimal(20);
        }
        if (rechargeAmount.compareTo(new BigDecimal(300)) >= 0) {
            giftAmount = new BigDecimal(30);
        }
        if (rechargeAmount.compareTo(new BigDecimal(400)) >= 0) {
            giftAmount = new BigDecimal(40);
        }
        if (rechargeAmount.compareTo(new BigDecimal(500)) >= 0) {
            giftAmount = new BigDecimal(50);
        }
        return giftAmount;
    }

    /**
     * 查询顾客
     *
     * @param id
     *            顾客主键
     * @return 顾客
     */
    @Override
    public PlayCustomUserInfoEntity selectById(String id) {
        PlayCustomUserInfoEntity entity = this.baseMapper.selectById(id);
        if (entity == null) {
            throw new CustomException("顾客不存在");
        }
        return entity;
    }

    @Override
    public IPage<PlayCustomRankingReturnVo> selectRankingByPage(PlayCustomRankingQueryVo vo) {
        MPJLambdaWrapper<PlayCustomUserInfoEntity> lambdaQueryWrapper = new MPJLambdaWrapper<>();
        lambdaQueryWrapper.selectCollection(PlayOrderInfoEntity.class, PlayCustomRankingReturnVo::getOrderInfos)
                .leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getPurchaserBy,
                        PlayCustomUserInfoEntity::getId);
        if (StrUtil.isNotBlank(vo.getId())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getId, vo.getId());
        }
        if (vo.getPurchaserTime() != null && vo.getPurchaserTime().size() == 2) {
            lambdaQueryWrapper.between(PlayOrderInfoEntity::getPurchaserTime, vo.getPurchaserTime().get(0),
                    vo.getPurchaserTime().get(1));
        }

        IPage<PlayCustomRankingReturnVo> page = this.baseMapper.selectJoinPage(
                new Page<>(vo.getPageNum(), vo.getPageSize()), PlayCustomRankingReturnVo.class, lambdaQueryWrapper);
        int index = 1;
        for (PlayCustomRankingReturnVo record : page.getRecords()) {
            record.setRankingIndex((vo.getPageNum() - 1) * vo.getPageSize() + index);
            if (vo.getPurchaserTime() != null && vo.getPurchaserTime().size() == 2) {
                record.setBeginPurchaserTime(vo.getPurchaserTime().get(0));
                record.setEndPurchaserTime(vo.getPurchaserTime().get(1));
            }
            BigDecimal orderTotalAmount = new BigDecimal("0");
            int orderContinueNumber = 0;
            int orderNumber = 0;
            for (PlayOrderInfoEntity orderInfo : record.getOrderInfos()) {
                if (orderInfo.getId() == null) {
                    continue;
                }
                if ("0".equals(orderInfo.getFirstOrder())) {
                    orderContinueNumber++;
                }
                orderNumber++;
                if (!"4".equals(orderInfo.getOrderStatus())) {
                    orderTotalAmount = orderTotalAmount.add(orderInfo.getFinalAmount());
                }
            }
            record.setOrderTotalAmount(orderTotalAmount);
            record.setOrderNumber(String.valueOf(orderNumber));
            record.setOrderContinueNumber(String.valueOf(orderContinueNumber));
            if (orderNumber != 0) {
                record.setOrderPrice(
                        String.valueOf(orderTotalAmount.divide(new BigDecimal(orderNumber), 2, RoundingMode.HALF_UP)));
            } else {
                record.setOrderPrice("0");
            }
            index++;
        }
        // 按照订单顺序进行排序
        page.setRecords(page.getRecords().stream()
                .sorted(Comparator.comparing(PlayCustomRankingReturnVo::getOrderNumber).reversed())
                .collect(Collectors.toList()));
        return page;
    }

    @Override
    public IPage<PlayCustomUserReturnVo> selectByPage(PlayCustomUserQueryVo vo) {
        MPJLambdaWrapper<PlayCustomUserInfoEntity> lambdaQueryWrapper = new MPJLambdaWrapper<>();
        lambdaQueryWrapper.selectAll(PlayCustomUserInfoEntity.class);
        lambdaQueryWrapper.selectAs(PlayCustomLevelInfoEntity::getName, "levelName");
        lambdaQueryWrapper.leftJoin(PlayCustomLevelInfoEntity.class, PlayCustomLevelInfoEntity::getId,
                PlayCustomUserInfoEntity::getLevelId);
        if (StrUtil.isNotBlank(vo.getId())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getId, vo.getId());
        }
        if (StrUtil.isNotBlank(vo.getNickname())) {
            lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getNickname, vo.getNickname());
        }
        if (StrUtil.isNotBlank(vo.getRemark())) {
            lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getRemark, vo.getRemark());
        }
        if (StrUtil.isNotBlank(vo.getWeiChatCode())) {
            lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getWeiChatCode, vo.getWeiChatCode());
        }
        if (StrUtil.isNotBlank(vo.getPhone())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getPhone, vo.getPhone());
        }
        if (StrUtil.isNotBlank(vo.getSex())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getSex, vo.getSex());
        }
        if (StrUtil.isNotBlank(vo.getLevelId())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getLevelId, vo.getLevelId());
        }
        if (StrUtil.isNotBlank(vo.getSubscribeState())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getSubscribeState, vo.getSubscribeState());
        }
        if (StrUtil.isNotBlank(vo.getBlacklistState())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getBlacklistState, vo.getBlacklistState());
        }
        if (StrUtil.isNotBlank(vo.getViolationState())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getViolationState, vo.getViolationState());
        }
        if (StrUtil.isNotBlank(vo.getPurchaseState())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getPurchaseState, vo.getPurchaseState());
        }
        if (StrUtil.isNotBlank(vo.getMobilePhoneState())) {
            lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getMobilePhoneState, vo.getMobilePhoneState());
        }
        if (vo.getRegistrationTime() != null && vo.getRegistrationTime().size() == 2) {
            lambdaQueryWrapper.between(PlayCustomUserInfoEntity::getRegistrationTime, vo.getRegistrationTime().get(0),
                    vo.getRegistrationTime().get(1));
        }
        if (vo.getFirstPurchaseTime() != null && vo.getFirstPurchaseTime().size() == 2) {
            lambdaQueryWrapper.between(PlayCustomUserInfoEntity::getFirstPurchaseTime, vo.getFirstPurchaseTime().get(0),
                    vo.getFirstPurchaseTime().get(1));
        }
        if (vo.getLastPurchaseTime() != null && vo.getLastPurchaseTime().size() == 2) {
            lambdaQueryWrapper.between(PlayCustomUserInfoEntity::getLastPurchaseTime, vo.getLastPurchaseTime().get(0),
                    vo.getLastPurchaseTime().get(1));
        }
        if (StrUtil.isNotBlank(vo.getSort())) {
            if ("levelId".equals(vo.getSort())) {
                lambdaQueryWrapper.orderByDesc(PlayCustomUserInfoEntity::getLevelId);
            }
            if ("accountBalance".equals(vo.getSort())) {
                lambdaQueryWrapper.orderByDesc(PlayCustomUserInfoEntity::getAccountBalance);
            }
            if ("lastPurchaseTime".equals(vo.getSort())) {
                lambdaQueryWrapper.orderByDesc(PlayCustomUserInfoEntity::getLastPurchaseTime);
            }
        }

        IPage<PlayCustomUserReturnVo> page = this.baseMapper.selectJoinPage(
                new Page<>(vo.getPageNum(), vo.getPageSize()), PlayCustomUserReturnVo.class, lambdaQueryWrapper);
        for (PlayCustomUserReturnVo record : page.getRecords()) {
            List<PlayOrderInfoEntity> orderInfoEntities = playOrderInfoService.list(Wrappers
                    .lambdaQuery(PlayOrderInfoEntity.class).eq(PlayOrderInfoEntity::getPurchaserBy, record.getId())
                    .in(PlayOrderInfoEntity::getPlaceType, "0", "2"));
            BigDecimal orderTotalAmount = new BigDecimal("0");
            for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) {
                orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount());
            }
            record.setOrderNumber(String.valueOf(orderInfoEntities.size()));
            record.setOrderTotalAmount(orderTotalAmount);
            if (!orderInfoEntities.isEmpty()) {
                record.setOrderPrice(String.valueOf(
                        orderTotalAmount.divide(new BigDecimal(orderInfoEntities.size()), 2, RoundingMode.HALF_UP)));
            } else {
                record.setProvince("0");
            }

        }
        return page;

    }

    /**
     * 新增顾客
     *
     * @param playCustomUserInfo
     *            顾客
     * @return 结果
     */
    @Override
    public boolean create(PlayCustomUserInfoEntity playCustomUserInfo) {
        if (StrUtil.isBlankIfStr(playCustomUserInfo.getId())) {
            playCustomUserInfo.setId(IdUtils.getUuid());
        }
        return save(playCustomUserInfo);
    }

    @Override
    public void updateTokenById(String id, String token) {
        PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity();
        entity.setToken(token);
        entity.setId(id);
        this.baseMapper.updateById(entity);
    }

    @Override
    public void updateAccountBalanceById(String id, BigDecimal accountBalance) {
        // 更新余额
        this.baseMapper.updateById(new PlayCustomUserInfoEntity(id, accountBalance));
    }

    @Override
    public void updateAccountBalanceById(String userId, BigDecimal balanceBeforeOperation,
            BigDecimal balanceAfterOperation, String operationType, String operationAction, BigDecimal balanceMoney,
            BigDecimal giftAmount, String orderId) {
        // 更新余额
        PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity();
        entity.setId(userId);
        entity.setAccountBalance(balanceAfterOperation);
        entity.setAccountState(balanceAfterOperation.compareTo(new BigDecimal(0)) > 0 ? "1" : "0");
        this.baseMapper.updateById(entity);
        // 记录余额变更记录
        playBalanceDetailsInfoService.insertBalanceDetailsInfo("1", userId, balanceBeforeOperation,
                balanceAfterOperation, operationType, operationAction, balanceMoney, giftAmount, orderId);
    }

    /**
     * 修改顾客
     *
     * @param playCustomUserInfo
     *            顾客
     * @return 结果
     */
    @Override
    public boolean update(PlayCustomUserInfoEntity playCustomUserInfo) {
        return updateById(playCustomUserInfo);
    }

    /**
     * 批量删除顾客
     *
     * @param ids
     *            需要删除的顾客主键
     * @return 结果
     */
    @Override
    public int deletePlayCustomUserInfoByIds(String[] ids) {
        return playCustomUserInfoMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除顾客信息
     *
     * @param id
     *            顾客主键
     * @return 结果
     */
    @Override
    public int deletePlayCustomUserInfoById(String id) {
        return playCustomUserInfoMapper.deleteById(id);
    }

    @Override
    public List<PlayCustomUserInfoEntity> simpleList() {
        LambdaQueryWrapper<PlayCustomUserInfoEntity> wrapper = Wrappers.lambdaQuery(PlayCustomUserInfoEntity.class);
        wrapper.orderByDesc(PlayCustomUserInfoEntity::getId).eq(PlayCustomUserInfoEntity::getDeleted, 0).select(
                PlayCustomUserInfoEntity::getAvatar, PlayCustomUserInfoEntity::getId,
                PlayCustomUserInfoEntity::getNickname, PlayCustomUserInfoEntity::getAvatar);
        return baseMapper.selectList(wrapper);
    }

    @Override
    public void handleOrderCompletion(PlayOrderInfoEntity entity) {
        if (entity == null || StrUtil.isBlank(entity.getPurchaserBy())) {
            return;
        }
        PlayCustomUserInfoEntity userInfo = playCustomUserInfoMapper.selectById(entity.getPurchaserBy());
        if (userInfo == null) {
            log.warn("handleOrderCompletion skipped, userId={} missing, orderId={}", entity.getPurchaserBy(), entity.getId());
            return;
        }

        BigDecimal finalAmount = Objects.requireNonNullElse(entity.getFinalAmount(), BigDecimal.ZERO);
        Date completionTime = resolveCompletionTime(entity.getOrderEndTime());

        int affected = playCustomUserInfoMapper.applyOrderCompletionUpdate(
                userInfo.getId(),
                finalAmount,
                completionTime,
                entity.getWeiChatCode());
        if (affected == 0) {
            log.warn("handleOrderCompletion update skipped for userId={}, orderId={}", userInfo.getId(), entity.getId());
            return;
        }

        PlayCustomUserInfoEntity latest = playCustomUserInfoMapper.selectById(userInfo.getId());
        if (latest == null) {
            return;
        }

        PlayCustomLevelInfoEntity matchedLevel = playCustomLevelInfoService
                .matchLevelByConsumption(latest.getTenantId(), latest.getAccumulatedConsumptionAmount());
        if (matchedLevel != null && !StrUtil.equals(matchedLevel.getId(), latest.getLevelId())) {
            this.update(Wrappers.<PlayCustomUserInfoEntity>lambdaUpdate()
                    .eq(PlayCustomUserInfoEntity::getId, latest.getId())
                    .set(PlayCustomUserInfoEntity::getLevelId, matchedLevel.getId()));
            log.info("顾客{}消费累计达到{}，自动调整等级为{}", latest.getId(), latest.getAccumulatedConsumptionAmount(), matchedLevel.getName());
        }
    }

    private Date resolveCompletionTime(LocalDateTime orderEndTime) {
        LocalDateTime time = orderEndTime != null ? orderEndTime : LocalDateTime.now();
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    @Override
    public void saveOrderInfo(PlayOrderInfoEntity entity) {
        String id = entity.getPurchaserBy();
        LambdaUpdateWrapper<PlayCustomUserInfoEntity> wrapper = Wrappers.lambdaUpdate(PlayCustomUserInfoEntity.class)
                .eq(PlayCustomUserInfoEntity::getId, id).set(PlayCustomUserInfoEntity::getLastPurchaseTime, new Date());
        PlayCustomUserInfoEntity userInfoEntity = selectById(id);
        if (Objects.isNull(userInfoEntity.getFirstPurchaseTime())) {
            wrapper.set(PlayCustomUserInfoEntity::getFirstPurchaseTime, new Date());
        }
        wrapper.set(PlayCustomUserInfoEntity::getWeiChatCode, entity.getWeiChatCode());
        this.update(wrapper);
    }
}
