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

import com.viettel.campaign.config.DataSourceQualify;
import com.viettel.campaign.model.ccms_full.CampaignCustomer;
import com.viettel.campaign.repository.ccms_full.CampaignCustomerRepository;
import com.viettel.campaign.repository.ccms_full.CampaignRepositoryCustom;
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.*;
import com.viettel.campaign.web.dto.request_dto.CampaignRequestDTO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.hibernate.type.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.*;
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.*;

@Repository
public class CampaignRepositoryImpl implements CampaignRepositoryCustom {

    private static final Logger logger = LogManager.getLogger(CampaignRepositoryImpl.class);

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

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

    @Autowired
    CampaignCustomerRepository campaignCustomerRepository;

    @Override
    public ResultDTO search(CampaignRequestDTO requestDto) {
        logger.info("Start search campaign::");

        ResultDTO result = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrEmpty(requestDto.getCompanySiteId())) {
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setDescription(Constants.ApiErrorDesc.ERROR);
            return result;
        }
        try {
            StringBuilder sb = new StringBuilder();

            sb.append(" SELECT");
            sb.append("    a.CAMPAIGN_ID campaignId,");
            sb.append("    a.CAMPAIGN_CODE campaignCode,");
            sb.append("    a.CAMPAIGN_NAME campaignName,");
            sb.append("    a.CAMPAIGN_TYPE campaignType,");
            sb.append("    (SELECT PAR_NAME FROM AP_PARAM WHERE STATUS = 1 AND PAR_TYPE = 'CAMPAIGN_TYPE' AND PAR_VALUE = a.CAMPAIGN_TYPE) campaignTypeName,");
            sb.append("    a.CHANEL chanel,");
            sb.append("    a.START_TIME startTime,");
            sb.append("    a.END_TIME endTime,");
            sb.append("    a.CUSTOMER_NUMBER customerNumber,");
            sb.append("    a.STATUS status,");
            sb.append("    a.CUSTOMER_NUMBER cusNum,");
            sb.append("    b.SLKHThamgiaCD numOfJoinedCus,");
            sb.append("    e.SLKHDaTuongTac numOfInteractedCus,");
            sb.append("    c.SLKHChuaTuongTac numOfNotInteractedCus,");
            sb.append("    d.SLKHDoNotCall_Khoa numOfLockCus,");
            sb.append("    a.COMPANY_SITE_ID companySiteId,");
            sb.append("    a.CONTENT content,");
            sb.append("    a.MAX_RECALL maxRecall,");
            sb.append("    a.RECALL_TYPE recallType,");
            sb.append("    a.RECALL_DURATION recallDuration,");
            sb.append("    a.CURRENT_TIME_MODE currentTimeMode,");
            sb.append("    a.WRAPUP_TIME_CONNECT wrapupTimeConnect,");
            sb.append("    a.WRAPUP_TIME_DISCONNECT wrapupTimeDisconnect");
            sb.append(" FROM CAMPAIGN a");
            sb.append(" LEFT JOIN (SELECT campaign_id, COUNT (*) AS SLKHThamgiaCD");
            sb.append("                  FROM   campaign_customer cc INNER JOIN CUSTOMER cus ON cc.CUSTOMER_ID = cus.CUSTOMER_ID");
            sb.append("                  WHERE 1 = 1 AND cc.IN_CAMPAIGN_STATUS = 1 AND cus.STATUS = 1");
            sb.append("                  group by campaign_id) b");
            sb.append(" ON a.CAMPAIGN_ID = b.CAMPAIGN_ID");
            sb.append(" LEFT JOIN (SELECT campaign_id, COUNT (*) AS SLKHChuaTuongTac");
            sb.append("                  FROM   campaign_customer cc INNER JOIN CUSTOMER cus ON cc.CUSTOMER_ID = cus.CUSTOMER_ID");
            sb.append("                  WHERE 1 = 1 AND cc.STATUS = 0 AND cus.STATUS = 1");
            sb.append("                  group by campaign_id) c");
            sb.append(" ON c.CAMPAIGN_ID = a.CAMPAIGN_ID");
            sb.append(" LEFT JOIN (SELECT cc.campaign_id, count(*) AS SLKHDoNotCall_Khoa");
            sb.append("        FROM CAMPAIGN_CUSTOMER cc , CUSTOMER c");
            sb.append("        WHERE cc.CUSTOMER_ID = c.CUSTOMER_ID");
            sb.append("        AND (c.IPCC_STATUS = 'locked' or c.CALL_ALLOWED = 0) AND cc.STATUS = 1");
            sb.append("        GROUP BY cc.CAMPAIGN_ID) d");
            sb.append(" ON d.CAMPAIGN_ID = a.CAMPAIGN_ID");
            sb.append(" LEFT JOIN (SELECT campaign_id, COUNT (*) AS SLKHDaTuongTac");
            sb.append("                  FROM   campaign_customer cc INNER JOIN CUSTOMER cus ON cc.CUSTOMER_ID = cus.CUSTOMER_ID");
            sb.append("                  WHERE 1 = 1 AND cc.STATUS <> 0 AND cus.STATUS = 1");
            sb.append("                  group by campaign_id) e");
            sb.append(" ON e.CAMPAIGN_ID = a.CAMPAIGN_ID");
            sb.append(" WHERE 1 = 1");
            sb.append(" AND COMPANY_SITE_ID = :p_company_site_id");
            sb.append(" AND a.STATUS <> -1");


            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignCode())) {
                sb.append(" AND a.CAMPAIGN_CODE IN (:p_code) ");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignName())) {
                sb.append(" AND UPPER(a.CAMPAIGN_NAME) LIKE :p_name");
            }
            if (requestDto.getStatus() != null && requestDto.getStatus() >= 0) {
                sb.append(" AND a.STATUS = :p_status");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getFromDateFr())) {
                sb.append(" AND TO_DATE(a.START_TIME, 'DD/MM/YYYY') >= :p_frDateFr");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getToDateFr())) {
                sb.append(" AND TO_DATE(a.START_TIME, 'DD/MM/YYYY') <= :p_toDateFr");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getFromDateTo())) {
                sb.append(" AND TO_DATE(a.END_TIME, 'DD/MM/YYYY') >= :p_frDateTo");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getToDateTo())) {
                sb.append(" AND TO_DATE(a.END_TIME, 'DD/MM/YYYY') <= :p_toDateTo");
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusFr())) {
                sb.append(" AND a.CUSTOMER_NUMBER >= :p_cusNumFr");
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusTo())) {
                sb.append(" AND a.CUSTOMER_NUMBER <= :p_cusNumTo");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getTypes())) {
                sb.append(" AND a.CAMPAIGN_TYPE IN (:p_type)");
            }
            if (requestDto.getChanel() != null && !DataUtil.isNullOrZero(requestDto.getChanel())) {
                sb.append(" AND a.CHANEL = :p_chanel");
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusFr())) {
                sb.append(" AND a.CUSTOMER_NUMBER >= :p_cusNumFr");
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusTo())) {
                sb.append(" AND a.CUSTOMER_NUMBER <= :p_cusNumTo");
            }

            sb.append(" ORDER BY a.CREATE_TIME DESC ");

            SQLQuery query = session.createSQLQuery(sb.toString());
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignCode())) {
                String[] lstCode = requestDto.getCampaignCode().split(",");
                query.setParameterList("p_code", lstCode);
            }

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

            query.setParameter("p_company_site_id", requestDto.getCompanySiteId());

            if (requestDto.getStatus() != null && requestDto.getStatus() >= 0) {
                query.setParameter("p_status", requestDto.getStatus());
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getFromDateFr())) {
                query.setParameter("p_frDateFr", requestDto.getFromDateFr());
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getFromDateTo())) {
                query.setParameter("p_frDateTo", requestDto.getFromDateTo());
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getToDateFr())) {
                query.setParameter("p_toDateFr", requestDto.getToDateFr());
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getToDateTo())) {
                query.setParameter("p_toDateTo", requestDto.getToDateTo());
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getTypes())) {
                String[] types = requestDto.getTypes().split(",");
                query.setParameterList("p_type", types);
            }
            if (requestDto.getChanel() != null && !DataUtil.isNullOrZero(requestDto.getChanel())) {
                query.setParameter("p_chanel", requestDto.getChanel());
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusFr())) {
                query.setParameter("p_cusNumFr", requestDto.getNumOfCusFr() == 0 ? null : requestDto.getNumOfCusFr());
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusTo())) {
                query.setParameter("p_cusNumTo", requestDto.getNumOfCusTo() == 0 ? null : requestDto.getNumOfCusTo());
            }

            query.addScalar("campaignId", new LongType());
            query.addScalar("campaignCode", new StringType());
            query.addScalar("campaignName", new StringType());
            query.addScalar("campaignType", new StringType());
            query.addScalar("campaignTypeName", new StringType());
            query.addScalar("chanel", new ShortType());
            query.addScalar("startTime", new DateType());
            query.addScalar("endTime", new DateType());
            query.addScalar("customerNumber", new LongType());
            query.addScalar("status", new ShortType());
            query.addScalar("numOfJoinedCus", new LongType());
            query.addScalar("numOfInteractedCus", new LongType());
            query.addScalar("numOfNotInteractedCus", new LongType());
            query.addScalar("numOfLockCus", new LongType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("content", new StringType());
            query.addScalar("maxRecall", new IntegerType());
            query.addScalar("recallType", new IntegerType());
            query.addScalar("recallDuration", new IntegerType());
            query.addScalar("currentTimeMode", new LongType());
            query.addScalar("wrapupTimeConnect", new LongType());
            query.addScalar("wrapupTimeDisconnect", new LongType());

            query.setResultTransformer(Transformers.aliasToBean(CampaignDTO.class));
            int count = 0;
            List<CampaignDTO> list = query.list();
            if (list.size() > 0) {
                count = query.list().size();
            }
            if (requestDto.getPage() != null && requestDto.getPageSize() != null) {
                Pageable pageable = SQLBuilder.buildPageable(requestDto);
                if (pageable != null) {
                    query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                    query.setMaxResults(pageable.getPageSize());
                }
                List<CampaignDTO> data = query.list();
                Page<CampaignDTO> dataPage = new PageImpl<>(data, pageable, count);
                result.setData(dataPage);
            } else {
                List<CampaignDTO> dataExport = query.list();
                result.setData(dataExport);
            }
            result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            result.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception ex) {
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setDescription(Constants.ApiErrorDesc.ERROR);
            logger.error(ex.getMessage(), ex);
        } finally {
            session.close();
        }
        return result;
    }

    @Override
    public ResultDTO findByCampaignCode(CampaignRequestDTO requestDto) {
        logger.info("Start search campaign by code::");
        ResultDTO result = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrEmpty(requestDto.getCompanySiteId())) {
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setDescription(Constants.ApiErrorDesc.ERROR);
            return result;
        }
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(" SELECT CAMPAIGN_ID campaignId, " +
                    "       CAMPAIGN_CODE campaignCode, " +
                    "       CAMPAIGN_NAME campaignName, " +
                    "       START_TIME startTime," +
                    "       END_TIME endTime, " +
                    "       STATUS status " +
                    " FROM CAMPAIGN" +
                    " WHERE COMPANY_SITE_ID = :p_company_site_id AND STATUS <> -1 ");
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignCode())) {
                sb.append(" AND CAMPAIGN_CODE LIKE :p_code ");
            }
            sb.append(" ORDER BY START_TIME DESC ");
            SQLQuery query = session.createSQLQuery(sb.toString());
            query.setParameter("p_company_site_id", requestDto.getCompanySiteId());
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignCode())) {
                query.setParameter("p_code", "%" +
                        requestDto.getCampaignCode().toUpperCase()
                                .replace("\\", "\\\\")
                                .replaceAll("%", "\\\\%")
                                .replaceAll("_", "\\\\_")
                        + "%");
            }
            query.addScalar("campaignId", new LongType());
            query.addScalar("campaignCode", new StringType());
            query.addScalar("campaignName", new StringType());
            query.addScalar("startTime", new DateType());
            query.addScalar("endTime", new DateType());
            query.addScalar("status", new ShortType());

            query.setResultTransformer(Transformers.aliasToBean(CampaignDTO.class));
            int count = 0;
            List<CampaignDTO> list = query.list();
            if (list.size() > 0) {
                count = query.list().size();
            }
            Pageable pageable = SQLBuilder.buildPageable(requestDto);
            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }
            List<CampaignDTO> data = query.list();
            Page<CampaignDTO> dataPage = new PageImpl<>(data, pageable, count);
            result.setData(dataPage);
            result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            result.setDescription(Constants.ApiErrorDesc.SUCCESS);

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

    @Override
    public String getMaxCampaignIndex() {
        logger.info("Start search max campaign code index::");
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        Session session = sessionFactory.openSession();
        session.beginTransaction();
        try {
            //StringBuilder sb = new StringBuilder();
            //sb.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-max-campaign-code-index"));
            StringBuilder sb = new StringBuilder();

            sb.append("SELECT CASE WHEN");
            sb.append("            (SELECT COUNT(1) FROM CAMPAIGN) > 0");
            sb.append("       THEN (SELECT SUBSTR((SELECT CAMPAIGN_CODE FROM CAMPAIGN WHERE CAMPAIGN_ID = (SELECT MAX(CAMPAIGN_ID) FROM CAMPAIGN)),");
            sb.append("                    INSTR((SELECT CAMPAIGN_CODE FROM CAMPAIGN WHERE CAMPAIGN_ID = (SELECT MAX(CAMPAIGN_ID) FROM CAMPAIGN)), '_', -1, 1 )+1) FROM DUAL)");
            sb.append("       ELSE '0'");
            sb.append("       END FROM DUAL");
            SQLQuery query = session.createSQLQuery(sb.toString());
            List<String> list = query.list();
            if (list.size() > 0) {
                return list.get(0);
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public ResultDTO checkAllowStatusToPrepare(Long campaignId) {
        logger.info("Start check allow campaign status to prepare::");
        ResultDTO result = new ResultDTO();
        if (DataUtil.isNullOrZero(campaignId)) {
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setDescription(Constants.ApiErrorDesc.ERROR);
            return result;
        }
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        try {
//            StringBuilder sb = new StringBuilder();
//            sb.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "check-allow-campaign-status-to-prepare"));
            StringBuilder sb = new StringBuilder();

            sb.append(" WITH COUNT_LIST AS (SELECT (SELECT COUNT(1) FROM CAMPAIGN_CUSTOMER WHERE CAMPAIGN_ID = :p_campaignId) countCamp,");
            sb.append("                           (SELECT COUNT(1) FROM CAMPAIGN_AGENT WHERE CAMPAIGN_ID = :p_campaignId)    countAgent,");
            sb.append("                           (select COUNT(1)");
            sb.append("                            FROM SCENARIO s");
            sb.append("                                     INNER JOIN SCENARIO_QUESTION sq ON s.SCENARIO_ID = sq.SCENARIO_ID");
            sb.append("                                     INNER JOIN SCENARIO_ANSWER sa ON sq.SCENARIO_QUESTION_ID = sa.SCENARIO_QUESTION_ID");
            sb.append("                            WHERE s.CAMPAIGN_ID = :p_campaignId)                                      countScenario");
            sb.append("                    FROM DUAL)");
            sb.append(" SELECT c.countCamp          countCamp,");
            sb.append("       c.countAgent         countAgent,");
            sb.append("       c.countScenario      countScenario,");
            sb.append("       CASE");
            sb.append("           WHEN (c.countCamp IS NOT NULL AND c.countAgent IS NOT NULL AND c.countScenario IS NOT NULL) THEN '00'");
            sb.append("           ELSE '01' END as code");
            sb.append(" FROM COUNT_LIST c");

            SQLQuery query = session.createSQLQuery(sb.toString());
            query.setParameter("p_campaignId", campaignId);
            List<Object[]> list = query.list();
            if (list.size() > 0) {
                result.setData(list.get(0));
                result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                result.setDescription(Constants.ApiErrorDesc.SUCCESS);
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setDescription(Constants.ApiErrorDesc.ERROR);
        } finally {
            session.close();
        }
        return result;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO findCustomerListReallocation(CampaignRequestDTO dto) {
        ResultDTO resultDTO = new ResultDTO();
        List<CustomerCustomDTO> list = new ArrayList<>();
        Map<String, String> params = new HashMap<>();
        StringBuilder stringBuilder = new StringBuilder();
        try {
//            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-list-customer-reallocation");
            stringBuilder.append(" with contact as (");
            stringBuilder.append("     select customer_id, contact");
            stringBuilder.append("     from (");
            stringBuilder.append("         select * from customer_contact");
            stringBuilder.append("         where status = 1");
            stringBuilder.append("             and contact_type = 5");
            stringBuilder.append("             and is_direct_line = 1");
            stringBuilder.append("         order by create_date desc");
            stringBuilder.append("     )");
            stringBuilder.append("     where rownum = 1");
            stringBuilder.append(" ),");
            stringBuilder.append(" connect_status as (");
            stringBuilder.append("     select complete_value, complete_name");
            stringBuilder.append("     from campaign_complete_code");
            stringBuilder.append("     where company_site_id = :p_company_site_id");
            stringBuilder.append("         and complete_type = 1");
            stringBuilder.append("         and complete_value <> 1");
            stringBuilder.append(" ),");
            stringBuilder.append(" connect_status_list as (");
            stringBuilder.append("     select trim (regexp_substr(:p_list_connect_status, '[^,]+', 1, level)) connect_status");
            stringBuilder.append("     from dual");
            stringBuilder.append("     connect by level <= regexp_count(:p_list_connect_status, ',') +1");
            stringBuilder.append(" ),");
            stringBuilder.append(" data as (");
            stringBuilder.append("     select  a.campaign_customer_id campaignCustomerId,");
            stringBuilder.append("             b.name customerName,");
            stringBuilder.append("             c.contact mobileNumber,");
            stringBuilder.append("             to_char(a.call_time, 'DD/MM/YYYY HH24:MI:SS') connectTime,");
            stringBuilder.append("             d.complete_name connectStatus");
            stringBuilder.append("     from campaign_customer a");
            stringBuilder.append("     left join customer b on a.customer_id = b.customer_id");
            stringBuilder.append("     left join contact c on a.customer_id = c.customer_id");
            stringBuilder.append("     left join connect_status d on d.complete_value = a.status");
            stringBuilder.append("     where a.campaign_id = :p_campaign_id");
            stringBuilder.append("         and a.in_campaign_status = 1");
            stringBuilder.append("         and a.status in (select connect_status from connect_status_list)");
            stringBuilder.append("     order by connectTime desc, customerName");
            stringBuilder.append(" ),");
            stringBuilder.append(" final_data as (");
            stringBuilder.append("     select a.*, rownum row_ from data a");
            stringBuilder.append(" )");
            stringBuilder.append(" select * from final_data");
            stringBuilder.append(" where row_ >= ((:p_page_number - 1) * :p_page_size + 1)");
            stringBuilder.append("     and row_ < (:p_page_number * :p_page_size + 1)");
            params.put("p_company_site_id", dto.getCompanySiteId());
            params.put("p_campaign_id", dto.getCampaignId());
            params.put("p_list_connect_status", dto.getConnectStatus());
            params.put("p_page_size", dto.getPageSize().toString());
            params.put("p_page_number", dto.getPage().toString());
            list = namedParameterJdbcTemplate.query(stringBuilder.toString(), params, BeanPropertyRowMapper.newInstance(CustomerCustomDTO.class));
            resultDTO.setListData(list);
            resultDTO.setTotalRow(list.size());
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO reallocationCustomer(CampaignRequestDTO dto) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            List<CustomerCustomDTO> list = dto.getCustomerCustomDTOList();
            for (CustomerCustomDTO customerCustomDTO: list) {
                CampaignCustomer campaignCustomer = campaignCustomerRepository.findCampaignCustomerByCampaignCustomerId(customerCustomDTO.getCampaignCustomerId());
                campaignCustomer.setStatus((short) 0);
                campaignCustomer.setCallStatus(null);
                campaignCustomer.setRedistribute((short) 1);
            }
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getListFieldsNotShow(CampaignRequestDTO dto) {
        ResultDTO resultDTO = new ResultDTO();
        Map<String, String> params = new HashMap<>();
        List<FieldsToShowDTO> list = new ArrayList<>();
        StringBuilder stringBuilder = new StringBuilder();
        try {
//            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-list-fields-not-show");
            stringBuilder.append(" with column_name_temp as (");
            stringBuilder.append("     select column_name columnName, 1 isFix from user_tab_columns, dual");
            stringBuilder.append("     where table_name = 'CUSTOMER'");
            stringBuilder.append(" )");
            stringBuilder.append(" select * from column_name_temp");
            stringBuilder.append(" where columnName not in (select column_name from campaign_customerlist_column where column_name is not null)");
            stringBuilder.append(" union all");
            stringBuilder.append(" select title columnName, 0 isFix ");
            stringBuilder.append(" from customize_fields, dual");
            stringBuilder.append(" where function_code = 'CUSTOMER'");
            stringBuilder.append("     and site_id = :p_company_site_id");
            stringBuilder.append("     and customize_field_id not in (select customize_field_id");
            stringBuilder.append("                                     from campaign_customerlist_column");
            stringBuilder.append("                                     where campaign_customerlist_column.campaign_id = :p_campaign_id)");
            params.put("p_company_site_id", dto.getCompanySiteId());
            params.put("p_campaign_id", dto.getCampaignId());
            list = namedParameterJdbcTemplate.query(stringBuilder.toString(), params, BeanPropertyRowMapper.newInstance(FieldsToShowDTO.class));
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            resultDTO.setListData(list);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getListFieldsToShow(CampaignRequestDTO dto) {
        ResultDTO resultDTO = new ResultDTO();
        Map<String, String> params = new HashMap<>();
        List<FieldsToShowDTO> list = new ArrayList<>();
        StringBuilder sqlBuilder = new StringBuilder();
        try {
//            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-list-fields-to-show");
            sqlBuilder.append(" select to_char(column_name) columnName, 1 isFix");
            sqlBuilder.append(" from campaign_customerlist_column, dual");
            sqlBuilder.append(" where campaign_id = :p_campaign_id and column_name is not null");
            sqlBuilder.append(" union all");
            sqlBuilder.append(" select customize_field_title columnName, 0 isFix");
            sqlBuilder.append(" from campaign_customerlist_column");
            sqlBuilder.append(" where campaign_id = :p_campaign_id");
            params.put("p_campaign_id", dto.getCampaignId());
            list = namedParameterJdbcTemplate.query(sqlBuilder.toString(), params, BeanPropertyRowMapper.newInstance(FieldsToShowDTO.class));
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            resultDTO.setListData(list);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getCampaignCustomerList(CampaignRequestDTO dto) {
        List<CustomerListDTO> list = new ArrayList();
        ResultDTO resultDTO = new ResultDTO();
        Map<String, String> params = new HashMap<>();

//        StringBuilder sb = new StringBuilder();
        try {
//            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-list-campaign-customer");
            String sql = "with campaign_customer_id as (\n" +
                    "    select ccl.CUSTOMER_LIST_ID from campaign_customerlist ccl\n" +
                    "    where ccl.campaign_id = :p_campaign_id and ccl.company_site_id = :p_company_site_id\n" +
                    "),\n" +
                    "customer_table as (\n" +
                    "    select count(a.customer_id) totalCustomer, a.customer_list_id customerListId from customer_list_mapping a\n" +
                    "    left join customer b on a.customer_id = b.customer_id\n" +
                    "    where b.status = 1\n" +
                    "    group by a.customer_list_id\n" +
                    "),\n" +
                    "campaign_customer_table as (\n" +
                    "    select count(a.customer_id) campaignCustomer, a.customer_list_id customerListId, a.campaign_id from campaign_customer a\n" +
                    "    where a.campaign_id = :p_campaign_id\n" +
                    "    group by a.customer_list_id, a.campaign_id\n" +
                    "),\n" +
                    "customer_interactive_table as (\n" +
                    "    select count(a.customer_id) campaignCustomerCalled, a.customer_list_id customerListId, a.campaign_id from campaign_customer a\n" +
                    "    where a.status <> 0 and a.campaign_id = :p_campaign_id\n" +
                    "    group by a.customer_list_id, a.campaign_id\n" +
                    "),\n" +
                    "customer_not_interactive_table as (\n" +
                    "    select count(a.customer_id) cusNotInteractive, a.customer_list_id customerListId, a.campaign_id from campaign_customer a\n" +
                    "    where a.status = 0 and a.campaign_id = :p_campaign_id and a.in_campaign_status = 1\n" +
                    "    group by a.customer_list_id, a.campaign_id\n" +
                    "),\n" +
                    "data_temp as (\n" +
                    "select  a.customer_list_id customerListId,\n" +
                    "        a.customer_list_code customerListCode,\n" +
                    "        a.customer_list_name customerListName,\n" +
                    "        nvl(b.totalCustomer, 0) totalCusList,\n" +
                    "        nvl(c.campaignCustomer, 0) totalCusCampaign,\n" +
                    "        nvl(d.campaignCustomerCalled, 0) totalCusCalled,\n" +
                    "        nvl(e.cusNotInteractive, 0) totalCusNotInteract\n" +
                    "from customer_list a\n" +
                    "left join customer_table b on a.customer_list_id = b.customerListId\n" +
                    "left join campaign_customer_table c on a.customer_list_id = c.customerListId\n" +
                    "left join customer_interactive_table d on a.customer_list_id = d.customerListId\n" +
                    "left join customer_not_interactive_table e on a.customer_list_id = e.customerListId\n" +
                    "where a.customer_list_id in (select CUSTOMER_LIST_ID from campaign_customer_id)\n" +
                    "),\n" +
                    "data as (\n" +
                    "select a.*, rownum row_ from data_temp a\n" +
                    "),\n" +
                    "count_data as (\n" +
                    "select count(*) totalRow from data_temp\n" +
                    ")\n" +
                    "select a.customerListId, a.customerListCode, a.customerListName, a.totalCusList, a.totalCusCampaign, a.totalCusCalled, a.totalCusNotInteract, totalRow from data a, count_data\n" +
                    "where row_ >= ((:p_page_number - 1) * :p_page_size + 1) and row_ < (:p_page_number * :p_page_size + 1)\n";
            params.put("p_campaign_id", dto.getCampaignId());
            params.put("p_company_site_id", dto.getCompanySiteId());
            params.put("p_page_number", dto.getPage().toString());
            params.put("p_page_size", dto.getPageSize().toString());
            list = namedParameterJdbcTemplate.query(sql, params, BeanPropertyRowMapper.newInstance(CustomerListDTO.class));
            int total = 0;
            if (list.size() > 0) {
                total = list.get(0).getTotalRow();
            }
            resultDTO.setListData(list);
            resultDTO.setTotalRow(total);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

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

        Session session = sessionFactory.openSession();
        session.beginTransaction();
//        Map<String, String> params = new HashMap<>();

        StringBuilder sb = new StringBuilder();
        try {
//            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-customer-list");
            sb.append(" with campaign_customer_id as (");
            sb.append("     select ccl.CUSTOMER_LIST_ID from campaign_customerlist ccl");
            sb.append("     where ccl.campaign_id = :p_campaign_id and ccl.company_site_id = :p_company_site_id");
            sb.append(" ),");
            sb.append(" customer_table as (");
            sb.append("     select count(a.customer_id) totalCustomer, a.customer_list_id customerListId from customer_list_mapping a");
            sb.append("     left join customer b on a.customer_id = b.customer_id");
            sb.append("     where b.status = 1");
            sb.append("     group by a.customer_list_id");
            sb.append(" ),");
            sb.append(" customer_active_table as (");
            sb.append("     select count(a.customer_id) customerActive, a.customer_list_id customerListId from customer_list_mapping a");
            sb.append("     left join customer b on a.customer_id = b.customer_id");
            sb.append("     where b.status = 1 and b.ipcc_status = 'active'");
            sb.append("     group by a.customer_list_id");
            sb.append(" ),");
            sb.append(" customer_lock_table as (");
            sb.append("     select count(a.customer_id) customerLock, a.customer_list_id customerListId from customer_list_mapping a");
            sb.append("     left join customer b on a.customer_id = b.customer_id");
            sb.append("     where b.status = 1 and b.ipcc_status = 'locked'");
            sb.append("     group by a.customer_list_id");
            sb.append(" ),");
            sb.append(" customer_dnc_table as (");
            sb.append("     select count(a.customer_id) customerDnc, a.customer_list_id customerListId from customer_list_mapping a");
            sb.append("     left join customer b on a.customer_id = b.customer_id");
            sb.append("     where b.status = 1 and b.call_allowed = 0");
            sb.append("     group by a.customer_list_id");
            sb.append(" ),");
            sb.append(" data_temp as (");
            sb.append(" select  a.customer_list_id customerListId,");
            sb.append("         a.customer_list_code customerListCode,");
            sb.append("         a.customer_list_name customerListName,");
            sb.append("         nvl(b.totalCustomer, 0) totalCusList,");
            sb.append("         nvl(c.customerActive, 0) totalCusActive,");
            sb.append("         nvl(d.customerLock, 0) totalCusLock,");
            sb.append("         nvl(e.customerDnc, 0) totalCusDnc,");
            sb.append("         a.create_at createAt,");
            sb.append("         a.company_site_id companySiteId,");
            sb.append("         a.status status");
            sb.append(" from customer_list a");
            sb.append(" left join customer_table b on a.customer_list_id = b.customerListId");
            sb.append(" left join customer_active_table c on a.customer_list_id = c.customerListId");
            sb.append(" left join customer_lock_table d on a.customer_list_id = d.customerListId");
            sb.append(" left join customer_dnc_table e on a.customer_list_id = e.customerListId");
            sb.append(" where a.status = 1");
            sb.append("     and (:p_cus_list_code is null or upper(a.customer_list_code) like '%'||:p_cus_list_code||'%')");
            sb.append("     and (:p_cus_list_name is null or upper(a.customer_list_name) like '%'||:p_cus_list_name||'%')");
            sb.append("     and (a.create_at <= to_date(:p_to_date, 'DD/MM/YYYY'))");
            sb.append("     and (a.create_at >= to_date(:p_from_date, 'DD/MM/YYYY'))");
            sb.append("     and (a.company_site_id = :p_company_site_id)");
            sb.append("     and (a.customer_list_id not in (select CUSTOMER_LIST_ID from campaign_customer_id))");
            sb.append(" ),");
            sb.append(" data as (");
            sb.append(" select a.*, rownum row_ from data_temp a");
            sb.append(" ),");
            sb.append(" count_data as (");
            sb.append(" select count(*) totalRow from data_temp");
            sb.append(" )");
            sb.append(" select a.customerListId, a.customerListCode, a.customerListName, a.totalCusList, a.totalCusActive, a.totalCusLock, a.totalCusDnc, totalRow from data a, count_data");
            sb.append(" where row_ >= ((:p_page_number - 1) * :p_page_size + 1) and row_ < (:p_page_number * :p_page_size + 1)");
//            params.put("p_campaign_id", dto.getCampaignId());
//            params.put("p_cus_list_code", DataUtil.isNullOrEmpty(dto.getCustListCode()) ? null : dto.getCustListCode().toUpperCase());
//            params.put("p_cus_list_name", DataUtil.isNullOrEmpty(dto.getCustListName()) ? null : dto.getCustListName().toUpperCase());
//            params.put("p_to_date", dto.getCreateTimeTo());
//            params.put("p_from_date", dto.getCreateTimeFr());
//            params.put("p_company_site_id", dto.getCompanySiteId());
//            params.put("p_page_number", dto.getPage().toString());
//            params.put("p_page_size", dto.getPageSize().toString());
//
//            list = namedParameterJdbcTemplate.query(sb.toString(), params, BeanPropertyRowMapper.newInstance(CustomerListDTO.class));
            SQLQuery query = session.createSQLQuery(sb.toString());
            query.setParameter("p_company_site_id", dto.getCompanySiteId());
            query.setParameter("p_campaign_id", dto.getCampaignId());
            query.setParameter("p_cus_list_code", DataUtil.isNullOrEmpty(dto.getCustListCode()) ? null : dto.getCustListCode().toUpperCase());
            query.setParameter("p_cus_list_name", DataUtil.isNullOrEmpty(dto.getCustListName()) ? null : dto.getCustListName().toUpperCase());
            query.setParameter("p_to_date", dto.getCreateTimeTo());
            query.setParameter("p_from_date", dto.getCreateTimeFr());
            query.setParameter("p_page_number", dto.getPage());
            query.setParameter("p_page_size", dto.getPageSize());

            query.addScalar("customerListId", new LongType());
            query.addScalar("customerListCode", new StringType());
            query.addScalar("customerListName", new StringType());
            query.addScalar("totalCusList", new LongType());
            query.addScalar("totalCusActive", new LongType());
            query.addScalar("totalCusLock", new LongType());
            query.addScalar("totalCusDnc", new LongType());
            query.addScalar("totalRow", new IntegerType());

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

            int total = 0;
            list = query.list();
            if (list.size() > 0) {
                total = list.get(0).getTotalRow();
            }
            resultDTO.setListData(list);
            resultDTO.setTotalRow(total);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        } finally {
            session.close();
            return resultDTO;
        }
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getCustomerChoosenList(CampaignRequestDTO dto) {
        List<CustomerListDTO> list = new ArrayList();
        ResultDTO resultDTO = new ResultDTO();
        Map<String, String> params = new HashMap<>();

//        StringBuilder sb = new StringBuilder();
        try {
//            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-customer-list-choosen");
            String sql = "with campaign_customer_id as (\n" +
                    "    select ccl.CUSTOMER_LIST_ID from campaign_customerlist ccl\n" +
                    "    where ccl.campaign_id = :p_campaign_id and ccl.company_site_id = :p_company_site_id\n" +
                    "),\n" +
                    "customer_table as (\n" +
                    "    select count(a.customer_id) totalCustomer, a.customer_list_id customerListId from customer_list_mapping a\n" +
                    "    left join customer b on a.customer_id = b.customer_id\n" +
                    "    where b.status = 1\n" +
                    "    group by a.customer_list_id\n" +
                    "),\n" +
                    "customer_active_table as (\n" +
                    "    select count(a.customer_id) customerActive, a.customer_list_id customerListId from customer_list_mapping a\n" +
                    "    left join customer b on a.customer_id = b.customer_id\n" +
                    "    where b.status = 1 and b.ipcc_status = 'active'\n" +
                    "    group by a.customer_list_id\n" +
                    "),\n" +
                    "customer_lock_table as (\n" +
                    "    select count(a.customer_id) customerLock, a.customer_list_id customerListId from customer_list_mapping a\n" +
                    "    left join customer b on a.customer_id = b.customer_id\n" +
                    "    where b.status = 1 and b.ipcc_status = 'locked'\n" +
                    "    group by a.customer_list_id\n" +
                    "),\n" +
                    "customer_dnc_table as (\n" +
                    "    select count(a.customer_id) customerDnc, a.customer_list_id customerListId from customer_list_mapping a\n" +
                    "    left join customer b on a.customer_id = b.customer_id\n" +
                    "    where b.status = 1 and b.call_allowed = 0\n" +
                    "    group by a.customer_list_id\n" +
                    "),\n" +
                    "customer_filter_table as (\n" +
                    "    select count(a.customer_id) customerFilter, a.customer_list_id customerListId from campaign_customer a\n" +
                    "    where a.campaign_id = :p_campaign_id\n" +
                    "    group by a.customer_list_id\n" +
                    "),\n" +
                    "data_temp as (\n" +
                    "select  a.customer_list_id customerListId,\n" +
                    "        a.customer_list_code customerListCode,\n" +
                    "        a.customer_list_name customerListName,\n" +
                    "        nvl(b.totalCustomer, 0) totalCusList,\n" +
                    "        nvl(c.customerActive, 0) totalCusActive,\n" +
                    "        nvl(d.customerLock, 0) totalCusLock,\n" +
                    "        nvl(e.customerDnc, 0) totalCusDnc,\n" +
                    "        nvl(null, 0) totalCusAddRemove,\n" +
                    "        nvl(f.customerFilter, 0) totalCusFilter\n" +
                    "from customer_list a\n" +
                    "left join customer_table b on a.customer_list_id = b.customerListId\n" +
                    "left join customer_active_table c on a.customer_list_id = c.customerListId\n" +
                    "left join customer_lock_table d on a.customer_list_id = d.customerListId\n" +
                    "left join customer_dnc_table e on a.customer_list_id = e.customerListId\n" +
                    "left join customer_filter_table f on a.customer_list_id = f.customerListId\n" +
                    "where a.customer_list_id in (select CUSTOMER_LIST_ID from campaign_customer_id)\n" +
                    "),\n" +
                    "data as (\n" +
                    "select a.*, rownum row_ from data_temp a\n" +
                    "),\n" +
                    "count_data as (\n" +
                    "select count(*) totalRow from data_temp\n" +
                    ")\n" +
                    "select a.customerListId, a.customerListCode, a.customerListName, a.totalCusList, a.totalCusActive, a.totalCusLock, a.totalCusDnc, a.totalCusAddRemove, a.totalCusFilter totalRow from data a, count_data\n" +
                    "where row_ >= ((:p_page_number - 1) * :p_page_size + 1) and row_ < (:p_page_number * :p_page_size + 1)\n";
            params.put("p_campaign_id", dto.getCampaignId());
            params.put("p_company_site_id", dto.getCompanySiteId());
            params.put("p_page_number", dto.getPage().toString());
            params.put("p_page_size", dto.getPageSize().toString());
            list = namedParameterJdbcTemplate.query(sql, params, BeanPropertyRowMapper.newInstance(CustomerListDTO.class));
            int total = 0;
            if (list.size() > 0) {
                total = list.get(0).getTotalRow();
            }
            resultDTO.setListData(list);
            resultDTO.setTotalRow(total);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

}
