package com.crm.activity.task;

import com.crm.activity.dao.mapper.ActivityRaceCalcMapper;
import com.crm.activity.enums.ActivityRaceType;
import com.crm.activity.service.ActivityRaceRankingService;
import com.crm.activity.service.ActivityRaceRuleService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.model.pojo.table.ActivityRaceRankingTable;
import com.crm.rely.backend.model.pojo.table.ActivityRaceRuleTable;
import com.crm.rely.backend.model.pojo.view.ActivityRaceCalcView;
import com.crm.rely.backend.util.DateUtil;
import com.crm.rely.backend.util.ListSplitUtil;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author y
 * @create 2022/7/21
 */
@Service
public class ActivityRaceTask {

    private final Logger logger = LoggerFactory.getLogger(ActivityRaceTask.class);

    @Autowired
    private ActivityRaceRuleService activityRaceRuleService;
    @Autowired
    private ActivityRaceCalcMapper activityRaceCalcMapper;
    @Autowired
    private ActivityRaceRankingService activityRaceRankingService;

    /**
     * 周比赛生成
     * 每周日0点生成周规则
     */
    @Transactional(rollbackFor = Exception.class)
    @Scheduled(cron = "10 0 0 ? * 7")
    public void generateWeeklyRule() throws Exception {
        try {
            Calendar calendar = Calendar.getInstance();
            //开始时间
            Date start = DateUtil.getPureDate(new Date());
            calendar.setTime(start);
            //截至时间
            calendar.add(Calendar.DATE, 5);
            calendar.add(Calendar.HOUR, 18);
            Date upTo = calendar.getTime();
            //结束时间
            calendar.setTime(start);
            calendar.add(Calendar.DATE, 7);
            Date end = calendar.getTime();
            //保存
            createRuleInfo(start, upTo, end, ActivityRaceType.WEEKLY.getCode());
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw e;
        }

    }

    /**
     * 月比赛生成
     * 每月1日生成月规则
     *
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @Scheduled(cron = "30 0 0 1 * ?")
    public void generateMonthlyRule() throws Exception {
        try {
            Calendar calendar = Calendar.getInstance();
            //开始时间
            calendar.setTime(DateUtil.getPureDate(new Date()));
            calendar.set(Calendar.DATE, 1);
            Date start = calendar.getTime();
            //截至时间
            calendar.add(Calendar.DATE, 24);
            Date upTo = calendar.getTime();
            //结束时间
            calendar.setTime(start);
            calendar.add(Calendar.MONTH, 1);
            Date end = calendar.getTime();
            //保存
            createRuleInfo(start, upTo, end, ActivityRaceType.MONTHLY.getCode());
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw e;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Scheduled(cron = "5 0 0 * * ?")
    public void calcProfit() throws Exception {
        try {
            //当前时间
            Date now = DateUtil.getPureDate(new Date());
            //获取周、月比赛规则
            List<ActivityRaceRuleTable> ruleTables = activityRaceRuleService.findAllCaleRule(now);
            //获取对应规则
            ActivityRaceRuleTable weeklyRule = null;
            ActivityRaceRuleTable monthlyRule = null;
            for (ActivityRaceRuleTable ruleTable : ruleTables) {
                if (ActivityRaceType.WEEKLY.getCode().equals(ruleTable.getRaceType()) && weeklyRule == null) {
                    weeklyRule = ruleTable;
                }
                if (ActivityRaceType.MONTHLY.getCode().equals(ruleTable.getRaceType()) && monthlyRule == null) {
                    monthlyRule = ruleTable;
                }
            }
            //计算对应规则盈利
            if (weeklyRule != null) {
                calcRuleProfit(weeklyRule);
            }

            if (monthlyRule != null) {
                calcRuleProfit(monthlyRule);
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw e;
        }
    }

    /**
     * 1.计算规则内的盈利信息
     * 2.保存信息
     * 3.重新排名
     *
     * @param ruleTable
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void calcRuleProfit(ActivityRaceRuleTable ruleTable) throws Exception {
        Long ruleId = ruleTable.getId();
        //获取规则内的出入金、净值信息
        List<ActivityRaceCalcView> views = getCalcViews(ruleId, Constants.MT4);
        if (CollectionUtils.isEmpty(views)) {
            return;
        }
        //获取对应排名信息
        Map<Long, ActivityRaceRankingTable> rankingMap = activityRaceRankingService.mapAllByRuleId(ruleId);
        //生成保存信息
        List<ActivityRaceRankingTable> tables = Lists.newArrayList();
        Date now = new Date();
        for (ActivityRaceCalcView view : views) {

            ActivityRaceRankingTable table = rankingMap.get(view.getCustomId());
            if (table == null) continue;
            table.setActive((view.getHasTrade() >= 1 || view.getHasOpen() >= 1) ? 1 : 0);
            table.setDw(view.getDw());
            table.setEndEquity(view.getEquity());
            table.setProfit(table.getEndEquity() - table.getStartEquity() + table.getManual() - table.getDw());
            table.setModifyTime(now);
            tables.add(table);
        }
        //重新排名
        tables = activityRaceRankingService.reOrderRanking(tables);
        //保存信息
        List<List<ActivityRaceRankingTable>> lists = ListSplitUtil.split(tables);
        for (List<ActivityRaceRankingTable> list : lists) {
            activityRaceRankingService.updateCalcResult(list);
        }
    }

    /**
     * 保存规则信息
     *
     * @param start 活动开始时间
     * @param upTo  活动截至时间
     * @param end   活动结束时间
     * @param type  活动类型
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    void createRuleInfo(Date start, Date upTo, Date end, Integer type) throws Exception {
        //判断是否已存在规则
        boolean exists = activityRaceRuleService.existsByDate(start, end, type);
        if (exists) return;
        //保存信息
        ActivityRaceRuleTable ruleTable = new ActivityRaceRuleTable();
        ruleTable.setAddTime(new Date());
        ruleTable.setSerial(activityRaceRuleService.getNextSerialByRaceType(type));
        ruleTable.setStartDate(start);
        ruleTable.setEndDate(end);
        ruleTable.setUpTo(upTo);
        ruleTable.setRaceType(type);
        activityRaceRuleService.saveTable(ruleTable);

    }

    List<ActivityRaceCalcView> getCalcViews(Long ruleId, String platform) {
        List<ActivityRaceCalcView> views = Lists.newArrayList();
        //账户及出入金信息
        List<ActivityRaceCalcView> accountViews = activityRaceCalcMapper.findAccountAndDwInfoByRuleId(ruleId, platform);
        if (!CollectionUtils.isEmpty(accountViews)) {
            views.addAll(accountViews);
        }
        //平仓信息
        List<ActivityRaceCalcView> tradeViews = activityRaceCalcMapper.findCloseTradeByRuleId(ruleId, platform);
        if (!CollectionUtils.isEmpty(tradeViews)) {
            for (ActivityRaceCalcView view : views) {
                for (ActivityRaceCalcView tradeView : tradeViews) {
                    if (view.getCustomId().equals(tradeView.getCustomId())) {
                        view.setHasTrade(tradeView.getHasTrade());
                        break;
                    }
                }
            }
        }
        //开仓信息
        List<ActivityRaceCalcView> openViews = activityRaceCalcMapper.findOpenTradeByRuleId(ruleId, platform);
        if (!CollectionUtils.isEmpty(openViews)) {
            for (ActivityRaceCalcView view : views) {
                for (ActivityRaceCalcView openView : openViews) {
                    if (view.getCustomId().equals(openView.getCustomId())) {
                        view.setHasOpen(openView.getHasOpen());
                        break;
                    }
                }
            }
        }

        return views;

    }

}
