package com.bytesw.bytebot.jdbc;

import com.bytesw.bytebot.bean.MessageByIntentBean;
import com.bytesw.bytebot.bean.SummaryMessageByIntentBean;
import com.bytesw.bytebot.bean.SummaryMessageBySentenceBean;
import com.bytesw.xdf.sql.beans.Pagination;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class MessageJDBCRepository {

    @Autowired
    @Qualifier("sqlSessionFactory")
    private SqlSessionFactory sqlSessionFactory;

    public int countSessionInRange(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countMessagesInRange", params);
        } finally {
            session.close();
        }
    }

    public int countMessageInRangeHour(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countMessagesInRangeForHour", params);
        } finally {
            session.close();
        }
    }

    public List<SummaryMessageBySentenceBean> getSummaryByIntentAndSentence(Pagination<SummaryMessageBySentenceBean> pagination) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("initLimit", pagination.getCurrentPage() * pagination.getItemsPerPage());
            params.put("itemsForPage", pagination.getItemsPerPage());
            if (pagination.getSortFields() != null && pagination.getSortFields().length > 0) {
                params.put("columnSort", pagination.getSortFields()[0].getField());
                params.put("directionSort", pagination.getSortFields()[0].getDirection().toUpperCase());
            } else {
                params.put("columnSort", "count");
                params.put("directionSort", "DESC");
            }
            completeDates(params, pagination.getFilterExpression());
            return session.selectList("com.bytesw.bytebot.dao.jdbc.MessageMapper.getSummaryByIntentAndSentence", params);
        } finally {
            session.close();
        }
    }

    public List<SummaryMessageByIntentBean> getSummaryByIntent(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectList("com.bytesw.bytebot.dao.jdbc.MessageMapper.getSummaryByIntent", params);
        } finally {
            session.close();
        }
    }

    /**
     * Metodo que consulta el total de mensajes con intent asociado
     * @return
     */
    public int countByIntentAndRange(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countByIntentAndRange", params);
        } finally {
            session.close();
        }
    }


    /**
     * Metodo que consulta el total de frases sin intent asociado
     * @return
     */
    public int countBySentencesAndRange(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countBySentencesAndRange", params);
        } finally {
            session.close();
        }
    }

    public List<SummaryMessageBySentenceBean> getSummaryBySentence(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            params.put("initLimit", 0);
            params.put("itemsForPage", 4);
            params.put("columnSort", "count");
            params.put("directionSort", "DESC");
            return session.selectList("com.bytesw.bytebot.dao.jdbc.MessageMapper.getSummaryBySentence", params);
        } finally {
            session.close();
        }
    }

    public List<SummaryMessageBySentenceBean> getMessageBySentencePage(Pagination<SummaryMessageBySentenceBean> pagination) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("initLimit", pagination.getCurrentPage() * pagination.getItemsPerPage());
            params.put("itemsForPage", pagination.getItemsPerPage());
            if (pagination.getSortFields() != null && pagination.getSortFields().length > 0) {
                params.put("columnSort", pagination.getSortFields()[0].getField());
                params.put("directionSort", pagination.getSortFields()[0].getDirection().toUpperCase());
            } else {
                params.put("columnSort", "count");
                params.put("directionSort", "DESC");
            }
            completeDates(params, pagination.getFilterExpression());
            return session.selectList("com.bytesw.bytebot.dao.jdbc.MessageMapper.getSummaryBySentence", params);
        } finally {
            session.close();
        }
    }

    public int countSummaryBySentence(Pagination<SummaryMessageBySentenceBean> pagination) {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            Map<String, Object> params = new HashMap<>();
            completeDates(params, pagination.getFilterExpression());
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countSummaryBySentence", params);
        } finally {
            session.close();
        }
    }

    /**
     * obtiene el promedio intenciones por cliente y rango de fechas
     * @return
     */
    public Double avgIntentsByCustomerAndRange(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.avgIntentsByCustomerAndRange", params);
        } finally {
            session.close();
        }
    }

    /**
     * Obtiene la cantidad por cada intención en un periodo de tiempo
     * @return
     */
    public List<MessageByIntentBean> countMessageByIntent(OffsetDateTime startDate, OffsetDateTime endDate) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("startDate", startDate);
            params.put("endDate", endDate);
            return session.selectList("com.bytesw.bytebot.dao.jdbc.MessageMapper.countMessageByIntent", params);
        } finally {
            session.close();
        }
    }

    public int countSummaryByIntentAndSentence(Pagination<SummaryMessageBySentenceBean> pagination) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            Map<String, Object> params = new HashMap<>();
            completeDates(params, pagination.getFilterExpression());
            return session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countSummaryByIntentAndSentence", params);
        } finally {
            session.close();
        }
    }

    public int countCustomersBySentence(String sentence) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("sentence", sentence);
            Object result = session.selectOne("com.bytesw.bytebot.dao.jdbc.MessageMapper.countCustomersBySentence", params);
            if (result instanceof Double) {
                return ((Double) result).intValue();
            } else if (result instanceof Integer) {
                return (Integer) result;
            }
            return 0;
        } finally {
            session.close();
        }
    }

    private void completeDates(Map<String, Object> params, String filterString) {
        if (filterString == null || filterString.isEmpty()) {
            return;
        }
        String[] filters = filterString.split("&&");
        if (filters != null) {
            for (String filter : filters) {
                String[] filterValue = filter.split("=");
                params.put(filterValue[0], OffsetDateTime.ofInstant(Instant.ofEpochMilli(new Long(filterValue[1])), ZoneId.systemDefault()));
            }
        }
    }
}

