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

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.valid.bank.BankCardInfo;
import com.ruoyi.common.valid.bank.BankValidUtils;
import com.ruoyi.ss.account.domain.Account;
import com.ruoyi.ss.account.domain.AccountQuery;
import com.ruoyi.ss.account.domain.AccountVO;
import com.ruoyi.ss.account.domain.enums.AccountType;
import com.ruoyi.ss.account.mapper.AccountMapper;
import com.ruoyi.ss.account.service.AccountAssembler;
import com.ruoyi.ss.account.service.AccountService;
import com.ruoyi.ss.channelWithdraw.domain.ChannelWithdrawVO;
import com.ruoyi.ss.channelWithdraw.service.ChannelWithdrawService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户账户Service业务层处理
 *
 * @author ruoyi
 * @date 2024-03-26
 */
@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountAssembler accountAssembler;

    @Autowired
    private ChannelWithdrawService channelWithdrawService;

    /**
     * 查询用户账户
     *
     * @param accountId 用户账户主键
     * @return 用户账户
     */
    @Override
    public AccountVO selectSmAccountByAccountId(Long accountId) {
        return accountMapper.selectSmAccountByAccountId(accountId);
    }

    /**
     * 查询用户账户列表
     *
     * @param dto 用户账户
     * @return 用户账户
     */
    @Override
    public List<AccountVO> selectSmAccountList(AccountQuery dto) {
        return accountMapper.selectSmAccountList(dto);
    }

    /**
     * 新增用户账户
     *
     * @param data 用户账户
     * @return 结果
     */
    @Override
    public int insertSmAccount(Account data) {
        // 查重
        ServiceUtil.assertion(isRepeat(data), "已绑定的账户不可重复绑定");

        // 银行卡校验
        if (AccountType.BANK_CARD.getType().equals(data.getAccountType())) {
            ServiceUtil.assertion(StringUtils.isAnyBlank(data.getAccountNo(), data.getName(), data.getIdCard()), "银行卡号、姓名、身份证不允许为空");
            // 银行卡三要素校验，并获取卡面信息
            BankCardInfo bankCardInfo = BankValidUtils.valid3Bank(data.getAccountNo(), data.getName(), data.getIdCard());
            data.setCardInfo(bankCardInfo);
        }

        data.setCreateTime(DateUtils.getNowDate());
        return accountMapper.insertSmAccount(data);
    }

    /**
     * 修改用户账户
     *
     * @param data 用户账户
     * @return 结果
     */
    @Override
    public int updateSmAccount(Account data) {
        // 查重
        ServiceUtil.assertion(isRepeat(data), "已绑定的账户不可重复绑定");

        // 银行卡校验
        if (AccountType.BANK_CARD.getType().equals(data.getAccountType())) {
            ServiceUtil.assertion(StringUtils.isAnyBlank(data.getAccountNo(), data.getName(), data.getIdCard()), "银行卡号、姓名、身份证不允许为空");
            // 银行卡三要素校验，并获取卡面信息
            BankCardInfo bankCardInfo = BankValidUtils.valid3Bank(data.getAccountNo(), data.getName(), data.getIdCard());
            data.setCardInfo(bankCardInfo);
        }

        return accountMapper.updateSmAccount(data);
    }

    /**
     * 批量删除用户账户
     *
     * @param accountIds 需要删除的用户账户主键
     * @return 结果
     */
    @Override
    public int deleteSmAccountByAccountIds(Long[] accountIds) {
        return accountMapper.deleteSmAccountByAccountIds(accountIds);
    }

    /**
     * 删除用户账户信息
     *
     * @param accountId 用户账户主键
     * @return 结果
     */
    @Override
    public int deleteSmAccountByAccountId(Long accountId) {
        return accountMapper.deleteSmAccountByAccountId(accountId);
    }

    @Override
    public Map<String, List<AccountVO>> selectSmAccountGroup(AccountQuery dto) {
        List<AccountVO> list = this.selectSmAccountList(dto);
        // 获取可用渠道，仅返回可用渠道
        Set<String> enabledChannel = channelWithdrawService.selectEnabledList()
                .stream().map(ChannelWithdrawVO::getAccountType).collect(Collectors.toSet());

        list.forEach(AccountVO::desensitization);
        Map<String, List<AccountVO>> map = new HashMap<>();
        if (enabledChannel.contains(AccountType.BANK_CARD.getType())) {
            map.put(AccountType.BANK_CARD.name(), list.stream()
                    .filter(item -> Objects.equals(AccountType.BANK_CARD.getType(), item.getAccountType())).collect(Collectors.toList()));
        }
        if (enabledChannel.contains(AccountType.WECHAT.getType())) {
            map.put(AccountType.WECHAT.name(), list.stream()
                    .filter(item -> Objects.equals(AccountType.WECHAT.getType(), item.getAccountType())).collect(Collectors.toList()));
        }
        if (enabledChannel.contains(AccountType.ALIPAY.getType())) {
            map.put(AccountType.ALIPAY.name(), list.stream()
                    .filter(item -> Objects.equals(AccountType.ALIPAY.getType(), item.getAccountType())).collect(Collectors.toList()));
        }
        if (enabledChannel.contains(AccountType.OFFLINE_IMAGE.getType())) {
            map.put(AccountType.OFFLINE_IMAGE.name(), list.stream()
                    .filter(item -> Objects.equals(AccountType.OFFLINE_IMAGE.getType(), item.getAccountType())).collect(Collectors.toList()));
        }

        return map;
    }

    /**
     * 判断用户是否有这个账号
     *
     * @param userId      用户id
     * @param accountNo   账号
     * @param accountType 账号类型
     */
    @Override
    public boolean validateUserHasAccount(Long userId, String accountNo, AccountType accountType) {
        if (userId == null || accountNo == null) {
            return false;
        }
        AccountVO account = accountMapper.selectByAccountNo(accountNo, accountType.getType());
        return account != null && account.getUserId() != null && account.getUserId().equals(userId);
    }

    @Override
    public AccountVO selectUserWxAccount(Long userId) {
        if (userId == null) {
            return null;
        }
        AccountQuery dto = new AccountQuery();
        dto.setUserId(userId);
        dto.setAccountType(AccountType.WECHAT.getType());
        List<AccountVO> list = accountMapper.selectSmAccountList(dto);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public AccountVO selectUseAliAccount(Long userId) {
        if (userId == null) {
            return null;
        }
        AccountQuery dto = new AccountQuery();
        dto.setUserId(userId);
        dto.setAccountType(AccountType.ALIPAY.getType());
        List<AccountVO> list = accountMapper.selectSmAccountList(dto);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public boolean setDefault(Long userId, Long accountId) {
        AccountVO account = accountMapper.selectSmAccountByAccountId(accountId);
        ServiceUtil.assertion(account == null, "账户不存在");
        ServiceUtil.assertion(!Objects.equals(account.getUserId(), userId), "该账户不是本用户的账户");

        int updateCount = accountMapper.setDefault(userId, accountId);
        ServiceUtil.assertion(updateCount == 0, "设置默认账户失败");
        return true;
    }

    @Override
    public AccountVO selectOne(AccountQuery query) {
        return accountMapper.selectOne(query);
    }

    @Override
    public List<AccountVO> selectByUserId(Long userId) {
        if (userId == null) {
            return Collections.emptyList();
        }
        AccountQuery query = new AccountQuery();
        query.setUserId(userId);
        return this.selectSmAccountList(query);
    }

    @Override
    public List<AccountVO> selectUserAccountByType(Long userId, String type) {
        AccountQuery query = new AccountQuery();
        query.setUserId(userId);
        query.setAccountType(type);
        return this.selectSmAccountList(query);
    }

    private boolean isRepeat(Account data) {
        AccountQuery dto = new AccountQuery();
        dto.setUserId(data.getUserId());
        dto.setAccountType(data.getAccountType());
        if (data.getAccountId() != null) {
            dto.setExcludeIds(Collections.singletonList(data.getAccountId()));
        }
        List<AccountVO> repeats = accountMapper.selectSmAccountList(dto);
        return !CollectionUtils.isEmpty(repeats);
    }
}
