package com.m2pool.oapi.service.impl;

import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.dto.*;
import com.m2pool.oapi.entity.MinerState;
import com.m2pool.oapi.enums.PoolUnits;
import com.m2pool.oapi.mapper.AccountMapper;
import com.m2pool.oapi.service.AccountService;
import com.m2pool.oapi.utils.EnumUtils;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Date 2024/9/13 10:47
 * @Author 杜懿
 */
@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapperMapper;

    @Override
    public AjaxResult getHashRateReal(AccountVo vo) {

        PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
        if(StringUtils.isNull(unit)){
            return AjaxResult.error("coin error");
        }
        List<HashRateRealDto> list = accountMapperMapper.getAccountRealHashRateListByCoinAndAccount(vo);

        BigDecimal mhs = list.stream().map(e -> {
            return e.getMhs();
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal mhs24h = list.stream().map(e -> {
            return e.getMhs24h();
        }).reduce(BigDecimal.ZERO, BigDecimal::add);

        HashRateRealDto dto = new HashRateRealDto();
        dto.setUnit(unit.getUnit());
        dto.setMhs(mhs);
        dto.setMhs24h(mhs24h);
        return AjaxResult.success(dto);
    }

    @Override
    public AjaxResult getHashRateHistory(AccountDateVo vo) {
        System.out.println(vo);

        PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
        if(StringUtils.isNull(unit)){
            return AjaxResult.error("coin error");
        }

        Date today = new Date();
        today.setHours(0);
        today.setMinutes(0);
        today.setMinutes(0);

        Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        ca.setTime(today);
        ca.add(Calendar.MONTH,-3);

        Date firstDate = ca.getTime();

        if (StringUtils.isBlank(vo.getStart())){
            vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
        }else {
            if(DateUtils.parseDate(vo.getStart()).before(firstDate)){
                vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
            }else {
                //在三个月之内 不做处理
                try {
                    DateUtils.parseDate(vo.getStart());
                }catch (Exception e){
                    //出错说明格式错误有
                    return AjaxResult.error("start param error");
                }
            }
        }

        if (StringUtils.isNotBlank(vo.getEnd())){
            //在三个月之内 不做处理
            try {
                Date end = DateUtils.parseDate(vo.getEnd());
                if(end.before(DateUtils.parseDate(vo.getStart()))){
                    //end时间在start之前
                    return AjaxResult.error("end Date can not before start Date");
                }

                if(firstDate.before(end)){
                    return AjaxResult.error("end Date can not before "+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,firstDate));
                }
            }catch (Exception e){
                //出错说明格式错误有
                return AjaxResult.error("end param error");
            }
        }else {
            //没有end 则不做处理
        }

        List<HashRateDto> mhsList = accountMapperMapper.getAccountHashRateHistory24hListByCoinAndAccount(vo);
        HashRateHistory24hDto dto = new HashRateHistory24hDto();
        dto.setList(mhsList);
        dto.setUnit(unit.getUnit());
        return AjaxResult.success(dto);
    }

    @Override
    public AjaxResult getHashRateLast24h(AccountVo vo) {

        long t0 = System.currentTimeMillis();

        PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
        if(StringUtils.isNull(unit)){
            return AjaxResult.error("coin error");
        }

        Date today = new Date();

        Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        ca.setTime(today);
        ca.add(Calendar.DATE,-1);

        String start = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,ca.getTime());
        long t1 = System.currentTimeMillis();
        List<HashRateDto> list = accountMapperMapper.getAccountHashRateHistory30mListByCoinAndAccount(vo, start);
        long t2 = System.currentTimeMillis();
        HashRateHistory30mDto dto = new HashRateHistory30mDto();
        dto.setList(list);
        dto.setUnit(unit.getUnit());

        System.out.println("挖矿账户last24h业务 数据库查询耗时："+(t2-t1)+"ms,业务耗时"+(t2-t0)+"ms");
        return AjaxResult.success(dto);
    }

    @Override
    public AjaxResult getMinersList(AccountVo vo) {
        PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
        if(StringUtils.isNull(unit)){
            //防止coin注入异常数据
            return AjaxResult.error("coin error");
        }
        List<MinerState> list = accountMapperMapper.getMinerListByCoinAndAccount(vo);
        List<MinerStateDto> minerList = list.stream().map(e -> {
            MinerStateDto dto = new MinerStateDto();
            dto.setMiner(e.getMiner());
            if ("online".equals(e.getState().toLowerCase())) {
                dto.setState(0);
            } else if ("offline".equals(e.getState().toLowerCase())) {
                dto.setState(1);
            } else {
                dto.setState(2);
            }
            return dto;
        }).collect(Collectors.toList());

        MinerStateListDto minerStateListDto = new MinerStateListDto();
        minerStateListDto.setList(minerList);

        return AjaxResult.success(minerStateListDto);
    }

    @Override
    public AjaxResult getWatch(AccountVo vo) {
        PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
        if(StringUtils.isNull(unit)){
            //防止coin注入异常数据
            return AjaxResult.error("coin error");
        }
        MinerWatchDto dto = new MinerWatchDto();

        List<MinerState> list = accountMapperMapper.getMinerListByCoinAndAccount(vo);
        Map<String, Long> map = list.stream().collect(Collectors.groupingBy(
                MinerState::getState,
                Collectors.counting()
        ));

        long total = Convert.toLong(list.size(),0L);
        long online = map.getOrDefault("online", 0L);
        long offline = map.getOrDefault("offline", 0L);
        dto.setTotal(total);
        dto.setOnline(online);
        dto.setOffline(offline);
        dto.setTimeout(BigDecimal.valueOf(total)
                .subtract(BigDecimal.valueOf(online))
                .subtract(BigDecimal.valueOf(offline))
                .longValue());

        return AjaxResult.success(dto);
    }
}
