package com.viettel.campaign.repository.ccms_full.impl;

import com.viettel.campaign.config.DataSourceQualify;
import com.viettel.campaign.repository.ccms_full.CampaignExecuteRepository;
import com.viettel.campaign.repository.ccms_full.TimeRangeDialModeRepository;
import com.viettel.campaign.repository.ccms_full.TimeZoneDialModeRepository;
import com.viettel.campaign.utils.Constants;
import com.viettel.campaign.utils.DataUtil;
import com.viettel.campaign.utils.HibernateUtil;
import com.viettel.campaign.utils.SQLBuilder;
import com.viettel.campaign.web.dto.ApParamDTO;
import com.viettel.campaign.web.dto.CampaignDTO;
import com.viettel.campaign.web.dto.ContactCustResultDTO;
import com.viettel.campaign.web.dto.ResultDTO;
import com.viettel.campaign.web.dto.request_dto.CampaignRequestDTO;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.hibernate.type.DateType;
import org.hibernate.type.LongType;
import org.hibernate.type.ShortType;
import org.hibernate.type.StringType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Repository
public class CampaignExecuteRepositoryImp implements CampaignExecuteRepository {

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

    @Autowired
    @Qualifier(DataSourceQualify.NAMED_JDBC_PARAMETER_TEMPLATE_CCMS_FULL)
    NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Autowired
    @PersistenceContext(unitName = DataSourceQualify.JPA_UNIT_NAME_CCMS_FULL)
    EntityManager entityManager;

    @Autowired
    TimeZoneDialModeRepository zoneDialModeRepository;

    @Autowired
    TimeRangeDialModeRepository rangeDialModeRepository;

    @Override
    public List<ApParamDTO> getComboBoxStatus(String companySiteId, String completeType) {
        List<ApParamDTO> list = new ArrayList<>();
        Map<String, String> params = new HashMap<>();
        String sql = SQLBuilder.getSqlQueryById(Constants.SQL_MODULES.MODULE_EXECUTE, "get-combo-status");
        try {
            params.put("p_company_site_id", companySiteId);
            params.put("p_complete_type", completeType);
            list = namedParameterJdbcTemplate.query(sql, params, BeanPropertyRowMapper.newInstance(ApParamDTO.class));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return list;
    }

    @Override
    public List<ApParamDTO> getComboCampaignType(String companySiteId) {
        List<ApParamDTO> list = new ArrayList<>();
        Map<String, String> params = new HashMap<>();
        String sql = SQLBuilder.getSqlQueryById(Constants.SQL_MODULES.MODULE_EXECUTE, "get-combo-campaign-type");
        try {
            params.put("p_company_site_id", companySiteId);
            list = namedParameterJdbcTemplate.query(sql, params, BeanPropertyRowMapper.newInstance(ApParamDTO.class));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return list;
    }

    @Override
    public ResultDTO getInteractiveResult(CampaignRequestDTO dto) {
        ResultDTO resultDTO = new ResultDTO();
        List<ContactCustResultDTO> list = new ArrayList<>();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        StringBuilder sqlBuilder = new StringBuilder();
        try {
            String sql = SQLBuilder.getSqlQueryById(Constants.SQL_MODULES.MODULE_EXECUTE, "get-execute-interactive");
            sqlBuilder.append(sql);

            sqlBuilder.append(" and b.campaign_type in (:p_list_compaign_type)");
            sqlBuilder.append(" and to_char(a.customer_id) like :p_customer_id");
            sqlBuilder.append(" and to_char(a.contact_status) in (:p_list_contact_status)");
            sqlBuilder.append(" and to_char(a.call_status) in (:p_list_survey_status)");
            sqlBuilder.append(" and to_char(a.status) in (:p_list_record_status)");

            if (!DataUtil.isNullOrEmpty(dto.getPhoneNumber())) {
                sqlBuilder.append(" and a.phone_number like :p_phone_number");
            }
            if (!DataUtil.isNullOrEmpty(dto.getCampaignId())) {
                sqlBuilder.append(" and b.campaign_code in (:p_list_campaign_id) ");
            }
            if (!DataUtil.isNullOrEmpty(dto.getCampaignName())) {
                sqlBuilder.append(" and upper(b.campaign_name) like :p_campaign_name");
            }
            if (!DataUtil.isNullOrEmpty(dto.getAgentId())) {
                sqlBuilder.append(" and upper(c.user_name) like :p_user_name");
            }

            SQLQuery query = session.createSQLQuery(sqlBuilder.toString());

            query.setParameter("p_company_site_id", dto.getCompanySiteId());
            query.setParameter("p_customer_id", "%" + dto.getCustomerId()
                    .replace("\\", "\\\\")
                    .replaceAll("%", "\\%")
                    .replaceAll("_", "\\_")
                    + "%");
            query.setParameter("p_date_from", dto.getFromDate());
            query.setParameter("p_date_to", dto.getToDate());
            query.setParameterList("p_list_compaign_type", dto.getCampaignType().split(","));
            query.setParameterList("p_list_contact_status", dto.getContactStatus().split(","));
            query.setParameterList("p_list_survey_status", dto.getSurveyStatus().split(","));
            query.setParameterList("p_list_record_status", dto.getRecordStatus().split(","));
            query.setParameter("p_call_time_from", dto.getCallTimeFrom());
            query.setParameter("p_call_time_to", dto.getCallTimeTo());

            if (!DataUtil.isNullOrEmpty(dto.getCampaignId())) {
                query.setParameterList("p_list_campaign_id", dto.getCampaignId().split(","));
            }
            if (!DataUtil.isNullOrEmpty(dto.getPhoneNumber())) {
                query.setParameter("p_phone_number", "%" + dto.getPhoneNumber()
                        .replace("\\", "\\\\")
                        .replaceAll("%", "\\%")
                        .replaceAll("_", "\\_")
                        + "%");
            }
            if (!DataUtil.isNullOrEmpty(dto.getCampaignName())) {
                query.setParameter("p_campaign_name", "%" + dto.getCampaignName().toUpperCase()
                        .replace("\\", "\\\\")
                        .replaceAll("%", "\\%")
                        .replaceAll("_", "\\_")
                        + "%");
            }
            if (!DataUtil.isNullOrEmpty(dto.getAgentId())) {
                query.setParameter("p_user_name", "%" + dto.getAgentId().toUpperCase()
                        .replace("\\", "\\\\")
                        .replaceAll("%", "\\%")
                        .replaceAll("_", "\\_")
                        + "%");
            }

            query.addScalar("campaignCode", new StringType());
            query.addScalar("campaignName", new StringType());
            query.addScalar("userName", new StringType());
            query.addScalar("phoneNumber", new StringType());
            query.addScalar("customerName", new StringType());
            query.addScalar("createTime", new DateType());
            query.addScalar("contactStatus", new StringType());
            query.addScalar("surveyStatus", new StringType());
            query.addScalar("status", new ShortType());
            query.addScalar("recordStatus", new ShortType());
            query.addScalar("callTime", new LongType());

            query.setResultTransformer(Transformers.aliasToBean(ContactCustResultDTO.class));

            int count = 0;
            list = query.list();
            if (list.size() > 0) {
                count = list.size();
            }
            Pageable pageable = SQLBuilder.buildPageable(dto);
            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }
            List<ContactCustResultDTO> data = query.list();
            for (ContactCustResultDTO contactCustResultDTO : data) {
                if (!"AGENT".equals(dto.getRoleUser())) {
                    contactCustResultDTO.setEnableEdit(true);
                } else {
                    if (contactCustResultDTO.getRecordStatus() == 2) {
                        contactCustResultDTO.setEnableEdit(true);
                    } else if (contactCustResultDTO.getRecordStatus() == 1 && isLower24Hour(contactCustResultDTO.getCreateTime())) {
                        contactCustResultDTO.setEnableEdit(true);
                    } else {
                        contactCustResultDTO.setEnableEdit(false);
                    }
                }
            }
            Page<ContactCustResultDTO> dataPage = new PageImpl<>(data, pageable, count);
            resultDTO.setData(dataPage);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            logger.error(e.getMessage(), e);
        } finally {
            session.close();
            return resultDTO;
        }
    }

    @Override
    public List<ContactCustResultDTO> getExcelInteractiveResult(CampaignRequestDTO dto) {
        List<ContactCustResultDTO> list = new ArrayList<>();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        StringBuilder sqlBuilder = new StringBuilder();
        try {
            String sql = SQLBuilder.getSqlQueryById(Constants.SQL_MODULES.MODULE_EXECUTE, "get-execute-interactive");
            sqlBuilder.append(sql);

            sqlBuilder.append(" and b.campaign_type in (:p_list_compaign_type)");
            sqlBuilder.append(" and to_char(a.customer_id) like :p_customer_id");
            sqlBuilder.append(" and to_char(a.contact_status) in (:p_list_contact_status)");
            sqlBuilder.append(" and to_char(a.call_status) in (:p_list_survey_status)");
            sqlBuilder.append(" and to_char(a.status) in (:p_list_record_status)");

            if (!DataUtil.isNullOrEmpty(dto.getPhoneNumber())) {
                sqlBuilder.append(" and a.phone_number like :p_phone_number");
            }
            if (!DataUtil.isNullOrEmpty(dto.getCampaignId())) {
                sqlBuilder.append(" and b.campaign_code in (:p_list_campaign_id) ");
            }
            if (!DataUtil.isNullOrEmpty(dto.getCampaignName())) {
                sqlBuilder.append(" and upper(b.campaign_name) like :p_campaign_name");
            }
            if (!DataUtil.isNullOrEmpty(dto.getAgentId())) {
                sqlBuilder.append(" and upper(c.user_name) like :p_user_name");
            }

            SQLQuery query = session.createSQLQuery(sqlBuilder.toString());

            query.setParameter("p_company_site_id", dto.getCompanySiteId());
            query.setParameter("p_customer_id", "%" + dto.getCustomerId()
                    .replace("\\", "\\\\")
                    .replaceAll("%", "\\%")
                    .replaceAll("_", "\\_")
                    + "%");
            query.setParameter("p_date_from", dto.getFromDate());
            query.setParameter("p_date_to", dto.getToDate());
            query.setParameterList("p_list_compaign_type", dto.getCampaignType().split(","));
            query.setParameterList("p_list_contact_status", dto.getContactStatus().split(","));
            query.setParameterList("p_list_survey_status", dto.getSurveyStatus().split(","));
            query.setParameterList("p_list_record_status", dto.getRecordStatus().split(","));
            query.setParameter("p_call_time_from", dto.getCallTimeFrom());
            query.setParameter("p_call_time_to", dto.getCallTimeTo());

            if (!DataUtil.isNullOrEmpty(dto.getCampaignId())) {
                query.setParameterList("p_list_campaign_id", dto.getCampaignId().split(","));
            }
            if (!DataUtil.isNullOrEmpty(dto.getPhoneNumber())) {
                query.setParameter("p_phone_number", "%" + dto.getPhoneNumber()
                        .replace("\\", "\\\\")
                        .replaceAll("%", "\\%")
                        .replaceAll("_", "\\_")
                        + "%");
            }
            if (!DataUtil.isNullOrEmpty(dto.getCampaignName())) {
                query.setParameter("p_campaign_name", "%" + dto.getCampaignName().toUpperCase()
                        .replace("\\", "\\\\")
                        .replaceAll("%", "\\%")
                        .replaceAll("_", "\\_")
                        + "%");
            }
            if (!DataUtil.isNullOrEmpty(dto.getAgentId())) {
                query.setParameter("p_user_name", "%" + dto.getAgentId().toUpperCase()
                        .replace("\\", "\\\\")
                        .replaceAll("%", "\\%")
                        .replaceAll("_", "\\_")
                        + "%");
            }

            query.addScalar("campaignCode", new StringType());
            query.addScalar("campaignName", new StringType());
            query.addScalar("userName", new StringType());
            query.addScalar("phoneNumber", new StringType());
            query.addScalar("customerName", new StringType());
            query.addScalar("createTime", new DateType());
            query.addScalar("contactStatus", new StringType());
            query.addScalar("surveyStatus", new StringType());
            query.addScalar("status", new ShortType());
            query.addScalar("recordStatus", new ShortType());
            query.addScalar("callTime", new LongType());

            query.setResultTransformer(Transformers.aliasToBean(ContactCustResultDTO.class));

            list = query.list();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            session.close();
            return list;
        }
    }

    @Override
    public List<ContactCustResultDTO> getContactCustById(CampaignRequestDTO dto) {
        return null;
    }

    private boolean isLower24Hour(Date createTime) {
        Date currTime = new Date();
        long diffMilSec = currTime.getTime() - createTime.getTime();
        long hour = TimeUnit.MILLISECONDS.toHours(diffMilSec);
        if (hour > 24) return false;
        return true;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<CampaignDTO> searchCampaignExecute(CampaignRequestDTO campaignRequestDto, Pageable pageable) {
        List<CampaignDTO> result = new ArrayList<>();
        StringBuilder expression = new StringBuilder()
                .append(" SELECT C.CAMPAIGN_CODE, C.CAMPAIGN_NAME, C.CONTENT, C.START_TIME, C.END_TIME, C.STATUS, CA.STATUS AS AGENT_STATUS, C.CAMPAIGN_ID ")
                .append(" FROM CAMPAIGN C INNER JOIN CAMPAIGN_AGENT CA ON C.CAMPAIGN_ID = CA.CAMPAIGN_ID ")
                .append(" WHERE 1 = 1 ")
                .append(" AND CA.AGENT_ID = :pAgentId ");

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getCampaignCode())) {
            expression.append(" AND C.CAMPAIGN_CODE IN (:pCampaignCode) ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getCampaignName())) {
            expression.append(" AND UPPER(C.CAMPAIGN_NAME) LIKE :pCampaignName ");
        }

        if (!DataUtil.isNullOrZero(campaignRequestDto.getStatus().longValue())) {
            if (campaignRequestDto.getStatus() != 0)
                expression.append(" AND C.STATUS = :pStatus ");
        } else {
            expression.append(" AND C.STATUS IN (2, 3) ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getFromDateFr())) {
            expression.append(" AND TRUNC(C.START_TIME) >= TRUNC(:pStartTimeFr) ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getFromDateTo())) {
            expression.append(" AND TRUNC(C.START_TIME) <= TRUNC(:pStartTimeTo) ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateFr())) {
            expression.append(" AND TRUNC(C.END_TIME) >= TRUNC(:pEndTimeFr) ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateTo())) {
            expression.append(" AND TRUNC(C.END_TIME) <= TRUNC(:pEndTimeTo) ");
        }

        if (!DataUtil.isNullOrZero(campaignRequestDto.getNumOfCusFr())) {
            expression.append(" AND C.CUSTOMER_NUMBER >= :pCustNumFr ");
        }

        if (!DataUtil.isNullOrZero(campaignRequestDto.getNumOfCusTo())) {
            expression.append(" AND C.CUSTOMER_NUMBER <= :pCustNumTo ");
        }

        try {
            Query query = entityManager.createNativeQuery(expression.toString());
            query.setParameter("pAgentId", Long.parseLong(campaignRequestDto.getAgentId()));

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getCampaignCode())) {
                String[] lstCode = campaignRequestDto.getCampaignCode().split(",");
                query.setParameter("pCampaignCode", lstCode);
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getCampaignName())) {
                query.setParameter("pCampaignName", "%" +
                        campaignRequestDto.getCampaignName().toUpperCase()
                                .replace("\\", "\\\\")
                                .replaceAll("%", "\\\\%")
                                .replaceAll("_", "\\\\_")
                        + "%");
            }

            if (!DataUtil.isNullOrZero(campaignRequestDto.getStatus().longValue())) {
                if (campaignRequestDto.getStatus() != 0)
                    query.setParameter("pStatus", campaignRequestDto.getStatus());
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getFromDateFr())) {
                query.setParameter("pStartTimeFr", campaignRequestDto.getFromDateFr());
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getFromDateTo())) {
                query.setParameter("pStartTimeTo", campaignRequestDto.getFromDateTo());
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateFr())) {
                query.setParameter("pEndTimeFr", campaignRequestDto.getToDateFr());
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateTo())) {
                query.setParameter("pEndTimeTo", campaignRequestDto.getToDateTo());
            }

            if (!DataUtil.isNullOrZero(campaignRequestDto.getNumOfCusFr())) {
                query.setParameter("pCustNumFr", campaignRequestDto.getNumOfCusFr());
            }

            if (!DataUtil.isNullOrZero(campaignRequestDto.getNumOfCusTo())) {
                query.setParameter("pCustNumTo", campaignRequestDto.getNumOfCusTo());
            }

            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }

            List<Object[]> data = query.getResultList();
            //TimeZoneDialMode zoneDialMode = zoneDialModeRepository.findDialModeAtCurrent(Long.parseLong(campaignRequestDto.getCampaignId()), Long.parseLong(campaignRequestDto.getCompanySiteId()));
            //TimeRangeDialMode rangeDialMode = rangeDialModeRepository.findDialModeAtCurrent(Long.parseLong(campaignRequestDto.getCampaignId()), Long.parseLong(campaignRequestDto.getCompanySiteId()));

            for (Object[] obj : data) {
                CampaignDTO item = new CampaignDTO();
                item.setPage(campaignRequestDto.getPage());
                item.setPageSize(campaignRequestDto.getPageSize());
                item.setSort(campaignRequestDto.getSort());
                item.setCampaignCode((String) obj[0]);
                item.setCampaignName((String) obj[1]);
                item.setContent((String) obj[2]);
                item.setStartTime((Date) obj[3]);
                item.setEndTime((Date) obj[4]);
                item.setStatus(((BigDecimal) obj[5]).shortValueExact());
                item.setAgentStatus(((BigDecimal) obj[6]).shortValueExact());
                item.setCampaignId(((BigDecimal) obj[7]).longValueExact());

                result.add(item);
            }

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

}
