package com.bytesw.bytebot.service.dashboard;

import com.bytesw.bytebot.bean.*;
import com.bytesw.bytebot.jdbc.ActionJDBCRepository;
import com.bytesw.bytebot.jdbc.MessageJDBCRepository;
import com.bytesw.xdf.sql.beans.Pagination;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Log4j2
@Service
public class CustomerInteractionDashboardService extends DashboardService {

    @Autowired
    private MessageJDBCRepository messageJDBCRepository;

    @Autowired
    private ActionJDBCRepository actionJDBCRepository;

    @Override
    protected void completeData(OffsetDateTime startDate, OffsetDateTime endDate, Integer rangeMinutes,Map<String, Object> info) {
        List<RangeBean> rangeList = calculateRangeList(startDate, endDate);
        info.put("sessionFlow", generateInteractionByCustomerData(startDate, endDate));
        info.put("summaryGoals", generateSummaryByGoals(startDate, endDate));
        info.put("intentAvgByCustomer", generateAverageIntentsByCustomer(rangeList));
        info.put("summaryIntents", generateSummaryMessageByIntent(rangeList,startDate,endDate));
    }


    private List<ActionSummaryByGoalBean> generateSummaryByGoals(OffsetDateTime startDate, OffsetDateTime endDate) {
        List<ActionSummaryByGoalBean> actionByGoalList;

        actionByGoalList = actionJDBCRepository.getSummaryByGoals(startDate, endDate);

        if (actionByGoalList == null) {
            actionByGoalList = new ArrayList<>();
        }
        return actionByGoalList;
    }

    private Map<String, List<Object>> generateSummaryMessageByIntent(List<RangeBean> rangeList,OffsetDateTime startDate, OffsetDateTime endDate) {
        List<MessageByIntentBean> total_list = messageJDBCRepository.countMessageByIntent(startDate,endDate);
        Map<String, List<Object>> data = new HashMap<>();
        rangeList.stream().forEach(x -> {
            List<String> identifiers = new ArrayList<>();
            List<MessageByIntentBean> list = messageJDBCRepository.countMessageByIntent(x.getStartDate(), x.getEndDate());
            list.stream().forEach(intentSummary -> {
                identifiers.add((intentSummary.getIdentifier()));
                if (!data.containsKey(intentSummary.getIdentifier())){
                    data.put(intentSummary.getIdentifier(), new ArrayList<>());
                }
                data.get(intentSummary.getIdentifier()).add(new Object[]{getDayOnStart(x.getStartDate()).toInstant().toEpochMilli()/1000, intentSummary.getCount()});
            });
            total_list.stream().forEach(intentSummary -> {
                if(!identifiers.contains(intentSummary.getIdentifier())){
                    if(!data.containsKey(intentSummary.getIdentifier())){
                        data.put(intentSummary.getIdentifier(),new ArrayList<>());
                    }
                    data.get(intentSummary.getIdentifier()).add(new Object[]{getDayOnStart(x.getStartDate()).toInstant().toEpochMilli()/1000, 0});
                }
            });
        });
        return data;
    }

    private List<Object[]> generateAverageIntentsByCustomer(List<RangeBean> rangeList) {
        List<Object[]> averageList = new ArrayList<>();
        rangeList.stream().forEach(x -> {
            LocalDateTime times = x.getStartDate().toLocalDateTime().plusHours(12);
            Long timestamp = Timestamp.valueOf(times).getTime();
            Double avg = messageJDBCRepository.avgIntentsByCustomerAndRange(x.getStartDate(), x.getEndDate());
            if(avg!=null){
                averageList.add(new Object[]{timestamp,avg});
            }
        });
        return averageList;
    }

    private double round(Double value) {
        BigDecimal bd = BigDecimal.valueOf(value);
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

    private Map<String, Map<String, Object>> generateInteractionByCustomerData(OffsetDateTime startDate, OffsetDateTime endDate) {
        Map<String, Map<String, Object>> data = new HashMap<>();
        data.put("intent", new HashMap<>());
        List<SummaryMessageByIntentBean> intentTopList = messageJDBCRepository.getSummaryByIntent(startDate, endDate);
        int totalIntents = messageJDBCRepository.countByIntentAndRange(startDate, endDate);

        if (intentTopList == null) {
            new ArrayList<>();
        }

        BigInteger result = intentTopList.stream()
                .map(SummaryMessageByIntentBean::getCount)
                .reduce(BigInteger.ZERO, BigInteger::add);

        SummaryMessageByIntentBean others = new SummaryMessageByIntentBean();
        others.setCount(new BigInteger(String.valueOf(totalIntents)).subtract(result));
        others.setId(0L);
        others.setIdentifier("others");

        if(others.getCount().intValue()>0){
            intentTopList.add(others);
        }
        data.get("intent").put("total", totalIntents);
        data.get("intent").put("topList", intentTopList);

        List<SummaryMessageBySentenceBean> sentenceTopList = messageJDBCRepository.getSummaryBySentence(startDate, endDate);
        int totalSentences = messageJDBCRepository.countBySentencesAndRange(startDate, endDate);

        if (sentenceTopList == null) {
            sentenceTopList = new ArrayList<>();
        }

        data.put("sentence", new HashMap<>());

        BigInteger resultSentence = sentenceTopList.stream()
                .map(SummaryMessageBySentenceBean::getCount)
                .reduce(BigInteger.ZERO, BigInteger::add);

        SummaryMessageBySentenceBean othersSentence = new SummaryMessageBySentenceBean();
        othersSentence.setCount(new BigInteger(String.valueOf(totalSentences)).subtract(resultSentence));
        othersSentence.setId(0L);
        othersSentence.setIdentifier("others");

        if(othersSentence.getCount().intValue()>0){
            sentenceTopList.add(othersSentence);
        }

        data.get("sentence").put("topList", sentenceTopList);
        data.get("sentence").put("total", totalSentences);

        return data;
    }

    public void getSummaryByIntentAndSentencePagination(Pagination<SummaryMessageBySentenceBean> pagination) {
        int total = messageJDBCRepository.countSummaryByIntentAndSentence(pagination);
        int totalPages = total / pagination.getItemsPerPage();
        if (total % pagination.getItemsPerPage() != 0) {
            totalPages++;
        }
        pagination.setTotalItems(total);
        pagination.setTotalPages(totalPages);
        List<SummaryMessageBySentenceBean> list = messageJDBCRepository.getSummaryByIntentAndSentence(pagination);
        list.stream().forEach(x -> {
            int customers = messageJDBCRepository.countCustomersBySentence(x.getSentence());
            x.setCustomerCount(BigInteger.valueOf(customers));
        });
        pagination.setData(list);
    }

    public void getSummaryBySentencePagination(Pagination<SummaryMessageBySentenceBean> pagination) {
        int total = messageJDBCRepository.countSummaryBySentence(pagination);
        int totalPages = total / pagination.getItemsPerPage();
        if (total % pagination.getItemsPerPage() != 0) {
            totalPages++;
        }
        pagination.setTotalItems(total);
        pagination.setTotalPages(totalPages);
        List<SummaryMessageBySentenceBean> list = messageJDBCRepository.getMessageBySentencePage(pagination);
        pagination.setData(list);
    }
}
