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.ContactQuestResultRepository;
import com.viettel.campaign.repository.ccms_full.TimeRangeDialModeRepository;
import com.viettel.campaign.repository.ccms_full.TimeZoneDialModeRepository;
import com.viettel.campaign.utils.*;
import com.viettel.campaign.web.dto.*;
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.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);
    private static final String CONNECT_STATUS_TYPE_RE = "3";

    @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;

    @Autowired
    ContactQuestResultRepository contactQuestResultRepository;

    @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");
        StringBuilder sb = new StringBuilder();

        sb.append("select distinct COMPLETE_VALUE apParamId,");
        sb.append("        COMPLETE_NAME parName");
        sb.append(" from CAMPAIGN_COMPLETE_CODE");
        sb.append(" where to_char(COMPLETE_TYPE) = :p_complete_type and STATUS = 1 and COMPANY_SITE_ID = :p_company_site_id");
        try {
            params.put("p_company_site_id", companySiteId);
            params.put("p_complete_type", completeType);
            list = namedParameterJdbcTemplate.query(sb.toString(), 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");

        StringBuilder sb = new StringBuilder();

        sb.append("select  PAR_VALUE apParamId,");
        sb.append("        PAR_NAME parName");
        sb.append(" from AP_PARAM");
        sb.append(" where PAR_TYPE = 'CAMPAIGN_TYPE'");
        sb.append("    and COMPANY_SITE_ID = :p_company_site_id");
        sb.append("    and IS_DELETE = 0");
        try {
            params.put("p_company_site_id", companySiteId);
            list = namedParameterJdbcTemplate.query(sb.toString(), params, BeanPropertyRowMapper.newInstance(ApParamDTO.class));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return list;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<ContactCustResultDTO> getInteractiveResult(CampaignRequestDTO dto, Pageable pageable) {
        ResultDTO resultDTO = new ResultDTO();
        List<ContactCustResultDTO> list = new ArrayList<>();

        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        try {
            StringBuilder sql = new StringBuilder();

            sql.append("SELECT CCR.CONTACT_CUST_RESULT_ID   AS contactCustResultId, ");
            sql.append("    CCR.CREATE_TIME                 AS createTime, ");
            sql.append("    C.CAMPAIGN_CODE                 AS campaignCode, ");
            sql.append("    C.CAMPAIGN_NAME                 AS campaignName, ");
            sql.append("    VU.USER_NAME                    AS userName, ");
            sql.append("    CCR.PHONE_NUMBER                AS phoneNumber, ");
            sql.append("    CUS.NAME                        AS customerName, ");
            sql.append("    CCR.START_CALL                  AS startCall, ");
            sql.append("    CC1.COMPLETE_NAME               AS connectStatus, ");
            sql.append("    CC2.COMPLETE_NAME               AS surveyStatus, ");
            sql.append("    C.STATUS                        AS status, ");
            sql.append("    CCR.STATUS                      AS recordStatus, ");
            sql.append("    (( CCR.END_TIME - CCR.START_CALL ) * 24 * 60 * 60) AS callTime, ");
            sql.append("    C.CAMPAIGN_ID                   AS campaignId, ");
            sql.append("    CUS.CUSTOMER_ID                 AS customerId ");
            sql.append("FROM CONTACT_CUST_RESULT CCR ");
            sql.append("    INNER JOIN CAMPAIGN                 C ON CCR.CAMPAIGN_ID = C.CAMPAIGN_ID ");
            sql.append("    INNER JOIN VSA_USERS                VU ON CCR.AGENT_ID = VU.USER_ID ");
            sql.append("    INNER JOIN CUSTOMER                 CUS ON CCR.CUSTOMER_ID = CUS.CUSTOMER_ID ");
            sql.append("    INNER JOIN CAMPAIGN_COMPLETE_CODE   CC1 ON CCR.CONTACT_STATUS = CC1.COMPLETE_VALUE ");
            sql.append("    LEFT JOIN CAMPAIGN_COMPLETE_CODE   CC2 ON CCR.CALL_STATUS = CC2.COMPLETE_VALUE ");
            sql.append("WHERE CCR.STATUS <> 0 ");
            sql.append("  AND CCR.COMPANY_SITE_ID = :p_company_site_id ");
            sql.append("  AND to_date(CCR.CREATE_TIME, 'DD/MM/RR') >= to_date(:p_date_from, 'DD/MM/RR') ");
            sql.append("  AND to_date(CCR.CREATE_TIME, 'DD/MM/RR') <= to_date(:p_date_to, 'DD/MM/RR') ");

            if (!DataUtil.isNullOrEmpty(dto.getCustomerId())) {
                sql.append(" AND CCR.CUSTOMER_ID LIKE (:p_customer_id) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getCampaignType())) {
                sql.append(" AND C.CAMPAIGN_TYPE IN (:p_list_compaign_type) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getContactStatus())) {
                sql.append(" AND CCR.CONTACT_STATUS IN (:p_list_contact_status) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getSurveyStatus())) {
                sql.append(" AND CCR.CALL_STATUS IN (:p_list_survey_status) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getRecordStatus())) {
                sql.append(" AND CCR.STATUS IN (:p_list_record_status) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getCampaignCode())) {
                sql.append(" AND C.CAMPAIGN_CODE IN (:p_list_campaign_code) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getPhoneNumber())) {
                sql.append(" AND CCR.PHONE_NUMBER LIKE (:p_phone_number) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getCampaignName())) {
                sql.append(" AND UPPER(C.CAMPAIGN_NAME) LIKE (:p_campaign_name) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getAgentId())) {
                sql.append(" AND UPPER(VU.USER_NAME) LIKE (:p_user_name) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getCallTimeFrom())) {
                sql.append(" AND (( CCR.END_TIME - CCR.START_CALL ) * 24 * 60 * 60) >= (:p_call_time_from) ");
            }

            if (!DataUtil.isNullOrEmpty(dto.getCallTimeTo())) {
                sql.append(" AND (( CCR.END_TIME - CCR.START_CALL ) * 24 * 60 * 60) <= (:p_call_time_to) ");
            }

            SQLQuery query = session.createSQLQuery(sql.toString());
            query.setParameter("p_company_site_id", dto.getCompanySiteId());
            query.setParameter("p_date_from", dto.getFromDate());
            query.setParameter("p_date_to", dto.getToDate());

            if (!DataUtil.isNullOrEmpty(dto.getCustomerId())) {
                query.setParameter("p_customer_id", "%" +
                        dto.getCustomerId().toUpperCase()
                                .replace("\\", "\\\\")
                                .replaceAll("%", "\\\\%")
                                .replaceAll("_", "\\\\_")
                        + "%");
            }

            if (!DataUtil.isNullOrEmpty(dto.getCampaignType())) {
                String[] lstCode = dto.getCampaignType().split(",");
                query.setParameterList("p_list_compaign_type", lstCode);
            }

            if (!DataUtil.isNullOrEmpty(dto.getContactStatus())) {
                String[] lstCode = dto.getContactStatus().split(",");
                query.setParameterList("p_list_contact_status", lstCode);
            }

            if (!DataUtil.isNullOrEmpty(dto.getSurveyStatus())) {
                String[] lstCode = dto.getSurveyStatus().split(",");
                query.setParameterList("p_list_survey_status", lstCode);
            }

            if (!DataUtil.isNullOrEmpty(dto.getRecordStatus())) {
                String[] lstCode = dto.getRecordStatus().split(",");
                query.setParameterList("p_list_record_status", lstCode);
            }

            if (!DataUtil.isNullOrEmpty(dto.getCampaignCode())) {
                String[] lstCode = dto.getCampaignCode().split(",");
                query.setParameterList("p_list_campaign_code", lstCode);
            }

            if (!DataUtil.isNullOrEmpty(dto.getPhoneNumber())) {
                query.setParameter("p_phone_number", "%" +
                        dto.getPhoneNumber().toUpperCase()
                                .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.setParameter("p_call_time_from", dto.getCallTimeFrom());
            query.setParameter("p_call_time_to", dto.getCallTimeTo());

            // add data to parameter
            /*query.addScalar("contactCustResultId", new LongType());
            query.addScalar("createTime", new DateType());
            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("startCall", 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());*/

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

            List<Object[]> data = query.list();
            //query.setResultTransformer(Transformers.aliasToBean(ContactCustResultDTO.class));
            //list = query.list();

            for (Object[] obj : data) {
                ContactCustResultDTO item = new ContactCustResultDTO();
                item.setPage(dto.getPage());
                item.setPageSize(dto.getPageSize());
                item.setSort(dto.getSort());
                item.setContactCustResultId(((BigDecimal) obj[0]).longValueExact());
                item.setCreateTime((Date) obj[1]);
                item.setCampaignCode((String) obj[2]);
                item.setCampaignName((String) obj[3]);
                item.setUserName((String) obj[4]);
                item.setPhoneNumber((String) obj[5]);
                item.setCustomerName((String) obj[6]);
                item.setStartCall(obj[7] == null ? null : (Date) obj[7]);
                item.setConnectStatus((String) obj[8]);
                item.setSurveyStatus((String) obj[9]);
                item.setStatus(obj[10] == null ? 0 : ((BigDecimal) obj[10]).shortValueExact());
                item.setRecordStatus(obj[11] == null ? 0 : ((BigDecimal) obj[11]).shortValueExact());
                item.setCallTime(obj[12] == null ? 0L : ((BigDecimal) obj[12]).longValueExact());
                item.setCampaignId(obj[13] == null ? 0L : ((BigDecimal) obj[13]).longValueExact());
                item.setCustomerId(obj[14] == null ? 0L : ((BigDecimal) obj[14]).longValueExact());

                list.add(item);
            }

            for (ContactCustResultDTO ContactCustResultDTO : list) {
                if (!"AGENT".equals(dto.getRoleUser())) { // ko phải nhân viên
                    ContactCustResultDTO.setEnableEdit(true);
                } else {
                    if (2 == ContactCustResultDTO.getRecordStatus()) {// là nhân viên thường
                        ContactCustResultDTO.setEnableEdit(true);
                    } else if (1 == ContactCustResultDTO.getRecordStatus() && isLower24Hour(ContactCustResultDTO.getCreateTime())) {
                        ContactCustResultDTO.setEnableEdit(true);
                    } else {
                        ContactCustResultDTO.setEnableEdit(false);
                    }
                }
            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        } finally {
            session.close();
        }

        return list;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<ContactCustResultDTO> getExcelInteractiveResult(CampaignRequestDTO dto) {
        List<ContactCustResultDTO> list = new ArrayList<>();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        Session session = sessionFactory.openSession();
        session.beginTransaction();

        try {
            StringBuilder sb = new StringBuilder();

            sb.append("with campaign_type_list as (");
            sb.append("    select trim (regexp_substr(:p_list_compaign_type, '[^,]+', 1, level)) campaign_type");
            sb.append("    from dual");
            sb.append("    connect by level <= regexp_count(:p_list_compaign_type, ',') +1");
            sb.append(" ),");
            sb.append(" contact_status_list as (");
            sb.append("    select trim (regexp_substr(:p_list_contact_status, '[^,]+', 1, level)) contact_status");
            sb.append("    from dual");
            sb.append("    connect by level <= regexp_count(:p_list_contact_status, ',') +1");
            sb.append(" ),");
            sb.append(" survey_status_list as (");
            sb.append("    select trim (regexp_substr(:p_list_survey_status, '[^,]+', 1, level)) survey_status");
            sb.append("    from dual");
            sb.append("    connect by level <= regexp_count(:p_list_survey_status, ',') +1");
            sb.append(" ),");
            sb.append(" record_status_list as (");
            sb.append("    select trim (regexp_substr(:p_list_record_status, '[^,]+', 1, level)) record_status");
            sb.append("    from dual");
            sb.append("    connect by level <= regexp_count(:p_list_record_status, ',') +1");
            sb.append(" ),");
            sb.append(" campaign_code_list as (");
            sb.append("    select trim (regexp_substr(:p_list_campaign_code, '[^,]+', 1, level)) campaign_code");
            sb.append("    from dual");
            sb.append("    connect by level <= regexp_count(:p_list_campaign_code, ',') +1");
            sb.append(" ),");
            sb.append(" data_temp as (");
            sb.append("    select  a.contact_cust_result_id contactCustResultId,");
            sb.append("            a.create_time createTime,");
            sb.append("            b.campaign_code campaignCode,");
            sb.append("            b.campaign_name campaignName,");
            sb.append("            c.user_name userName,");
            sb.append("            a.phone_number phoneNumber,");
            sb.append("            d.name customerName,");
            sb.append("            a.start_call startCall,");
            sb.append("            e.complete_name contactStatus,");
            sb.append("            f.complete_name surveyStatus,");
            sb.append("            g.status status,");
            sb.append("            a.status recordStatus,");
            sb.append("            (a.end_time - a.start_call)*24*60 callTime");
            sb.append("    from contact_cust_result a");
            sb.append("        left join campaign b on a.campaign_id = b.campaign_id");
            sb.append("        left join vsa_users c on a.agent_id = c.user_id");
            sb.append("        left join customer d on a.customer_id = d.customer_id");
            sb.append("        left join campaign_complete_code e on a.contact_status = e.complete_value");
            sb.append("        left join campaign_complete_code f on a.call_status = e.complete_value");
            sb.append("        left join campaign g on a.campaign_id = g.campaign_id");
            sb.append("    where a.status <> 0");
            sb.append("        and a.company_site_id = :p_company_site_id");
            sb.append("        and a.create_time >= to_date(:p_date_from, 'DD/MM/YYYY')");
            sb.append("        and a.create_time <= to_date(:p_date_to, 'DD/MM/YYYY')");
            sb.append("        and to_char(a.customer_id) like '%'||:p_customer_id||'%'");
            sb.append("        and b.campaign_type in (select campaign_type from campaign_type_list)");
            sb.append("        and to_char(a.contact_status) in (select contact_status from contact_status_list)");
            sb.append("        and to_char(a.call_status) in (select survey_status from survey_status_list)");
            sb.append("        and to_char(a.status) in (select record_status from record_status_list)");
            sb.append("        and (:p_phone_number is null or to_char(a.phone_number) like '%'||:p_phone_number||'%')");
            sb.append("        and (:p_list_campaign_code is null or b.campaign_code in (select campaign_code from campaign_code_list))");
            sb.append("        and (:p_campaign_name is null or upper(b.campaign_name) like '%'||:p_campaign_name||'%')");
            sb.append("        and (:p_user_name is null or upper(c.user_name) like '%'||:p_user_name||'%')");
            sb.append(" ),");
            sb.append(" data as (");
            sb.append("    select a.*, rownum row_ from data_temp a");
            sb.append("     where a.callTime >= :p_call_time_from");
            sb.append("         and a.callTime <= :p_call_time_to");
            sb.append(" )");
            sb.append(" select campaignCode, createTime, campaignName, userName, phoneNumber, customerName, startCall, contactStatus, surveyStatus, status, recordStatus, callTime from data");
            sb.append(" where :p_page_size = 0 or (row_ >= ((:p_page_number - 1) * :p_page_size + 1) and row_ < (:p_page_number * :p_page_size + 1))");

            SQLQuery query = session.createSQLQuery(sb.toString());
            query.setParameter("p_company_site_id", dto.getCompanySiteId());
            query.setParameter("p_customer_id", dto.getCustomerId());
            query.setParameter("p_date_from", dto.getFromDate());
            query.setParameter("p_date_to", dto.getToDate());
            query.setParameter("p_list_compaign_type", dto.getCampaignType());
            query.setParameter("p_list_contact_status", dto.getContactStatus());
            query.setParameter("p_list_survey_status", dto.getSurveyStatus());
            query.setParameter("p_list_record_status", dto.getRecordStatus());
            query.setParameter("p_call_time_from", dto.getCallTimeFrom());
            query.setParameter("p_call_time_to", dto.getCallTimeTo());
            query.setParameter("p_list_campaign_code", dto.getCampaignCode());
            query.setParameter("p_phone_number", dto.getPhoneNumber());
            query.setParameter("p_campaign_name", DataUtil.isNullOrEmpty(dto.getCampaignName()) ? null : dto.getCampaignName().trim().toUpperCase());
            query.setParameter("p_user_name", DataUtil.isNullOrEmpty(dto.getAgentId()) ? null : dto.getAgentId().trim().toUpperCase());
            query.setParameter("p_page_number", dto.getPage());
            query.setParameter("p_page_size", dto.getPageSize());

            query.addScalar("createTime", new DateType());
            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("startCall", new DateType());
            query.addScalar("contactStatus", new StringType());
            query.addScalar("surveyStatus", new StringType());
            query.addScalar("status", new StringType());
            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;
    }

    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<>();
        TimeZone tzClient = TimeZoneUtils.getZoneMinutes(campaignRequestDto.getTimezone());
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = null;

        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 C.START_TIME >= TO_DATE(:pStartTimeFr, 'DD/MM/YYYY HH24:MI:SS') ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getFromDateTo())) {
            expression.append(" AND C.START_TIME <= TO_DATE(:pStartTimeTo, 'DD/MM/YYYY HH24:MI:SS') ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateFr())) {
            expression.append(" AND C.END_TIME >= TO_DATE(:pEndTimeFr, 'DD/MM/YYYY HH24:MI:SS') ");
        }

        if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateTo())) {
            expression.append(" AND C.END_TIME <= TO_DATE(:pEndTimeTo, 'DD/MM/YYYY HH24:MI:SS') ");
        }

        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 {
            session = sessionFactory.openSession();
            session.beginTransaction();

            SQLQuery query = session.createSQLQuery(expression.toString());
            query.setParameter("pAgentId", Long.parseLong(campaignRequestDto.getAgentId()));

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getCampaignCode()) && !DataUtil.isNullOrEmpty(campaignRequestDto.getCampaignCode().trim())) {
                String[] lstCode = campaignRequestDto.getCampaignCode().split(",");
                query.setParameterList("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", TimeZoneUtils.toDateStringWithTimeZone(DateTimeUtil.parseDate("dd/MM/yyyy", campaignRequestDto.getFromDateFr()), tzClient));
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getFromDateTo())) {
                query.setParameter("pStartTimeTo", TimeZoneUtils.toDateStringWithTimeZone(DateTimeUtil.parseDate("dd/MM/yyyy", campaignRequestDto.getFromDateTo()), tzClient));
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateFr())) {
                query.setParameter("pEndTimeFr", TimeZoneUtils.toDateStringWithTimeZone(DateTimeUtil.parseDate("dd/MM/yyyy", campaignRequestDto.getToDateFr()), tzClient));
            }

            if (!DataUtil.isNullOrEmpty(campaignRequestDto.getToDateTo())) {
                query.setParameter("pEndTimeTo", TimeZoneUtils.toDateStringWithTimeZone(DateTimeUtil.parseDate("dd/MM/yyyy", campaignRequestDto.getToDateTo()), tzClient));
            }

            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.list();

            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();
        } finally {
            if (null != session) {
                session.close();
            }
        }

        return result;
    }
}
