package com.ruoyi.bst.channel.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import com.ruoyi.bst.channel.domain.Channel;
import com.ruoyi.bst.channel.domain.ChannelQuery;
import com.ruoyi.bst.channel.domain.ChannelVO;
import com.ruoyi.bst.channel.domain.dto.ChannelPayQuery;
import com.ruoyi.bst.channel.domain.enums.ChannelApiType;
import com.ruoyi.bst.channel.domain.enums.ChannelBstType;
import com.ruoyi.bst.channel.domain.vo.ChannelNameVO;
import com.ruoyi.bst.channel.domain.vo.ChannelPaySubVO;
import com.ruoyi.bst.channel.domain.vo.ChannelPayVO;
import com.ruoyi.bst.channel.mapper.ChannelMapper;
import com.ruoyi.bst.channel.service.ChannelConverter;
import com.ruoyi.bst.channel.service.ChannelService;
import com.ruoyi.bst.creditUser.domain.CreditUserQuery;
import com.ruoyi.bst.creditUser.domain.CreditUserVO;
import com.ruoyi.bst.creditUser.service.CreditUserService;
import com.ruoyi.bst.order.domain.OrderVO;
import com.ruoyi.bst.order.service.OrderService;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;

/**
 * 充值渠道Service业务层处理
 *
 * @author ruoyi
 * @date 2024-04-15
 */
@Service
public class ChannelServiceImpl implements ChannelService
{
    @Autowired
    private ChannelMapper channelMapper;

    @Autowired
    private ChannelConverter channelConverter;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private CreditUserService creditUserService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private OrderService orderService;

    /**
     * 查询充值渠道
     *
     * @param channelId 充值渠道主键
     * @return 充值渠道
     */
    @Override
    public ChannelVO selectChannelByChannelId(Long channelId)
    {
        if (channelId == null) {
            return null;
        }
        return channelMapper.selectChannelByChannelId(channelId);
    }

    /**
     * 查询充值渠道列表
     *
     * @param smChannel 充值渠道
     * @return 充值渠道
     */
    @Override
    public List<ChannelVO> selectChannelList(ChannelQuery smChannel)
    {
        return channelMapper.selectChannelList(smChannel);
    }

    /**
     * 新增充值渠道
     *
     * @param channel 充值渠道
     * @return 结果
     */
    @Override
    public int insertChannel(Channel channel)
    {
        channel.setCreateTime(DateUtils.getNowDate());
        Integer result = transactionTemplate.execute(status -> {
            int insert = channelMapper.insertChannel(channel);

            if (insert == 1) {
                clearCache();
            }

            return insert;
        });

        return result == null ? 0 : result;
    }

    /**
     * 修改充值渠道
     *
     * @param channel 充值渠道
     * @return 结果
     */
    @Override
    public int updateChannel(Channel channel)
    {
        Integer result = transactionTemplate.execute(status -> {
            int update = channelMapper.updateChannel(channel);

            if (update == 1) {
                clearCache();
            }

            return update;
        });

        return result == null ? 0 :result;
    }

    @Override
    public List<ChannelVO> selectEnabledRechargeList(ChannelQuery query) {
        query.setEnabled(true);
        return this.selectChannelList(query);
    }

    /**
     * 查询充值渠道映射表
     *
     * @param query     查询条件
     * @param keyMapper 映射函数
     */
    @Override
    public <K> Map<K, ChannelVO> selectMap(ChannelQuery query, Function<? super Channel, ? extends K> keyMapper) {
        List<ChannelVO> list = this.selectChannelList(query);
        if (CollectionUtils.isEmptyElement(list)) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(keyMapper, item -> item));
    }

    @Override
    public int logicDel(List<Long> ids) {
        if (CollectionUtils.isEmptyElement(ids)) {
            return 0;
        }

        List<ChannelVO> channelList = this.selectByIds(ids);
        if (CollectionUtils.isEmpty(channelList)) {
            return 0;
        }

        // 校验
//        for (ChannelVO channel : channelList) {
//            ServiceUtil.assertion(ChannelType.SYSTEM.getType().equals(channel.getType()), "不允许删除系统预设渠道 \"%s\"}", channel.getName());
//        }

        int del = channelMapper.logicDel(ids);
        if (del > 0) {
            clearCache();
        }
        return del;
    }

    @Override
    public List<ChannelVO> selectByIds(List<Long> ids) {
        if (CollectionUtils.isEmptyElement(ids)) {
            return Collections.emptyList();
        }
        ChannelQuery query = new ChannelQuery();
        query.setChannelIds(ids);
        return this.selectChannelList(query);
    }

    @Override
    public List<ChannelNameVO> selectAllChannelNameList() {
        List<ChannelNameVO> list = redisCache.getCacheList(CacheConstants.CHANNEL_NAME_LIST);
        if (CollectionUtils.isEmpty(list)) {
            list = channelMapper.selectNameList(new ChannelQuery());
            if (CollectionUtils.isNotEmpty(list)) {
                redisCache.setCacheList(CacheConstants.CHANNEL_NAME_LIST, list);
            }
        }
        return list;
    }

    /**
     * 清除缓存
     */
    private void clearCache() {
        redisCache.deleteObject(CacheConstants.CHANNEL_NAME_LIST);
    }

    @Override
    public List<ChannelPayVO> selectPayChannelList(ChannelPayQuery query) {

        ChannelQuery channelQuery = new ChannelQuery();
        channelQuery.setEnabled(true);
        channelQuery.setAppId(query.getAppId());
        channelQuery.setChannelId(query.getChannelId());
        channelQuery.setExcludeApiType(query.getExcludeApiType());
        channelQuery.setBstType(query.getBstType());
        List<ChannelVO> channelList = this.selectChannelList(channelQuery);

        List<ChannelPayVO> result = channelList.stream().map(item -> {
            ChannelPayVO channelPayVO = new ChannelPayVO();
            channelPayVO.setId(item.getChannelId());
            channelPayVO.setName(item.getOutName());
            channelPayVO.setPicture(item.getPicture());
            channelPayVO.setApiType(item.getApiType());
            return channelPayVO;
        }).collect(Collectors.toList());

        // 根据apiType查询二级选项
        boolean hasCredit = result.stream().anyMatch(item -> {
            return ChannelApiType.CREDIT.getType().equals(item.getApiType());
        });

        if (hasCredit && query.getUserId() != null) {
            // 查询挂账选项
            CreditUserQuery creditQuery = new CreditUserQuery();
            creditQuery.setId(query.getSubId());
            creditQuery.setUserId(query.getUserId());
            creditQuery.setAreaId(query.getAreaId());
            List<CreditUserVO> creditUserList = creditUserService.selectCreditUserList(creditQuery);
            if (CollectionUtils.isEmptyElement(creditUserList)) {
                // 若挂账选项不存在，则移除挂账渠道
                result = result.stream()
                    .filter(item -> !ChannelApiType.CREDIT.getType().equals(item.getApiType()))
                    .collect(Collectors.toList());
            }
            result.stream().filter(item -> {
                return ChannelApiType.CREDIT.getType().equals(item.getApiType());
            }).forEach(item -> {
                item.setSubList(creditUserList.stream().map(creditUser -> {
                    ChannelPaySubVO channelPaySubVO = new ChannelPaySubVO();
                    channelPaySubVO.setId(creditUser.getId());
                    channelPaySubVO.setName(creditUser.getCreditName());
                    channelPaySubVO.setPicture(creditUser.getCreditLogo());
                    return channelPaySubVO;
                }).collect(Collectors.toList()));
            });
        } else {
            // 移除挂账渠道
            result = result.stream()
                .filter(item -> !ChannelApiType.CREDIT.getType().equals(item.getApiType()))
                .collect(Collectors.toList());
        }

        return result;
    }


    @Override
    public List<ChannelPayVO> getRideFeePayChannelList(Long orderId) {
        OrderVO order = orderService.selectOrderById(orderId);
        return getRideFeePayChannelList(order);
    }

    @Override
    public List<ChannelPayVO> getRideFeePayChannelList(OrderVO order) {
        ServiceUtil.assertion(order == null, "订单不存在");

        ChannelPayQuery query = new ChannelPayQuery();
        query.setAppId(order.getPayAppId());
        query.setAreaId(order.getAreaId());
        query.setUserId(order.getUserId());
        query.setBstType(ChannelBstType.ORDER_RIDE.getCode());

        // 若是挂账订单，则指定使用挂账的渠道
        boolean isCredit = order.getIsCredit() != null && order.getIsCredit();
        if (isCredit) {
            query.setChannelId(order.getPayChannelId());
            query.setSubId(order.getCreditUserId());
        }
        // 若不是挂账订单，则使用其他渠道，不允许使用挂账渠道
        else {
            query.setExcludeApiType(ChannelApiType.CREDIT.getType());
        }

        return this.selectPayChannelList(query);
    }

    @Override
    public List<ChannelPayVO> selectPayChannelList(Long userId, Long areaId, Long appId, String bstType) {
        ChannelPayQuery query = new ChannelPayQuery();
        query.setUserId(userId);
        query.setAreaId(areaId);
        query.setAppId(appId);
        query.setBstType(bstType);
        return this.selectPayChannelList(query);
    }

}
