package com.crm.ucard.service.impl;

import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.PayConstant;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.dto.ucard.CardBlockchainConfigDto;
import com.crm.rely.backend.core.dto.ucard.CardBlockchainRateConfigDto;
import com.crm.rely.backend.core.entity.base.BaseDeleteEntities;
import com.crm.rely.backend.core.entity.ucard.*;
import com.crm.rely.backend.core.enums.CardBlockchainEnum;
import com.crm.rely.backend.core.pojo.table.ucard.CardBlockchainConfigTable;
import com.crm.rely.backend.core.pojo.table.ucard.CardBlockchainRateConfigTable;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.ucard.dao.mapper.CardBlockchainConfigMapper;
import com.crm.ucard.dao.mapper.CardBlockchainRateConfigMapper;
import com.crm.ucard.dao.repository.CardBlockchainConfigRepository;
import com.crm.ucard.dao.repository.CardBlockchainRateConfigRepository;
import com.crm.ucard.service.UcardBlockchainService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Slf4j
@Service
public class UcardBlockchainServiceImpl implements UcardBlockchainService {

    @Autowired
    private CardBlockchainConfigMapper blockchainConfigMapper;
    @Autowired
    private CardBlockchainConfigRepository blockchainConfigRepository;
    @Autowired
    private CardBlockchainRateConfigMapper blockchainRateConfigMapper;
    @Autowired
    private CardBlockchainRateConfigRepository blockchainRateConfigRepository;


    /**
     * 区块链配置列表
     */
    @Override
    public ResultWithPagerDto<CardBlockchainConfigDto> getCardBlockchainConfigPageList(CardBlockchainConfigPageEntity entity) throws ServiceException {
        try {
            // 获取总数
            Integer count = blockchainConfigMapper.countList(entity);
            PageDto pageDto = PageDto.format(entity, count);
            if (count == null || count <= 0) {
                return ResultWithPagerDto.success(pageDto);
            }
            List<CardBlockchainConfigDto> dtos = blockchainConfigMapper.pageList(entity);
            return ResultWithPagerDto.success(pageDto, dtos);
        } catch (Exception e) {
            log.error("获取区块链配置列表失败", e);
            throw new ServiceException("获取区块链配置列表失败");
        }
    }

    /**
     * 区块链配置下拉列表
     */
    @Override
    public BaseResultDto getCardBlockchainConfigDropdown(CardBlockchainConfigDropdownEntity entity) throws ServiceException {
        List<CardBlockchainConfigDto> dtos = new ArrayList<>();
        List<CardBlockchainConfigDto> configDtos = null;
        if ("2".equals(entity.getType()) && StringUtils.isNotEmpty(entity.getType())){
            configDtos = blockchainConfigMapper.findWithdrawalAllByEnableStatus();
        } else {
            configDtos = blockchainConfigMapper.findRechargeAllByEnableStatus();
        }
//        List<CardBlockchainConfigTable> tables = blockchainConfigRepository.findAllByEnableStatus(1);
        if (CollectionUtils.isNotEmpty(configDtos)) {
            for (CardBlockchainConfigDto dto : configDtos) {
                boolean shouldAdd = false;

                // 判断白名单
                if (StringUtils.isNotEmpty(dto.getWhitelist())) {
                    // 白名单不为空，检查入参id是否在白名单中
                    List<String> whitelist;
                    if (dto.getWhitelist().contains(",")) {
                        // 包含逗号，按逗号分割
                        whitelist = Arrays.asList(dto.getWhitelist().split(","));
                    } else {
                        // 不包含逗号，只有一个用户ID
                        whitelist = Collections.singletonList(dto.getWhitelist());
                    }
                    if (whitelist.contains(entity.getUniqueId())) {
                        shouldAdd = true;
                    }
                } else {
                    // 白名单为空，检查黑名单
                    if (StringUtils.isNotEmpty(dto.getBlacklist())) {
                        // 黑名单不为空，检查入参id是否在黑名单中
                        List<String> blacklist;
                        if (dto.getBlacklist().contains(",")) {
                            // 包含逗号，按逗号分割
                            blacklist = Arrays.asList(dto.getBlacklist().split(","));
                        } else {
                            // 不包含逗号，只有一个用户ID
                            blacklist = Collections.singletonList(dto.getBlacklist());
                        }
                        if (!blacklist.contains(entity.getUniqueId())) {
                            shouldAdd = true;
                        }
                    } else {
                        // 黑名单也为空，添加该数据
                        shouldAdd = true;
                    }
                }
                if (dto.getExchangeRate() == null){
                    shouldAdd = false;
                }

                // 如果符合条件，添加到结果中
                if (shouldAdd) {
                    CardBlockchainConfigDto configDto = new CardBlockchainConfigDto();
                    BeanUtils.copyProperties(dto, configDto);
                    dtos.add(configDto);
                }
            }
        }
        return BaseResultDto.success(dtos);
    }

    /**
     * 区块链下拉列表
     */
    @Override
    public BaseResultDto<List<String>> getCardBlockchainDropdown() throws ServiceException {
        List<String> list = CardBlockchainEnum.getAllBlockchains();
        return BaseResultDto.success(list);
    }

    /**
     * 新增区块链配置
     */
    @Override
    public BaseResultDto addCardBlockchainConfig(CardBlockchainConfigAddEntity entity) throws ServiceException {
        if (StringUtils.isNotEmpty(entity.getWhitelist()) && StringUtils.isNotEmpty(entity.getBlacklist())) {
            throw ServiceException.exception("白名单和黑名单不能同时存在");
        }
        blockchainConfigMapper.insert(entity);
        return BaseResultDto.success();
    }

    /**
     * 修改区块链配置
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto updateCardBlockchainConfig(CardBlockchainConfigUpdateEntity entity) throws ServiceException {
        if (StringUtils.isNotEmpty(entity.getWhitelist()) && StringUtils.isNotEmpty(entity.getBlacklist())) {
            throw ServiceException.exception("白名单和黑名单不能同时存在");
        }
        CardBlockchainConfigTable table = blockchainConfigRepository.findFirstById(entity.getId());
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        BeanUtils.copyProperties(entity, table);
        blockchainConfigRepository.save(table);
        return BaseResultDto.success();
    }

    /**
     * 批量删除区块链配置
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto deleteCardBlockchainConfig(BaseDeleteEntities entity) throws ServiceException {
        List<CardBlockchainConfigTable> tables = Lists.newArrayList();
        for (Long id : entity.getIds()) {
            CardBlockchainConfigTable table = new CardBlockchainConfigTable();
            table.setId(id);
            tables.add(table);
        }
        blockchainConfigRepository.deleteInBatch(tables);
        return BaseResultDto.success();
    }

    /**
     * 区块链汇率配置列表
     */
    @Override
    public ResultWithPagerDto<CardBlockchainRateConfigDto> getCardBlockchainRateConfigPageList(CardBlockchainRateConfigPageEntity entity) throws ServiceException {
        try {
            // 获取总数
            Integer count = blockchainRateConfigMapper.countList(entity);
            PageDto pageDto = PageDto.format(entity, count);
            if (count == null || count <= 0) {
                return ResultWithPagerDto.success(pageDto);
            }
            List<CardBlockchainRateConfigDto> dtos = blockchainRateConfigMapper.pageList(entity);
            return ResultWithPagerDto.success(pageDto, dtos);
        } catch (Exception e) {
            log.error("获取区块链配置列表失败", e);
            throw new ServiceException("获取区块链配置列表失败");
        }
    }

    /**
     * 新增区块链汇率配置
     */
    @Override
    public BaseResultDto addCardBlockchainRateConfig(CardBlockchainRateConfigAddEntity entity) throws ServiceException {
//        blockchainRateConfigMapper.insert(entity);
        existCurrency(entity.getCurrency(), entity.getConvertCurrency(), entity.getType());

        CardBlockchainRateConfigTable table = new CardBlockchainRateConfigTable();
        BeanUtils.copyProperties(entity, table);
        blockchainRateConfigRepository.save(table);
        return BaseResultDto.success();
    }

    /**
     * 修改区块链汇率配置
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto updateCardBlockchainRateConfig(CardBlockchainRateConfigUpdateEntity entity) throws ServiceException {
        CardBlockchainRateConfigTable table = blockchainRateConfigRepository.findFirstById(entity.getId());
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!entity.getCurrency().equals(table.getCurrency()) ||
                !entity.getConvertCurrency().equals(table.getConvertCurrency()) ||
                !entity.getType().equals(table.getType())) {
            existCurrency(entity.getCurrency(), entity.getConvertCurrency(), entity.getType());
        }
        BeanUtils.copyProperties(entity, table);
        blockchainRateConfigRepository.save(table);
        return BaseResultDto.success();
    }

    /**
     * 批量删除区块链汇率配置
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto deleteCardBlockchainRateConfig(BaseDeleteEntities entity) throws ServiceException {
        List<CardBlockchainRateConfigTable> tables = blockchainRateConfigRepository.findAllByIdIn(entity.getIds());
        if (tables == null || tables.size() <= 0) {
            return BaseResultDto.success();
        }
        blockchainRateConfigRepository.deleteInBatch(tables);
        return BaseResultDto.success();
    }


    private void existCurrency(String currency, String convertCurrency, Integer type) throws ServiceException {
        boolean bl = blockchainRateConfigRepository.existsByCurrencyAndConvertCurrencyAndType(currency, convertCurrency,
                type);
        if (bl) {
            throw ServiceException.exception(Constants.CURRENCY_EXIST_ERROR);
        }
    }


    @Override
    public BigDecimal getRate(String currency, String convertCurrency, Integer type) throws ServiceException {
        if (type == null) {
            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        BigDecimal rate = null;

        if (currency.equals(convertCurrency)) {
            return BigDecimal.ONE;
        }

        //先用转化货币和货币进行获取
        CardBlockchainRateConfigTable financeRateTable = blockchainRateConfigRepository.getByTypeAndCurrencyAndConvertCurrencyAndEnableStatus(type, convertCurrency, currency,1);
        //如果不存在 则根据货币和转换货币获取汇率
        if (financeRateTable == null) {
            financeRateTable = blockchainRateConfigRepository.getByTypeAndCurrencyAndConvertCurrencyAndEnableStatus(type, currency, convertCurrency,1);
            //如果不存在 则表示当前系统未设置此货币汇率
            if (financeRateTable == null) {
                if (type.equals(0)) {
                    throw new ServiceException(PayConstant.FINANCE_DEPOSIT_RATE_NOT_EMPTY);
                } else {
                    throw new ServiceException(PayConstant.FINANCE_WITHDRAW_RATE_NOT_EMPTY);
                }
            }
            int roundingMode = 1;

            if (type.equals(0)) {
                roundingMode = 0;
            }

            rate = BigDecimal.ONE.divide(financeRateTable.getExchangeRate(), 10, roundingMode);
        } else {
            rate = financeRateTable.getExchangeRate();
        }
        return rate;
    }

    @Override
    public BigDecimal getRateAmount(String currency, String transformCurrency, Integer type, BigDecimal amount) throws ServiceException {

        if (amount == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        BigDecimal rate = getRate(currency, transformCurrency, type);

        return amount.multiply(rate);
    }



}
