package com.copy.trade.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.copy.trade.constant.DogeApi;
import com.copy.trade.constant.RedisKey;
import com.copy.trade.dao.CustomerMapper;
import com.copy.trade.dao.FollowMapper;
import com.copy.trade.entity.dto.DogeAsset;
import com.copy.trade.entity.form.TraderQueryForm;
import com.copy.trade.entity.po.Customer;
import com.copy.trade.entity.po.Follow;
import com.copy.trade.entity.po.FollowConfig;
import com.copy.trade.entity.po.Position;
import com.copy.trade.entity.po.Tag;
import com.copy.trade.entity.po.TraderData;
import com.copy.trade.entity.vo.FollowerVo;
import com.copy.trade.entity.vo.MessageVo;
import com.copy.trade.entity.vo.TraderVo;
import com.copy.trade.entity.vo.YieldVo;
import com.copy.trade.enums.FollowConfigEnum;
import com.copy.trade.enums.FollowStatusEnum;
import com.copy.trade.enums.TraderEnum;
import com.copy.trade.service.*;
import com.copy.trade.util.DogeContractUtils;
import com.copy.trade.util.LocalDateUtils;
import com.copy.trade.util.RedisUtils;
import com.copy.trade.util.TraderConfiguration;
import com.copy.trade.util.WebAssert;

import springfox.documentation.schema.Collections;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author wz
 * @since 2022-11-08
 */
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements ICustomerService {

    @Value("${doge.host_inner}")
    private String dogeHost;

    @Value("${doge.host}")
    private String host;

    @Autowired
    private IFollowService followServiceImpl;

    @Autowired
    private ITraderTagService traderTagServiceImpl;

    @Autowired
    private ITraderDataService traderDataServiceImpl;
    
    @Autowired
    private ITraderSymbolService traderSymbolServiceImpl;
    
    @Autowired
    private IPositionService positionServiceImpl;
    
    @Autowired
    private IStatisticsDataService statisticsDataServiceImpl;
    
    @Autowired
    private ICustomerFollowSymbolService customerFollowSymbolServiceImpl;

    @Autowired
    private IFavoriteService favoriteServiceImpl;
    
    @Autowired
    private IFollowConfigService followConfigServiceImpl;
    
    @Autowired
    private KafkaTemplate kafkaTemplate;
    
    @Autowired
    private RedisUtils redisUtils;

    private final String avatar = "http://xinjiapo-74.oss-ap-southeast-1.aliyuncs.com/640181ee-b144-42f4-8cf4-92d961d15fa9.png";
    
    //private final BigDecimal APPLY_TRADER_MIN_ASSET = new BigDecimal("1000");
    
    private final Logger log = LoggerFactory.getLogger(CustomerServiceImpl.class);

    @Override
    public Boolean openAccount(AuthMember authMember) {
        //1.判断用户是否已经开户
        Customer customerDB = getByMemberId(authMember.getId());
        if(customerDB != null){
            return true;
        }
        //创建用户
        customerDB = new Customer();
        //初始化昵称
        customerDB.setNickname(""+authMember.getId());
        customerDB.setTrader(TraderEnum.NO_TRADER.getStatus());
        customerDB.setMemberId(authMember.getId());
        customerDB.setAutomaticUnfollow(true);
        FollowConfig followConfig = followConfigServiceImpl.getConfig(FollowConfigEnum.FOLLOW_DEFAULT_AVATAR_ADDRESS.getNameEn());
        String avatarAddress = (followConfig == null || StringUtils.isEmpty(followConfig.getConfigContent())) ? avatar : followConfig.getConfigContent();
        customerDB.setAvatar(avatarAddress);
        save(customerDB);
        return true;
    }

    @Override
    //@Cacheable(cacheNames = "customer")
    public Customer getByMemberId(Long memberId) {
        QueryWrapper<Customer> customerQueryWrapper = new QueryWrapper<>();
        customerQueryWrapper.eq("member_id",memberId);
        Customer customerDB = getOne(customerQueryWrapper);
        return customerDB;
    }

    @Override
    public Boolean applyTrade(AuthMember authMember) {
        return applyTrade(authMember, null);
    }

    @Override
    public Boolean applyTrade(AuthMember authMember, Map<String, String> requestHeaders) {
        //1.验证用户当前状态
        Customer customerDB = getByMemberId(authMember.getId());
        WebAssert.isNotNull(customerDB,"chk.copy-trade.null");
        Integer traderStatus = customerDB.getTrader();
        switch (TraderEnum.getTraderEnum(traderStatus)){
            case TRADER:
                WebAssert.throwException("chk.applyTrader.has.become");
                break;
            case APPLYING_TRADER:
                WebAssert.throwException("chk.applyTrader.reviewing");
                break;
        }
        //2.验证用户资产，需带 session/token 请求 doge
        BigDecimal balance = DogeContractUtils.asset(host + DogeApi.CONTRACT_ASSET_NEW, authMember.getId(), requestHeaders);
        WebAssert.isNotNull(balance,"5000");
        FollowConfig followConfig = followConfigServiceImpl.getConfig(FollowConfigEnum.APPLY_TRADER_MIN_ASSET.getNameEn());
        BigDecimal minAsset = (followConfig == null || StringUtils.isEmpty(followConfig.getConfigContent())) ? new BigDecimal("1000") : new BigDecimal(followConfig.getConfigContent());
        WebAssert.isTrue(balance.compareTo(minAsset) >= 0,"chk.applyTrader.balance.insufficient");
        //3.验证用户是否有跟随交易员
        QueryWrapper<Follow> followQueryWrapper = new QueryWrapper<>();
        followQueryWrapper.eq("customer_id", customerDB.getId())
                .eq("status", FollowStatusEnum.FOLLOWING.getStatus());
        List<Follow> followList = followServiceImpl.list(followQueryWrapper);
        WebAssert.isTrue(followList.size()==0,"chk.applyTrader.has.follow");
        //4.提交申请
        customerDB.setTrader(TraderEnum.APPLYING_TRADER.getStatus());
        updateById(customerDB);
        return true;
    }
    
    @Override
    @Transactional
    public Boolean cancelTrade(AuthMember authMember) {
    	//1.验证用户当前状态
    	Customer customerDB = getByMemberId(authMember.getId());
    	WebAssert.isNotNull(customerDB,"chk.copy-trade.null");
    	Integer traderStatus = customerDB.getTrader();
    	
    	//验证是否是交易员
    	WebAssert.isTrue(TraderEnum.TRADER.getStatus() == traderStatus, "chk.cancelTrader.not.trader");
    	Integer positionCount = positionServiceImpl.getPositionCount(customerDB.getId());
    	if(positionCount != null && positionCount > 0) {
    		WebAssert.isTrue(positionCount == 0, "chk.cancelTrader.has.position");
    	}
    	
    	// 修改用户表的字段
    	//customerDB.setTrader(TraderEnum.NO_TRADER.getStatus());
    	//customerDB.setTraderLevelId(null);
    	//customerDB.setTraderTime(null);
    	//updateById(customerDB);  updateById这一方法不能对字段置空.
        ((CustomerMapper) baseMapper).cancelTrader(customerDB.getId());

    	
    	//删除跟随表
    	Map<String, Object> followMap = new HashMap();
    	followMap.put("trader_id", customerDB.getId());
    	followServiceImpl.removeByMap(followMap);
    	//关注表
    	Map<String, Object> favoriteMap = new HashMap();
    	favoriteMap.put("trader_id", customerDB.getId());
    	favoriteServiceImpl.removeByMap(favoriteMap);
    	//交易员标签表
    	Map<String, Object> tagMap = new HashMap();
    	tagMap.put("trader_id", customerDB.getId());
    	traderTagServiceImpl.removeByMap(tagMap);
    	//交易员带单合约
    	Map<String, Object> traderSymbolMap = new HashMap();
    	traderSymbolMap.put("trader_id", customerDB.getId());
    	traderSymbolServiceImpl.removeByMap(traderSymbolMap);
    	//交易员统计数据
    	Map<String, Object> statisticsMap = new HashMap();
    	statisticsMap.put("customer_id", customerDB.getId());
    	statisticsDataServiceImpl.removeByMap(statisticsMap);
    	Map<String, Object> traderDataMap = new HashMap();
    	traderDataMap.put("trader_id", customerDB.getId());
    	traderDataServiceImpl.removeByMap(traderDataMap);
    	
    	
    	//用户跟随交易对
    	Map<String, Object> customerFollowSymbolMap = new HashMap();
    	customerFollowSymbolMap.put("trader_id", customerDB.getId());
    	customerFollowSymbolServiceImpl.removeByMap(customerFollowSymbolMap);
    	//可能还有未知的需要删除的
    	
    	JSONObject jsonObject = new JSONObject();
        jsonObject.put("memberId", customerDB.getMemberId());
        jsonObject.put("isTrader", 0);
        kafkaTemplate.send("trader-status-change", JSON.toJSONString(jsonObject));
    	
    	return true;
    }

    @Override
    public Page<TraderVo> traderList(TraderQueryForm traderQueryForm) {
        Page page = traderQueryForm.newFormPage();
        List<TraderVo> traderList = ((CustomerMapper)baseMapper).traderList(page,traderQueryForm);
        traderList.forEach(traderVo -> {
           Integer followCount = followServiceImpl.countByTrader(traderVo.getId());
	       
	       //当前跟单人数添加默认的
	       Integer defaultFollowCustomer = traderVo.getDefaultFollowCustomer() == null ? 0 : traderVo.getDefaultFollowCustomer();
	       traderVo.setFollowing(followCount + defaultFollowCustomer);
	       traderVo.setFollowCustomer((traderVo.getFollowCustomer() == null ? 0L : traderVo.getFollowCustomer()) + defaultFollowCustomer);
	       
           traderVo.setIsFollow(0);
           if(followServiceImpl.isFollow(traderQueryForm.getCustomerId(),traderVo.getId())){
               traderVo.setIsFollow(1);
           }
           
           FollowConfig followConfig = followConfigServiceImpl.getConfig(FollowConfigEnum.SPECIAL_TRADER_CODE.getNameEn());
           boolean isSpecialTrader = traderVo.getTraderLevelId() >= Integer.parseInt(followConfig.getConfigContent());
           traderVo.setSpecialTrader(isSpecialTrader);

           //查询标签
           List<Tag> taglist = traderTagServiceImpl.list(traderVo.getId());
           List<String> tags = new ArrayList<>();
           taglist.forEach(tag ->{
               tags.add(tag.getName());
           });
           traderVo.setTags(tags);
           List<YieldVo> yieldVoList = traderDataServiceImpl.yield14(traderVo.getId());
           traderVo.setYield14List(dayYield14Trans(yieldVoList,traderVo));
		
		   BigDecimal balance = DogeContractUtils.asset(host + DogeApi.CONTRACT_ASSET_NEW,traderVo.getMemberId());
		   traderVo.setMoneyStrength("≥5K"); 
		   if(balance.compareTo(new BigDecimal("5000")) < 0) { 
			   traderVo.setMoneyStrength("<5K"); 
		   }
			
           if(isSpecialTrader) {
        	   traderVo.setTags(TraderConfiguration.getSpecailTagList(traderVo.getMemberId(),traderVo.getTags()));
        	   traderVo.setNickname(TraderConfiguration.getSpecailName(traderVo.getMemberId(),traderVo.getNickname()));
        	   traderVo.setMinFollowAmount(traderVo.getMinFollowAmount() == null ? 2000L : traderVo.getMinFollowAmount());
           }
           traderVo.setTeamProfit14String(TraderConfiguration.getSpecialTraderAmoutString(traderVo.getTeamProfit14()));
       	   traderVo.setProfitAmountString(TraderConfiguration.getSpecialTraderAmoutString(traderVo.getProfitAmount()));
        });
        page.setRecords(traderList);
        return page;
    }

    @Override
    public Page<TraderVo> topTraderList(Integer pageNum, Integer pageSize, TraderQueryForm traderQueryForm) {
        Page page = new Page(pageNum, pageSize);
        List<TraderVo> traderList = ((CustomerMapper)baseMapper).topTraderList(page, traderQueryForm);
        traderList.forEach(traderVo -> {
            Integer followCount = followServiceImpl.countByTrader(traderVo.getId());
            Integer defaultFollowCustomer = traderVo.getDefaultFollowCustomer() == null ? 0 : traderVo.getDefaultFollowCustomer();
            traderVo.setFollowing(followCount + defaultFollowCustomer);
            traderVo.setFollowCustomer((traderVo.getFollowCustomer() == null ? 0L : traderVo.getFollowCustomer()) + defaultFollowCustomer);

            FollowConfig followConfig = followConfigServiceImpl.getConfig(FollowConfigEnum.SPECIAL_TRADER_CODE.getNameEn());
            boolean isSpecialTrader = traderVo.getTraderLevelId() >= Integer.parseInt(followConfig.getConfigContent());
            traderVo.setSpecialTrader(isSpecialTrader);

            List<Tag> taglist = traderTagServiceImpl.list(traderVo.getId());
            List<String> tags = new ArrayList<>();
            taglist.forEach(tag -> tags.add(tag.getName()));
            traderVo.setTags(tags);

            List<YieldVo> yieldVoList = traderDataServiceImpl.yield14(traderVo.getId());
            traderVo.setYield14List(dayYield14Trans(yieldVoList, traderVo));

            BigDecimal balance = DogeContractUtils.asset(dogeHost + DogeApi.CONTRACT_ASSET_NEW, traderVo.getMemberId());
            traderVo.setMoneyStrength("≥5K");
            if (balance.compareTo(new BigDecimal("5000")) < 0) {
                traderVo.setMoneyStrength("<5K");
            }

            if (isSpecialTrader) {
                traderVo.setTags(TraderConfiguration.getSpecailTagList(traderVo.getMemberId(), traderVo.getTags()));
                traderVo.setNickname(TraderConfiguration.getSpecailName(traderVo.getMemberId(), traderVo.getNickname()));
                traderVo.setMinFollowAmount(traderVo.getMinFollowAmount() == null ? 2000L : traderVo.getMinFollowAmount());
            }
            traderVo.setTeamProfit14String(TraderConfiguration.getSpecialTraderAmoutString(traderVo.getTeamProfit14()));
            traderVo.setProfitAmountString(TraderConfiguration.getSpecialTraderAmoutString(traderVo.getProfitAmount()));
        });
        page.setRecords(traderList);
        return page;
    }

    @Override
    public TraderVo traderInfo(Long customerId, Long traderId) {
        TraderVo traderVo = ((CustomerMapper) baseMapper).traderInfo(traderId);
        traderVo.setIsFavorite(0);
        traderVo.setIsFollow(0);
        if(favoriteServiceImpl.isFavorite(customerId,traderId)){
            traderVo.setIsFavorite(1);
        }
        if(followServiceImpl.isFollow(customerId, traderId)){
            traderVo.setIsFollow(1);
        }
        FollowConfig followConfig = followConfigServiceImpl.getConfig(FollowConfigEnum.SPECIAL_TRADER_CODE.getNameEn());
        boolean isSpecialTrader = traderVo.getTraderLevelId() >= Integer.parseInt(followConfig.getConfigContent());
        
        traderVo.setSpecialTrader(isSpecialTrader);
        List<Tag> taglist = traderTagServiceImpl.list(traderVo.getId());
        List<String> tags = new ArrayList<>();
        taglist.forEach(tag ->{
            tags.add(tag.getName());
        });
        traderVo.setTags(tags);
        List<YieldVo> yieldVoList = traderDataServiceImpl.yield14(traderVo.getId());
        traderVo.setYield14List(dayYield14Trans(yieldVoList,traderVo));
		
		BigDecimal balance = DogeContractUtils.asset(host + DogeApi.CONTRACT_ASSET_NEW,traderVo.getMemberId());
		traderVo.setMoneyStrength("≥5K"); 
		if(balance.compareTo(new BigDecimal("5000")) < 0) { 
			traderVo.setMoneyStrength("<5K"); 
		}
		traderVo.setFollowBalance(balance);
		
    	Calendar calendar = Calendar.getInstance();
    	calendar.setWeekDate(calendar.getWeekYear(), calendar.get(Calendar.WEEK_OF_YEAR), 1);
    	calendar.set(calendar.get(calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(calendar.DAY_OF_MONTH), 16, 00, 00);
    	Date startDate = calendar.getTime();
    	Date nowDate = new Date();
    	Position position = new Position();
    	position.setTraderId(traderId);
    	BigDecimal dividendFeeAll = positionServiceImpl.selectDividendFee(position);
    	position.setUpdatedTime(nowDate);
    	position.setCreatedTime(startDate);
    	BigDecimal dividendFee = positionServiceImpl.selectDividendFee(position);
    	traderVo.setTotalFollowProfit(dividendFeeAll);
    	traderVo.setCurrentClearedProfit(dividendFee);
    	
    	
    	//入住天数添加默认的
    	Integer defaultRegisterDays = traderVo.getDefaultRegisterDays() == null ? 0 : traderVo.getDefaultRegisterDays();
    	traderVo.setRegisterDays((traderVo.getRegisterDays() == null? 0 : traderVo.getRegisterDays()) + defaultRegisterDays);
    	
    	//当前跟单人数添加默认的
    	Integer defaultFollowCustomer = traderVo.getDefaultFollowCustomer() == null ? 0 : traderVo.getDefaultFollowCustomer();
    	traderVo.setFollowing(followServiceImpl.followerCount(traderId) + defaultFollowCustomer);
    	traderVo.setFollowCustomer((traderVo.getFollowCustomer() == null ? 0L : traderVo.getFollowCustomer()) + defaultFollowCustomer);
    	
    	if(isSpecialTrader) {
        	traderVo.setTags(TraderConfiguration.getSpecailTagList(traderVo.getMemberId(),traderVo.getTags()));
     	    traderVo.setNickname(TraderConfiguration.getSpecailName(traderVo.getMemberId(),traderVo.getNickname()));
        	traderVo.setMinFollowAmount(traderVo.getMinFollowAmount() == null ? 2000L : traderVo.getMinFollowAmount());
        }
    	traderVo.setTeamProfit14String(TraderConfiguration.getSpecialTraderAmoutString(traderVo.getTeamProfit14()));
    	traderVo.setProfitAmountString(TraderConfiguration.getSpecialTraderAmoutString(traderVo.getProfitAmount()));
        return traderVo;
    }

    @Override
    public TraderVo traderFollowInfo(Long traderId) {
        TraderVo traderVo = ((CustomerMapper) baseMapper).traderInfo(traderId);
        if(traderVo == null)
        	return null;
        Integer defaultFollowCustomer = traderVo.getDefaultFollowCustomer() == null ? 0 : traderVo.getDefaultFollowCustomer();
    	traderVo.setFollowing(followServiceImpl.followerCount(traderId) + defaultFollowCustomer);
    	traderVo.setFollowCustomer((traderVo.getFollowCustomer() == null ? 0L : traderVo.getFollowCustomer()) + defaultFollowCustomer);
        return traderVo;
    }
    
    
    public static String main(String[] args) {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	Calendar calendar = Calendar.getInstance();
    	calendar.setWeekDate(calendar.getWeekYear(), calendar.get(Calendar.WEEK_OF_YEAR) + 1, 1);
    	calendar.set(calendar.get(calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(calendar.DAY_OF_MONTH), 23, 59, 59);
    	System.out.println(sdf.format(calendar.getTime()));

    	return sdf.format(calendar.getTime());
    }
    
    private List<YieldVo> dayYield14Trans(List<YieldVo> list,TraderVo traderVo) {
    	FollowConfig followConfig = followConfigServiceImpl.getConfig(FollowConfigEnum.DAY_YEILD_14_IS_MULTIPLY_14.getNameEn());
        Boolean isMultiply14 = (followConfig != null && !StringUtils.isEmpty(followConfig.getConfigContent()) && "1".equals(followConfig.getConfigContent())) 
        		? true : false; 
        if(isMultiply14) {
        	traderVo.setDayYield14(traderVo.getDayYield14() == null ? new BigDecimal(0) : traderVo.getDayYield14().multiply(new BigDecimal(14)));
        	list.forEach(yieldVo -> {
        		yieldVo.setDayYield14(yieldVo.getDayYield14() == null ? new BigDecimal(0) : yieldVo.getDayYield14().multiply(new BigDecimal(14)));
        	});
        }
    	
    	return list;
    }
    
}
