package com.ruoyi.ss.transactionBill.service.impl;

import com.github.pagehelper.PageHelper;
import com.ruoyi.common.enums.DesensitizedType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.bonus.domain.BonusQuery;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.channel.domain.Channel;
import com.ruoyi.ss.channel.domain.ChannelQuery;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.channel.service.ChannelService;
import com.ruoyi.ss.suit.domain.enums.SuitFeeType;
import com.ruoyi.ss.transactionBill.domain.enums.RechargeBillShowMobileStatus;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillOperatorVO;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.service.TransactionAssembler;
import com.ruoyi.ss.transactionBill.service.TransactionBillValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wjh
 * 2024/5/5
 */
@Service
public class TransactionAssemblerImpl implements TransactionAssembler {

    @Autowired
    private ChannelService channelService;

    @Autowired
    private BonusService bonusService;

    @Autowired
    private TransactionBillValidator transactionBillValidator;

    /**
     * 拼接渠道名称
     *
     * @param list
     */
    @Override
    public void assembleChannelName(List<TransactionBillVO> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        ChannelQuery query = new ChannelQuery();
        query.setChannelIds(list.stream().map(TransactionBillVO::getChannelId).filter(Objects::nonNull).distinct().collect(Collectors.toList()));
        Map<Long, ChannelVO> map = channelService.selectMap(query, Channel::getChannelId);

        for (TransactionBillVO bill : list) {
            Channel channel = map.get(bill.getChannelId());
            if (channel != null) {
                bill.setChannelName(channel.getName());
            }
        }
    }

    @Override
    public void assembleSuitSurplus(List<TransactionBillVO> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        for (TransactionBillVO bill : list) {
            // 充值时间
            if (SuitFeeType.rechargeTimeList().contains(bill.getSuitFeeType())) {
                LocalDateTime endTime = bill.getSuitEndTime() == null ? bill.getSuitExpireTime() : bill.getSuitEndTime();
                if (endTime == null) {
                    bill.setSuitSurplus(BigDecimal.ZERO);
                } else {
                    LocalDateTime now = LocalDateTime.now();
                    Duration between = Duration.between(now, endTime);
                    bill.setSuitSurplus(BigDecimal.valueOf(between.getSeconds()));
                }
            }
            // 充值时长
            else if (SuitFeeType.rechargeCountList().contains(bill.getSuitFeeType())) {
                BigDecimal endEle = bill.getSuitEndEle() == null ? bill.getDeviceTotalEle() : bill.getSuitEndEle();
                if (endEle == null) {
                    bill.setSuitSurplus(BigDecimal.ZERO);
                } else {
                    bill.setSuitSurplus(endEle.subtract(bill.getDeviceTotalEle()));
                }
            }
        }
    }

    @Override
    public void assembleBonusList(TransactionBillVO bill) {
        if (bill == null) {
            return;
        }
        this.assembleBonusList(Collections.singletonList(bill));
    }

    @Override
    public void assembleBonusList(List<TransactionBillVO> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        PageHelper.orderBy(" arrival_type desc");

        BonusQuery query = new BonusQuery();
        query.setBillIds(CollectionUtils.map(list, TransactionBillVO::getBillId));
        Map<Long, List<BonusVO>> group = bonusService.selectBonusList(query)
                .stream().collect(Collectors.groupingBy(BonusVO::getBillId));

        for (TransactionBillVO bill : list) {
            List<BonusVO> bonusList = group.get(bill.getBillId());
            if (CollectionUtils.isNotEmpty(bonusList)) {
                bill.setBonusList(bonusList);
            } else {
                bill.setBonusList(Collections.emptyList());
            }
        }
    }

    @Override
    public void assembleTotalUse(List<TransactionBillVO> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        for (TransactionBillVO bill : list) {
            if (bill == null) {
                continue;
            }
            if (SuitFeeType.rechargeTimeList().contains(bill.getSuitFeeType()) && bill.getSuitStartTime() != null && bill.getSuitEndTime() != null) {
                Duration between = Duration.between(bill.getSuitStartTime(), bill.getSuitEndTime());
                bill.setTotalUse(new BigDecimal(between.getSeconds()));
            } else if (SuitFeeType.rechargeCountList().contains(bill.getSuitFeeType()) && bill.getSuitStartEle() != null && bill.getSuitEndEle() != null) {
                bill.setTotalUse(bill.getSuitEndEle().subtract(bill.getSuitStartEle()));
            }
        }
    }

    @Override
    public void handleMchUserMobile(List<TransactionBillVO> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        for (TransactionBillVO bill : list) {
            if (bill == null) {
                continue;
            }
            boolean payed = RechargeBillShowMobileStatus.PAID.getStatus().equals(bill.getMchShowMobileStatus());    // 是否已经缴费
            // 若商户不需要显示手机号 或者 未缴费，则手机号脱敏
            if (bill.getMchShowMobile() == null || !bill.getMchShowMobile() || !payed) {
                if (StringUtils.hasText(bill.getUserMobile())) {
                    bill.setUserMobile(DesensitizedType.PHONE.desensitizer().apply(bill.getUserMobile()));
                }
            }
        }
    }

    @Override
    public void assembleOperator(List<TransactionBillVO> list, Long userId) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        for (TransactionBillVO bill : list) {
            TransactionBillOperatorVO vo = TransactionBillOperatorVO.defaultInstance();
            if (transactionBillValidator.canOperaOrder(bill, userId)) {
                vo.setRefund(true);
            }
            bill.setOperator(vo);
        }
    }

}
