package com.bizzan.bitrade.controller;

import com.bizzan.bitrade.constant.SysConstant;
import com.bizzan.bitrade.constant.TransactionType;
import com.bizzan.bitrade.constant.WalletType;
import com.bizzan.bitrade.engine.FollowAccountMonitor;
import com.bizzan.bitrade.engine.TradingAccountMonitor;
import com.bizzan.bitrade.entity.*;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.bizzan.bitrade.service.*;

import static com.bizzan.bitrade.constant.SysConstant.SESSION_MEMBER;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import com.bizzan.bitrade.util.DateUtil;
import com.bizzan.bitrade.util.MessageResult;
import com.bizzan.bitrade.util.RedisManager;
import com.bizzan.bitrade.vo.FollowWalletVo;
import com.bizzan.bitrade.vo.MemberFollowPosition;
import com.bizzan.bitrade.vo.TradingAccount;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Api(description="跟单钱包处理接口")
@RestController
@RequestMapping("/follow-wallet")
@Slf4j
public class FollowWalletController {
	@Autowired  
	private HttpSession session;
	@Autowired
    private MemberService memberService;
    @Autowired
    private MemberWalletService walletService;
    @Autowired
    private LocaleMessageSourceService msService;
    @Autowired
    private WalletTransRecordService walletTransRecordService;
    @Autowired
    private FollowWalletService followWalletService;
	@Autowired
    private FollowAccountMonitor followAccountMonitor;
    @Autowired
    private MemberHistoryService memberHistoryService;
    @Autowired
    private MemberTransactionService memberTransactionService;
    @Autowired
    private MemberContractPositionService memberContractPositionService;
    @Autowired
    private TradingAccountMonitor tradingAccountMonitor;
    @Autowired
	private SysConfigService sysConfigService;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
	private RedisLock redisLock;
    @Autowired
    private ExchangeWalletService exchangeWalletService;
    @Autowired
    private ExchangeFreezeHistoryService exchangeFreezeHistoryService;
    
    @ApiOperation(value="获取跟单钱包信息", notes="获取跟单钱包信息")
    @GetMapping("get")
    public MessageResult<FollowWalletVo> get(@SessionAttribute(SESSION_MEMBER) AuthMember authMember){
    	TradingAccount tradingAccount = tradingAccountMonitor.get(authMember.getId());
    	FollowWalletVo vo = new FollowWalletVo();
		vo.setId(authMember.getId());
		vo.setUsername(authMember.getName());
		FollowAccount followAccount = followAccountMonitor.get(authMember.getId());
		vo.setBalance(followAccount.getBalance());
		vo.setFrozenBalance(followAccount.getFrozenBalance());
		vo.setFrozenMargin(followAccount.getFrozenMargin());
		vo.setLeverage(followAccount.getLeverage());
		vo.setCurrentRevenue(followAccount.getCurrentRevenue());
		vo.setStaticBalance(followAccount.getStaticBalance());
		MemberWallet wallet = walletService.findByMemberId(authMember.getId());
		vo.setWalletBalance(wallet.getBalance());
		BigDecimal totalRevenue = memberHistoryService.sumFollowRevenueByMemberId(authMember.getId());
		List<Integer> types = new ArrayList<Integer>();
		types.add(TransactionType.FOLLOW_PROFIT.getOrdinal());
		types.add(TransactionType.FOLLOW_LOSS.getOrdinal());
		String[] todayStr = DateUtil.getTodayRealSartAndEndDateStr();
		totalRevenue = totalRevenue.add(memberTransactionService.sumAmountByMemberIdAndTypesAndTime(todayStr[0], todayStr[1], authMember.getId(), types));
		vo.setTotalRevenue(totalRevenue);
		vo.setAvailableBalance(followAccount.getAvailableBalance());
		vo.setCurrentCapital(followAccount.getCurrentCapital());
		vo.setRiskRate(followAccount.getRiskRate());
		vo.setRiskLevel(getRiskLevel(followAccount.getRiskRate()));
		vo.setCashBalance(vo.getCurrentCapital().add(vo.getWalletBalance()).add(tradingAccount.getCurrentCapital()));
		
		List<MemberFollowPosition> currentPositionList = new ArrayList<>();
		if(followAccount.getCurrentPositionList()!=null) {
			for(MemberContractPosition position: followAccount.getCurrentPositionList()) {
				MemberFollowPosition followPosition = new MemberFollowPosition();
				BeanUtils.copyProperties(position, followPosition);
				currentPositionList.add(followPosition);
				
				MemberContractPosition traderPosition = memberContractPositionService.findOne(position.getFollowPositionId());
				Member member = memberService.getMemberInfo(traderPosition.getMemberId());
				followPosition.setAvatar(member.getAvatar());
				followPosition.setNickname(member.getRealName());
			}
		}
		vo.setCurrentPositionList(currentPositionList);
		
		MessageResult<FollowWalletVo> mr = MessageResult.success("success");
		mr.setData(vo);
		return mr;
		
    }
    
    private String getRiskLevel(BigDecimal riskRate) {
    	if(riskRate.doubleValue() < 0.3)
			return "1";
		else if(riskRate.doubleValue() < 0.7)
			return "2";
		else
			return "3";
    }
    
    @ApiOperation(value="跟随特级", notes="跟随特级")
	@PostMapping("follow-special")
    public MessageResult followSpecialTrader(@SessionAttribute(SESSION_MEMBER) AuthMember authMember, BigDecimal amount) {
    	log.info("[follow-special] 接收参数: authMember.id={}, amount={}", authMember != null ? authMember.getId() : null, amount);
    	//boolean data = followWalletService.followSpecial(authMember.getId());
    	if(amount==null) {
    		amount = BigDecimal.valueOf(sysConfigService.get().getFollowSpecialAmount());
    	}
    	FollowAccount followAccount = followAccountMonitor.get(authMember.getId());
    	boolean data = followAccount.getCurrentCapital()
    			.compareTo(amount) >= 0;
    	MessageResult result = MessageResult.success("success");
    	result.setData(data);
    	log.info("[follow-special] 返回数据: code={}, message={}, data={}", result.getCode(), result.getMessage(), data);
        return result;
    }
    @ApiOperation(value="取消跟随特级", notes="取消跟随特级")
	@PostMapping("unfollow-special")
    public MessageResult unfollowSpecialTrader(@SessionAttribute(SESSION_MEMBER) AuthMember authMember) {
        //boolean data = followWalletService.unfollowSpecial(authMember.getId());
        boolean data = true;
        MessageResult result = MessageResult.success("success");
        result.setData(data);
        return result;
    }
    
    @ApiOperation(value="质押", notes="质押")
	@PostMapping("/m/add")
    public MessageResult followMTrader(@SessionAttribute(SESSION_MEMBER) AuthMember authMember, BigDecimal amount) {
    	if(amount==null) {
    		amount = BigDecimal.valueOf(sysConfigService.get().getFollowSpecialAmount());
    	}
    	ExchangeWallet platformWallet = exchangeWalletService.findPlatformWallet(authMember.getId());
    	if(platformWallet.getBalance().compareTo(amount) > 0) {
    		platformWallet.setBalance(platformWallet.getBalance().subtract(amount));
    		platformWallet.setToReleased(platformWallet.getToReleased().add(amount));
    		exchangeWalletService.save(platformWallet);
    		
    		ExchangeFreezeHistory exchangeFreezeHistory = new ExchangeFreezeHistory();
    		exchangeFreezeHistory.setMemberId(authMember.getId());
    		exchangeFreezeHistory.setAmount(amount);
    		exchangeFreezeHistory.setCoinId(platformWallet.getCoinId());
    		Calendar calendar = Calendar.getInstance();
    		calendar.add(Calendar.DATE, 90);
    		exchangeFreezeHistory.setUnfreezeTime(calendar.getTime());
    		exchangeFreezeHistoryService.save(exchangeFreezeHistory);
    	}
    	MessageResult result = MessageResult.success("success");
    	result.setData(true);
        return result;
    }
    
    @ApiOperation(value="获取质押信息", notes="获取质押信息")
	@GetMapping("/m/get")
    public MessageResult getMTrader(@SessionAttribute(SESSION_MEMBER) AuthMember authMember) {
    	FollowWallet followAccount = followWalletService.findOne(authMember.getId());
    	MessageResult result = MessageResult.success("success");
    	result.setData(followAccount);
        return result;
    }
    
	@ApiOperation(value="划入跟单账户", notes="划入跟单账户（通用划转接口在/uc下）")
	@ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "amount",value = "划转金额",required = true,paramType = "form",dataType = "float")
    })
	@PostMapping("transfer-in")
	public MessageResult transferIn(
            @RequestParam(value = "amount") BigDecimal amount) {
		AuthMember authMember = (AuthMember)session.getAttribute(SysConstant.SESSION_MEMBER);
		Member member = memberService.findOne(authMember.getId());
		if(member == null) {
            return MessageResult.error(msService.getMessage("REQUEST_OF_ILLEGAL"));
        }
		if(amount.compareTo(BigDecimal.ZERO) <= 0)
			return MessageResult.error(msService.getMessage("REQUEST_OF_ILLEGAL"));
		if(!redisLock.lockFollowAccount(member.getId()))
    		return MessageResult.error(msService.getMessage("TRANSFER_FAILED"));
		try {
			return followWalletService.transferInFromSpot(member.getId(), amount);
		} finally {
			redisLock.unlockFollowAccount(member.getId());
		}
	}
	
	@ApiOperation(value="划出跟单账户", notes="划出跟单账户（通用划转接口在/uc下）")
	@ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "amount",value = "划转金额",required = true,paramType = "form",dataType = "float")
    })
	@PostMapping("transfer-out")
	public MessageResult transferOut(
            @RequestParam(value = "amount") BigDecimal amount) {
		AuthMember authMember = (AuthMember)session.getAttribute(SysConstant.SESSION_MEMBER);
		Member member = memberService.findOne(authMember.getId());
		if(member == null) {
            return MessageResult.error(msService.getMessage("REQUEST_OF_ILLEGAL"));
        }
		if(amount.compareTo(BigDecimal.ZERO) <= 0)
			return MessageResult.error(msService.getMessage("REQUEST_OF_ILLEGAL"));
		if(!redisLock.lockFollowAccount(member.getId()))
    		return MessageResult.error(msService.getMessage("TRANSFER_FAILED"));
		try {
			return followWalletService.transferOutToSpot(member.getId(), amount);
		} finally {
			redisLock.unlockFollowAccount(member.getId());
		}
	}
    
}
