package com.viettel.campaign.service.impl;

import com.viettel.campaign.config.DataSourceQualify;
import com.viettel.campaign.mapper.CustomerListMapper;
import com.viettel.campaign.mapper.CustomerMapper;
import com.viettel.campaign.model.ccms_full.Customer;
import com.viettel.campaign.model.ccms_full.CustomerContact;
import com.viettel.campaign.model.ccms_full.CustomerList;
import com.viettel.campaign.repository.ccms_full.*;
import com.viettel.campaign.service.CustomerService;
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.CustomerDetailRequestDTO;
import com.viettel.campaign.web.dto.request_dto.CustomerRequestDTO;
import com.viettel.campaign.web.dto.request_dto.SearchCustomerRequestDTO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
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.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.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.*;

@Service
public class CustomerServiceImpl implements CustomerService {

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

    @Autowired
    CustomerRepository customerRepository;

    @Autowired
    CustomerListRepository customerListRepository;

    @Autowired
    CustomerContactRepository customerContactRepository;

    @Autowired
    CampaignCustomerListRepository campaignCustomerListRepository;

    @Autowired
    CampaignCustomerRepository campaignCustomerRepository;

    @Autowired
    CustomerListMappingRepository customerListMappingRepository;

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

    @Autowired
    VSAUsersRepository vsaUsersRepository;

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getAllCustomer(int page, int pageSize, String sort, long customerListId, long companySiteId) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrZero(companySiteId)) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            return resultDTO;
        }

        try {
            StringBuilder sqlStrBuilder = new StringBuilder();
            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "campaign-customer-detail-by-params"));

            sqlStrBuilder.append(" ORDER BY b.NAME ASC");

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

            query.setParameter("p_company_site_id", companySiteId);
            query.setParameter("p_customer_list_id", customerListId);

            query.addScalar("customerListMappingId", new LongType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("customerListId", new LongType());
            query.addScalar("customerId", new LongType());
            query.addScalar("name", new StringType());
            query.addScalar("description", new StringType());
            query.addScalar("companyName", new StringType());
            query.addScalar("customerType", new StringType());
            query.addScalar("currentAddress", new StringType());
            query.addScalar("callAllowed", new ShortType());
            query.addScalar("emailAllowed", new ShortType());
            query.addScalar("smsAllowed", new ShortType());
            query.addScalar("ipccStatus", new StringType());
            query.addScalar("mobileNumber", new StringType());
            query.addScalar("email", new StringType());

            query.setResultTransformer(Transformers.aliasToBean(CustomerCustomDTO.class));
            int count = 0;
            List<CustomerCustomDTO> dtoList = query.list();
            if (dtoList.size() > 0) {
                count = query.list().size();
            }

            Pageable pageable = PageRequest.of(page, pageSize, Sort.by(Sort.Order.desc(sort)));
            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }

            List<CustomerCustomDTO> data = query.list();
            Page<CustomerCustomDTO> 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);
        } finally {
            session.close();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getCustomerId(Long customerId) {
        ResultDTO resultDTO = new ResultDTO();

        List<Customer> customer = customerRepository.findByCustomerId(customerId);

        if (customer != null) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription("customer data");
            resultDTO.setListData(customer);
        } else {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription("customer data null");
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO searchAllCustomer(int page, int pageSize, String sort, long customerListId, long companySiteId, String name, String mobileNumber, String email) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrZero(companySiteId)) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            return resultDTO;
        }

        try {
            StringBuilder sqlStrBuilder = new StringBuilder();
            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "campaign-customer-detail-by-params"));

            if (!DataUtil.isNullOrEmpty(name)) {
                sqlStrBuilder.append(" AND UPPER(b.NAME) LIKE UPPER(:p_name)");
            }
            if (!DataUtil.isNullOrEmpty(mobileNumber)) {
                sqlStrBuilder.append(" AND UPPER(c.MOBILE) LIKE UPPER(:p_mobile_number)");
            }
            if (!DataUtil.isNullOrEmpty(email)) {
                sqlStrBuilder.append(" AND UPPER(d.EMAIL) LIKE UPPER(:p_email)");
            }
            sqlStrBuilder.append(" ORDER BY name DESC");

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

            query.setParameter("p_company_site_id", companySiteId);
            query.setParameter("p_customer_list_id", customerListId);

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

            if (!DataUtil.isNullOrEmpty(mobileNumber)) {
                query.setParameter("p_mobile_number", "%" +
                        mobileNumber.replace("\\", "\\\\")
                                .replaceAll("%", "\\%")
                                .replaceAll("_", "\\_")
                        + "%");
            }

            if (!DataUtil.isNullOrEmpty(email)) {
                query.setParameter("p_email", "%" +
                        email.replace("\\", "\\\\")
                                .replaceAll("%", "\\%")
                                .replaceAll("_", "\\_")
                        + "%");
            }

            query.addScalar("customerListMappingId", new LongType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("customerListId", new LongType());
            query.addScalar("customerId", new LongType());
            query.addScalar("name", new StringType());
            query.addScalar("description", new StringType());
            query.addScalar("companyName", new StringType());
            query.addScalar("customerType", new StringType());
            query.addScalar("currentAddress", new StringType());
            query.addScalar("mobileNumber", new StringType());
            query.addScalar("email", new StringType());

            query.setResultTransformer(Transformers.aliasToBean(CustomerCustomDTO.class));
            int count = 0;
            List<CustomerCustomDTO> dtoList = query.list();
            if (dtoList.size() > 0) {
                count = query.list().size();
            }

            Pageable pageable = PageRequest.of(page, pageSize, Sort.by(Sort.Order.desc(sort)));
            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }

            List<CustomerCustomDTO> data = query.list();
            Page<CustomerCustomDTO> 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);
        } finally {
            session.close();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO createCustomer(CustomerDTO customerDTO) {
        ResultDTO resultDTO = new ResultDTO();
        CustomerMapper customerMapper = new CustomerMapper();
        Customer customer = new Customer();

        try {
            if (customerDTO != null) {
                //check trung mobile number
                Long cusExist = customerRepository.findByMobileNumberAndSiteId(customerDTO.getMobileNumber(), customerDTO.getSiteId());
                if (cusExist > 0) {
                    resultDTO.setErrorCode("-7");
                    resultDTO.setDescription("Mobile number is existed");
                    return resultDTO;
                }

                // insert
                customer = customerMapper.toPersistenceBean(customerDTO);
                customer.setCreateDate(new Date());
                customer = customerRepository.save(customer);

                resultDTO.setErrorCode(customer.getCustomerId() + "");
                resultDTO.setDescription("customer created");
            } else {
                resultDTO.setErrorCode("-2");
                resultDTO.setDescription("customerDTO null");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteCustomer(CustomerRequestDTO customerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (customerRequestDTO != null) {
                // delete
//                customerRepository.deleteById(customerDTO.getCustomerId());
                customerListMappingRepository.deleteMappingByCustomerId(customerRequestDTO.getCustomerId(), customerRequestDTO.getCustomerListId(), customerRequestDTO.getCompanySiteId());

                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteIds(CustomerRequestDTO customerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (customerRequestDTO != null) {
//                customerRepository.deleteIds(ids);
                customerListMappingRepository.deleteMappingByCustomerIds(customerRequestDTO.getIds(), customerRequestDTO.getCustomerListId(), customerRequestDTO.getCompanySiteId());
                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultDTO;
    }

    @Override
    public ResultDTO getCustomerDetailById(Long companySiteId, Long customerListId, Long customerId) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrZero(companySiteId)) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            return resultDTO;
        }

        try {
            StringBuilder sqlStrBuilder = new StringBuilder();
            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-customer-detail-by-id"));

            sqlStrBuilder.append(" AND e.FUNCTION_CODE = 'CUSTOMER'");

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

            query.setParameter("p_company_site_id", companySiteId);
            query.setParameter("p_customer_list_id", customerListId);
            query.setParameter("p_customer_id", customerId);

            query.addScalar("companySiteId", new LongType());
            query.addScalar("customerListId", new LongType());
            query.addScalar("customerId", new LongType());
            query.addScalar("title", new StringType());
            query.addScalar("type", new StringType());
            query.addScalar("valueCombobox", new StringType());
            query.addScalar("valueCheckbox", new ShortType());
            query.addScalar("valueDate", new DateType());
            query.addScalar("valueNumber", new LongType());
            query.addScalar("valueText", new StringType());

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

            List<CustomerDetailRequestDTO> data = query.list();
            resultDTO.setData(data);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        } finally {
            session.close();
        }

        return resultDTO;
    }

    public Date getSysdate() {
        try {
            Query query = entityManager.createNativeQuery("SELECT to_char(sysdate, 'dd/MM/YYYY hh24:mi:ss') FROM DUAL ");
            List list = query.getResultList();
            if (list != null && list.size() > 0) {
                return DataUtil.convertStringToDateDDMMYYYYHHMISS(DataUtil.safeToString(list.get(0)));
            }
        } catch (Exception e) {
            //logger.info(e.getMessage(), e);
            e.printStackTrace();
        }
        return new Date();
    }

    // ------------- customer list ----------------- //

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getAllCustomerList(int page, int pageSize, String sort, Long companySiteId) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrZero(companySiteId)) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            return resultDTO;
        }

        try {
            StringBuilder sqlStrBuilder = new StringBuilder();
            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "search-campaign-customer-by-params"));

            sqlStrBuilder.append(" ORDER BY CREATE_AT DESC");

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

            query.setParameter("p_company_site_id", companySiteId);

            query.addScalar("customerListId", new LongType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("customerListCode", new StringType());
            query.addScalar("customerListName", new StringType());
            query.addScalar("status", new ShortType());
            query.addScalar("createBy", new StringType());
            query.addScalar("createAt", new DateType());
            query.addScalar("updateBy", new StringType());
            query.addScalar("updateAt", new DateType());
            query.addScalar("source", new StringType());
            query.addScalar("deptCreate", new StringType());

            query.setResultTransformer(Transformers.aliasToBean(CustomerListDTO.class));
            int count = 0;
            List<CustomerListDTO> dtoList = query.list();
            if (dtoList.size() > 0) {
                count = query.list().size();
            }

            Pageable pageable = PageRequest.of(page, pageSize, Sort.by(Sort.Order.desc(sort)));
            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }

            List<CustomerListDTO> data = query.list();
            Page<CustomerListDTO> 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);
        } finally {
            session.close();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO createCustomerList(CustomerListDTO customerListDTO) {
        ResultDTO resultDTO = new ResultDTO();
        CustomerListMapper customerListMapper = new CustomerListMapper();
        CustomerList customerList = new CustomerList();
        try {
            if (customerListDTO != null) {
                // insert
                CustomerList findCustomer = customerListRepository.findByCustomerListCode(customerListDTO.getCustomerListCode());
                if (findCustomer == null) {
                    customerList = customerListMapper.toPersistenceBean(customerListDTO);
                    customerListRepository.save(customerList);

                    resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                    resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
                } else {
                    resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                    resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
                }
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO updateCustomerList(CustomerListDTO customerListDTO) {
        ResultDTO resultDTO = new ResultDTO();
        CustomerListMapper customerListMapper = new CustomerListMapper();

        try {
            if (customerListDTO != null) {
                // update
                CustomerList customerList = customerListRepository.findByCustomerListIdAndCompanySiteId(customerListDTO.getCustomerListId(), customerListDTO.getCompanySiteId());

                if (customerList != null) {
                    customerList = customerListMapper.toPersistenceBean(customerListDTO);
                    customerListRepository.save(customerList);

                    resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                    resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
                } else {
                    resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                    resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
                }
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteCustomerList(CustomerListDTO customerListDTO) {
        ResultDTO resultDTO = new ResultDTO();

        try {
            // delete
            if (DataUtil.isNullOrZero(campaignCustomerListRepository.campaignCount(customerListDTO.getCustomerListId()))) {

                customerListRepository.deleteCustomerList(customerListDTO.getCustomerListId(), customerListDTO.getCompanySiteId());

                customerListMappingRepository.deleteMappingByCustomerListId(customerListDTO.getCustomerListId(), customerListDTO.getCompanySiteId());

                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }

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

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteCustomerListIds(CustomerRequestDTO customerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (customerRequestDTO != null) {
                if (DataUtil.isNullOrZero(campaignCustomerListRepository.campaignIdsCount(customerRequestDTO.getIds()))) {
                    customerListRepository.deleteCustomerListIds(customerRequestDTO.getIds(), customerRequestDTO.getCompanySiteId());

                    customerListMappingRepository.deleteMappingByCustomerListIds(customerRequestDTO.getIds(), customerRequestDTO.getCompanySiteId());

                    resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                    resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
                } else {
                    resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                    resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
                }
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO searchCustomerList(SearchCustomerRequestDTO searchCustomerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        if (DataUtil.isNullOrEmpty(searchCustomerRequestDTO.getCompanySiteId())) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            return resultDTO;
        }

        try {
            StringBuilder sqlStrBuilder = new StringBuilder();
            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "search-campaign-customer-by-params"));

            sqlStrBuilder.append(" AND CREATE_AT BETWEEN to_date(:p_date_from, 'YYYYMMDD') AND to_date(:p_date_to, 'YYYYMMDD')");

            if (!DataUtil.isNullOrEmpty(searchCustomerRequestDTO.getCustomerListCode())) {
                sqlStrBuilder.append(" AND UPPER(CUSTOMER_LIST_CODE) LIKE UPPER(:p_list_code)");
            }
            if (!DataUtil.isNullOrEmpty(searchCustomerRequestDTO.getCustomerListName())) {
                sqlStrBuilder.append(" AND UPPER(CUSTOMER_LIST_NAME) LIKE UPPER(:p_list_name)");
            }

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

            query.setParameter("p_company_site_id", searchCustomerRequestDTO.getCompanySiteId());
            query.setParameter("p_date_from", searchCustomerRequestDTO.getConvertedDateFrom());
            query.setParameter("p_date_to", searchCustomerRequestDTO.getConvertedDateTo());

            if (!DataUtil.isNullOrEmpty(searchCustomerRequestDTO.getCustomerListCode())) {
                query.setParameter("p_list_code", "%" +
                        searchCustomerRequestDTO.getCustomerListCode()
                                .replace("\\", "\\\\")
                                .replaceAll("%", "\\%")
                                .replaceAll("_", "\\_")
                        + "%");
            }

            if (!DataUtil.isNullOrEmpty(searchCustomerRequestDTO.getCustomerListName())) {
                query.setParameter("p_list_name", "%" +
                        searchCustomerRequestDTO.getCustomerListName()
                                .replace("\\", "\\\\")
                                .replaceAll("%", "\\%")
                                .replaceAll("_", "\\_")
                        + "%");
            }

            query.addScalar("customerListId", new LongType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("customerListCode", new StringType());
            query.addScalar("customerListName", new StringType());
            query.addScalar("status", new ShortType());
            query.addScalar("createBy", new StringType());
            query.addScalar("createAt", new DateType());
            query.addScalar("updateBy", new StringType());
            query.addScalar("updateAt", new DateType());
            query.addScalar("source", new StringType());
            query.addScalar("deptCreate", new StringType());

            query.setResultTransformer(Transformers.aliasToBean(CustomerListDTO.class));
            int count = 0;
            List<CustomerListDTO> dtoList = query.list();
            if (dtoList.size() > 0) {
                count = query.list().size();
            }

            Pageable pageable = PageRequest.of(searchCustomerRequestDTO.getPage(), searchCustomerRequestDTO.getPageSize(), Sort.by(searchCustomerRequestDTO.getSort()));
            if (pageable != null) {
                query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
                query.setMaxResults(pageable.getPageSize());
            }

            List<CustomerListDTO> data = query.list();
            Page<CustomerListDTO> 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);
        } finally {
            session.close();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public CustomerList getLatestCreated(Long companySiteId) {
        return customerListRepository.latestCreated(companySiteId);
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getCustomerContact(CustomerContactDTO customer) {
        ResultDTO result = new ResultDTO();

        try {
            List<CustomerContact> data = customerContactRepository.findByCustomerIdAndAndContactTypeAndContact(customer.getCustomerId(), customer.getContactType(), customer.getContact(), SQLBuilder.buildPageable(customer));

            if (customer != null) {
                result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                result.setDescription("customer contact data");
                result.setListData(data);
                result.setTotalRow(customerContactRepository.findByCustomerIdAndAndContactTypeAndContact(customer.getCustomerId(), customer.getContactType(), customer.getContact(), null).size());

            } else {
                result.setErrorCode(Constants.ApiErrorCode.ERROR);
                result.setDescription("customer contact data null");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getCustomerRecall(Long campaignId, Long customerId) {
        ResultDTO result = new ResultDTO();

        try {
            Long data = campaignCustomerRepository.getCustomerRecall(campaignId, customerId);

            if (data != null) {
                result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                result.setDescription("campaign customer data");
                result.setData(data);

            } else {
                result.setErrorCode(Constants.ApiErrorCode.ERROR);
                result.setDescription("campaign customer data null");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public List<DynamicExcelHeaderDTO> getDynamicHeader(Long companySiteId) {
        List<DynamicExcelHeaderDTO> headerList;
        try {
            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_CUSTOMER_MNG, "get-dynamic-header");
            Map<String, Object> param = new HashMap<>();
            param.put("p_company_site_id", companySiteId);
            headerList = namedParameterJdbcTemplate.query(sql, param, new BeanPropertyRowMapper<>(DynamicExcelHeaderDTO.class));
        } catch (Exception e) {
            return null;
        }
        return headerList;
    }

    @Override
    public void buildTemplate(Long companySiteId) {
        try {
            List<DynamicExcelHeaderDTO> headerList = getDynamicHeader(companySiteId);
            FileInputStream fis = new FileInputStream(ResourceUtils.getFile("classpath:templates/import_customer_template.xlsx"));
            XSSFWorkbook workbook = new XSSFWorkbook(fis);
            XSSFSheet sheet = workbook.getSheetAt(0);
            Row row = sheet.getRow(2);
            Cell cell = row.createCell(row.getPhysicalNumberOfCells());
            cell.setCellType(CellType.STRING);
            cell.setCellValue("test");
            FileOutputStream fos = new FileOutputStream(ResourceUtils.getFile("classpath:templates/import_customer_template.xlsx"));
            workbook.write(fos);
            fos.close();
            workbook.close();
        } catch (Exception e) {

        }
    }

    @Override
    public List<CustomizeFieldDTO> getCustomizeField(Long customerId) {
        List<CustomizeFieldDTO> customizeFieldDTOList;
        try {
            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "get-customize-field");
            Map<String, Object> param = new HashMap<>();
            param.put("p_customer_id", customerId);
            customizeFieldDTOList = namedParameterJdbcTemplate.query(sql, param, new BeanPropertyRowMapper<>(CustomizeFieldDTO.class));
        } catch (Exception e) {
            return null;
        }
        return customizeFieldDTOList;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<CustomerListDTO> getCustomerListInfo(CampaignCustomerDTO campaignCustomerDTO) {
        List<CustomerListDTO> customerList;
        try {
            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "search-customer-list-info-from-customer-list");
            Map<String, Object> param = new HashMap<>();
            param.put("p_campaign_id", campaignCustomerDTO.getCampaignId());
            param.put("p_company_site_id", campaignCustomerDTO.getCompanySiteId());
            param.put("p_page_number", campaignCustomerDTO.getPage());
            param.put("p_page_size", campaignCustomerDTO.getPageSize());
            customerList = namedParameterJdbcTemplate.query(sql, param, new BeanPropertyRowMapper<>(CustomerListDTO.class));
        } catch (Exception e) {
            return null;
        }
        return customerList;
    }

    @Override
    public List<CustomerDTO> getIndividualCustomerInfo(CampaignCustomerDTO campaignCustomerDTO) {
        List<CustomerDTO> customerList;
        try {
            String sql = SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "search-individual-customer");
            Map<String, Object> param = new HashMap<>();
            param.put("p_page_number", campaignCustomerDTO.getPage());
            param.put("p_page_size", campaignCustomerDTO.getPageSize());
            customerList = namedParameterJdbcTemplate.query(sql, param, new BeanPropertyRowMapper<>(CustomerDTO.class));
        } catch (Exception e) {
            return null;
        }
        return customerList;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<Customer> findAllByCondition(Long siteId, Date endTime) {
        return customerRepository.findAllByCondition(siteId, endTime);
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public Customer update(Customer c) {
        return customerRepository.save(c);
    }
}
