package com.bizzan.bitrade.engine;

import com.bizzan.bitrade.constant.NotifyType;
import com.bizzan.bitrade.entity.CloseType;
import com.bizzan.bitrade.entity.ContractCoin;
import com.bizzan.bitrade.entity.MemberContractPosition;
import com.bizzan.bitrade.service.ContractCoinService;
import com.bizzan.bitrade.service.MemberContractPositionService;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.service.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class FollowPositionMonitor {
	@Autowired
	private MemberContractPositionService memberContractPositionService;
	@Autowired
	private SysConfigService sysConfigService;
	@Autowired
    private ContractCoinMatchFactory contractCoinMatchFactory;
	@Autowired
	private MemberService memberService;
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    ContractCoinService contractCoinService;
	private static final String REDIS_PRICE_KEY = "NEW_COIN_PRICE:";
	
	private ConcurrentHashMap<Long, MemberContractPosition> positionMap = new ConcurrentHashMap<Long, MemberContractPosition>();
	
	private Map<String, BigDecimal> priceMapAtPresent = new HashMap<String, BigDecimal>();
	
	public void initPositions() {
		List<MemberContractPosition> positionList = memberContractPositionService.findCurrentFollowPositions();
		log.info("positionList={}", positionList);
		for(MemberContractPosition position: positionList) {
			this.addPosition(position);
		}
	}
	
	public void addPosition(MemberContractPosition position) {
		synchronized(positionMap) {
			positionMap.put(position.getId(), position);
		}
	}
	
	public void removePosition(MemberContractPosition position) {
		synchronized(positionMap) {
			positionMap.remove(position.getId());
		}
	}
	
	//@Scheduled(fixedDelay = 1500)
	public void checkBlast() {
		//log.info("currentPriceMap={}", currentPriceMap);
		List<ContractCoin> coinList = contractCoinService.findAllEnabled();
		for (ContractCoin coin : coinList) {
			Object priceObj = redisTemplate.opsForHash().get(REDIS_PRICE_KEY, coin.getId().toString());
			if (priceObj != null) { try { priceMapAtPresent.put(coin.getSymbol(), new BigDecimal(priceObj.toString())); } catch (Exception ignored) {} }
		}
		//log.info("priceMapAtPresent={}", priceMapAtPresent);
		int marginRate = sysConfigService.get().getContractMarginRate();
		
		synchronized(positionMap) {
			for(MemberContractPosition position:positionMap.values()) {
				position.setCurrentPrice(priceMapAtPresent.get(position.getCoin().getSymbol()));
				//log.info("checking blast memberID={}, currentCapital={}", tradingAccount.getId(), tradingAccount.getCurrentCapital());
				
				BigDecimal currentMargin = position.getCurrentMargin();
				double currentMarginRate = currentMargin.add(position.getCurrentProfit()).divide(currentMargin, 4, BigDecimal.ROUND_DOWN).doubleValue()*100;
				if(currentMarginRate<marginRate) {
					try {
						log.info("follow position blast, position={}", position);
						position.setCloseType(CloseType.BLAST);
						position.setBlastedAmount(BigDecimal.ZERO.subtract(position.getPrincipalAmount()));
						
						log.info("blasted amount={}", position.getBlastedAmount());
						contractCoinMatchFactory.getContractCoinMatch(position.getCoin().getSymbol()).dealAllCloseOrder(position);
						
						
						sendBlastEmail(position);
					} catch (Exception e) {
						log.error(e.getMessage(), e);
					}
				}
			}
		}
	}
	
	//@Scheduled(cron = "0 0 0 * * ?")
	public void collectOvernightFee() {
		log.info("start collecting overnight fee");
		
		log.info("end collecting overnight fee");
	}
	
	private void sendBlastEmail(MemberContractPosition position) {
		net.sf.json.JSONObject jsonObject = new net.sf.json.JSONObject();
		net.sf.json.JSONArray positionJsonArray = new net.sf.json.JSONArray();
		net.sf.json.JSONObject positionJsonObject = new net.sf.json.JSONObject();
		positionJsonObject.put("volume", position.getCurrentPosition());
		positionJsonObject.put("leverage", position.getLeverage());
		positionJsonObject.put("direction", position.getDirection().ordinal());
		positionJsonObject.put("contractName", position.getCoin().getSymbol());
		positionJsonArray.add(positionJsonObject);
		
		jsonObject.put("positions", positionJsonArray);
        
        log.info("jsonObject={}", jsonObject.toString());
        memberService.notifyByEmail(position.getMemberId(), NotifyType.BLAST, jsonObject);
	}
	
}
