package com.bytesw.bytebot.service.dashboard;

import com.bytesw.bytebot.bean.RangeBean;
import lombok.extern.log4j.Log4j2;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Log4j2
public abstract class DashboardService {

    abstract void completeData(OffsetDateTime startDate, OffsetDateTime endDate,
            Integer rangeMinutes, Map<String, Object> info);

    public Map<String, Object> generateInfo(Map<String, Object> params) {

        Map<String, Object> info = new HashMap<>();
        log.info(params);
        if (params == null) {
            return info;
        }

        OffsetDateTime startDate = convertToOffsetDatetime((String) params.get("startDate"));
        OffsetDateTime endDate = convertToOffsetDatetime((String) params.get("endDate"));
        Integer rangeMinutes = (Integer)params.get("rangeMinutes");

        if (startDate == null || endDate == null) {
            return info;
        }

        this.completeData(startDate, endDate, rangeMinutes, info);

        return info;
    }

    protected OffsetDateTime convertToOffsetDatetime(String date) {
        if (date.length() == 24) {
            date = date.substring(0, date.length() - 1);
        }
        OffsetDateTime dateOffset = null;
        try {
            LocalDateTime dateParsed = LocalDateTime.parse(date);
            dateOffset = OffsetDateTime.ofInstant(dateParsed.toInstant(ZoneOffset.UTC), ZoneId.systemDefault());
        } catch (Exception e) {
            log.warn(e);
        }
        return dateOffset;
    }

    protected OffsetDateTime getNextHour(OffsetDateTime date) {
        OffsetDateTime nextDate = date.plusHours(1);
        nextDate = nextDate.withMinute(0);
        nextDate = nextDate.withSecond(0);
        nextDate = nextDate.withNano(0);
        return nextDate;
    }

    protected OffsetDateTime getNextDay(OffsetDateTime date) {
        OffsetDateTime newDate = date.plusDays(1);
        newDate = newDate.withSecond(0);
        newDate = newDate.withMinute(0);
        newDate = newDate.withHour(0);
        newDate = newDate.withNano(0);
        return newDate;
    }

    protected OffsetDateTime getDayOnStart(OffsetDateTime date) {
        OffsetDateTime nextDate = date.withHour(12);
        nextDate = nextDate.withMinute(0);
        nextDate = nextDate.withSecond(0);
        nextDate = nextDate.withNano(0);
        return nextDate;
    }

    protected List<RangeBean> calculateMinutesRangeList(OffsetDateTime startDate, OffsetDateTime endDate, Integer range){
        List<RangeBean> rangeList = new ArrayList<>();
        OffsetDateTime nextRange = startDate.plusMinutes(range);
        OffsetDateTime startNextRange = startDate;
        while(nextRange.isBefore(endDate)){
            RangeBean rangeBean = new RangeBean();
            rangeBean.setStartDate(startNextRange);
            rangeBean.setEndDate(nextRange);
            rangeList.add(rangeBean);
            startNextRange = nextRange;
            nextRange = nextRange.plusMinutes(range);
        }
        RangeBean rangeBean = new RangeBean();
        rangeBean.setStartDate(startNextRange);
        rangeBean.setEndDate(endDate);
        rangeList.add(rangeBean);
        return rangeList;
    }

    protected List<RangeBean> calculateRangeList(OffsetDateTime startDate, OffsetDateTime endDate) {
        OffsetDateTime nextDate = getNextDay(startDate);
        OffsetDateTime startNextDate = startDate;
        List<RangeBean> rangeList = new ArrayList<>();
        while (nextDate.isBefore(endDate)) {
            RangeBean rangeBean = new RangeBean();
            rangeBean.setStartDate(startNextDate);
            rangeBean.setEndDate(nextDate);
            rangeList.add(rangeBean);
            startNextDate = nextDate;
            nextDate = getNextDay(nextDate);
        }

        RangeBean rangeBean = new RangeBean();
        rangeBean.setStartDate(startNextDate);
        rangeBean.setEndDate(endDate);
        rangeList.add(rangeBean);
        return rangeList;
    }
}
