package com.bizzan.bitrade.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.bizzan.bitrade.constant.BooleanEnum;
import com.bizzan.bitrade.constant.NotifyType;
import com.bizzan.bitrade.constant.PageModel;
import com.bizzan.bitrade.constant.TransactionType;
import com.bizzan.bitrade.dao.MemberDao;
import com.bizzan.bitrade.dao.ExchangeWalletDao;
import com.bizzan.bitrade.entity.Coin;
import com.bizzan.bitrade.entity.ExchangeCoin;
import com.bizzan.bitrade.entity.Member;
import com.bizzan.bitrade.entity.MemberTransaction;
import com.bizzan.bitrade.entity.ExchangeWallet;
import com.bizzan.bitrade.entity.Order;
import com.bizzan.bitrade.entity.OtcCoin;
import com.bizzan.bitrade.entity.QMember;
import com.bizzan.bitrade.entity.QMemberWallet;
import com.bizzan.bitrade.es.ESUtils;
import com.bizzan.bitrade.exception.InformationExpiredException;
import com.bizzan.bitrade.service.Base.BaseService;
import com.bizzan.bitrade.util.BigDecimalUtils;
import com.bizzan.bitrade.util.MessageResult;
import com.bizzan.bitrade.util.RedisManager;
import com.bizzan.bitrade.vendor.provider.SMSProvider;
import com.bizzan.bitrade.vo.ExchangeAccount;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;

import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;

@Service
@Slf4j
public class ExchangeWalletService extends BaseService {

	@Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private ExchangeWalletDao exchangeWalletDao;
    @Autowired
    private ExchangeCoinService exchangeCoinService;
    @Autowired
    private MemberService memberService;
	@Autowired
	private RedisManager redisManager;
    
    public ExchangeWallet save(ExchangeWallet wallet) {
        return exchangeWalletDao.saveAndFlush(wallet);
    }

    /**
     * 获取钱包
     *
     * @param coin
     * @param memberId
     * @return
     */
    public ExchangeWallet findByCoinIdAndMemberId(String coin_id, long memberId) {
        return exchangeWalletDao.findByCoinIdAndMemberId(coin_id, memberId);
    }
    
    public ExchangeWallet findUsdtWallet(long memberId) {
        return exchangeWalletDao.findByCoinIdAndMemberId("USDT", memberId);
    }
    
    public ExchangeWallet findPlatformWallet(long memberId) {
    	ExchangeCoin platformCoin = exchangeCoinService.findPlatformCoin();
        return exchangeWalletDao.findByCoinIdAndMemberId(platformCoin.getCoinSymbol(), memberId);
    }
    
    @Transactional(rollbackFor = Exception.class)
	public void transferIn(Long id, BigDecimal amount) {
    	exchangeWalletDao.increaseBalance(id, amount);
	}
	@Transactional(rollbackFor = Exception.class)
	public boolean transferOut(Long id, BigDecimal amount) {
		return exchangeWalletDao.decreaseBalance(id, amount) > 0;
	}
	
	public List<ExchangeWallet> findWallets(long memberId) {
		return exchangeWalletDao.findAllByMemberId(memberId);
	}

	public List<Long> findAllMemberIds() {
		return exchangeWalletDao.findDistinctMemberIds();
	}

	public ExchangeAccount findExchangeAccountFromRedis(long memberId) {
		Object object = redisManager.getExchangeAccount(memberId);
		if(object != null) {
			//TradingAccount tradingAccount = (TradingAccount)redisManager.getTradingAccount(id);
			try {
				String jsonStr = object.toString();
				ExchangeAccount account = JSON.parseObject(jsonStr, ExchangeAccount.class);
				//log.info("tradingAccount1={}", tradingAccount);
				if(account!=null) {
					return account;
				}
			} catch (Exception e) {
				log.info("ExchangeAccount format error, memberId={}", memberId);
			}
		}
		ExchangeAccount account = this.findExchangeAccount(memberId);
		//log.info("tradingAccount3={}", JSON.toJSONString(tradingAccount));
		redisManager.saveExchangeAccount(memberId, JSON.toJSONString(account));
		return account;
    }
	
	public ExchangeAccount findExchangeAccount(long memberId) {
		ExchangeAccount account = new ExchangeAccount();
		List<ExchangeWallet> wallet = findWallets(memberId);
		account.setWallets(wallet);
		return account;
	}
	
	public void updateExchangeAccount(long memberId) {
		redisManager.removeExchangeAccount(memberId);
	}
	
	public void addCoinforAllMembers(String coinSymbol) {
		List<Member> members = memberService.findAll();
        for (Member member: members) {
        	ExchangeWallet exchangeWallet = new ExchangeWallet();
            exchangeWallet.setMemberId(member.getId());
            exchangeWallet.setCoinId(coinSymbol);
            exchangeWallet.setBalance(new BigDecimal(0));
            exchangeWallet.setFrozenBalance(new BigDecimal(0));
            exchangeWallet.setToReleased(new BigDecimal(0));
            exchangeWallet.setIsLock(0);
            exchangeWallet.setVersion(0);
            this.save(exchangeWallet);
        }
	}
}
