package com.viettel.campaign.service.impl;

import com.github.tennaito.rsql.jpa.JpaCriteriaCountQueryVisitor;
import com.github.tennaito.rsql.jpa.JpaCriteriaQueryVisitor;
import com.viettel.campaign.config.DataSourceQualify;
import com.viettel.campaign.mapper.CustomerMapper;
import com.viettel.campaign.model.ccms_full.*;
import com.viettel.campaign.repository.ccms_full.*;
import com.viettel.campaign.service.CustomerService;
import com.viettel.campaign.utils.*;
import com.viettel.campaign.web.dto.*;
import com.viettel.campaign.web.dto.request_dto.CustomerQueryDTO;
import com.viettel.campaign.web.dto.request_dto.CustomerRequestDTO;
import com.viettel.campaign.web.dto.request_dto.SearchCustomerListRequestDTO;
import com.viettel.campaign.web.dto.request_dto.SearchCustomerRequestDTO;
import com.viettel.econtact.filter.UserSession;
import cz.jirutka.rsql.parser.RSQLParser;
import cz.jirutka.rsql.parser.ast.Node;
import cz.jirutka.rsql.parser.ast.RSQLVisitor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
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.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.*;
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 javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class CustomerServiceImpl implements CustomerService {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomerServiceImpl.class);
    //    private static final Pattern EMAIL_REGEXP = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
    private static final Pattern EMAIL_REGEXP = Pattern.compile("^(.+)@(.+)$", Pattern.CASE_INSENSITIVE);

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

    @Autowired
    CustomizeFieldsRepository customizeFieldsRepository;

    @Autowired
    CustomizeFieldObjectRepository customizeFieldObjectRepository;

    @Autowired
    CustomizeFieldOptionValueRepository customizeFieldOptionValueRepository;

    @Autowired
    ApParamRepository apParamRepository;

    @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(SearchCustomerRequestDTO searchCustomerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();

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

        try {
            int count = customerRepository.getAllCustomerByParams(searchCustomerRequestDTO, null).size();

            resultDTO.setTotalRow(count);
            List<CustomerCustomDTO> data = customerRepository.getAllCustomerByParams(searchCustomerRequestDTO, SQLBuilder.buildPageable(searchCustomerRequestDTO));
            resultDTO.setListData(data);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        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 deleteIds(CustomerRequestDTO customerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (customerRequestDTO != null) {
                if (customerListMappingRepository.findAllCustomerListMapping(customerRequestDTO.getIds(), customerRequestDTO.getCustomerListId(), customerRequestDTO.getCompanySiteId()).size() > 0) {
                    //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.DELETE_ERROR);
                    resultDTO.setDescription(Constants.ApiErrorDesc.DELETE_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 getCustomerDetailById(Long companySiteId, Long customerListId, Long customerId) {
        ResultDTO resultDTO = new ResultDTO();
        if (DataUtil.isNullOrZero(companySiteId)) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            return resultDTO;
        }
        try {
            resultDTO.setData(customerRepository.getCustomerDetailById(companySiteId, customerListId, customerId));
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        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 createCustomerList(CustomerListDTO customerListDTO, String userName) {
        ApParam apParam = apParamRepository.getCustomerListSeq();

        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        Date currentDate = new Date(dateFormat.format(new Date()));
        Date oldDate = new Date(apParam.getDescription());
        Long newDay = (currentDate.getTime() - oldDate.getTime()) / (1000 * 60 * 60 * 24);
        String convertDate = dateFormat.format(new Date());
        String[] dateArray = convertDate.split("/");

        if (customerListDTO.getCustomerListCode().trim().length() == 0) {
            if (newDay == 0) {
                apParamRepository.updateCustomerListSeq(String.valueOf(Integer.parseInt(apParam.getParValue()) + 1), apParam.getDescription());
                customerListDTO.setCustomerListCode(dateArray[0] + dateArray[2] + dateArray[1] + "_" + (Integer.parseInt(apParam.getParValue()) + 1));
            } else {
                apParamRepository.updateCustomerListSeq("1", dateFormat.format(new Date()));
                customerListDTO.setCustomerListCode(dateArray[0] + dateArray[2] + dateArray[1] + "_1");
            }
        }

        // THÍM NÀO MERGE CONFLICT THÌ GIỮ LẠI HỘ E CÁI METHOD NÀY VỚI
        // VIẾT ĐI VIẾT LẠI 4 LẦN RỒI ĐẤY
        ResultDTO resultDTO = new ResultDTO();
        try {
            CustomerList cl = customerListRepository.findByCustomerListCode(customerListDTO.getCustomerListCode());
            if (cl != null) {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription("Entity exists");
                return resultDTO;
            } else {
                cl = new CustomerList();
                cl.setCustomerListCode(customerListDTO.getCustomerListCode());
                cl.setCustomerListName(customerListDTO.getCustomerListName());
                cl.setStatus((short) 1);
                cl.setCreateBy(userName);
                cl.setCreateAt(new Date());
                cl.setUpdateBy(null);
                cl.setUpdateAt(null);
                cl.setSource(null);
                cl.setDeptCreate(null);
                cl.setCompanySiteId(customerListDTO.getCompanySiteId());
                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
                resultDTO.setData(customerListRepository.save(cl));
                return resultDTO;
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription("Error");
            return resultDTO;
        }
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO updateCustomerList(CustomerListDTO customerListDTO, String userName) {
        ResultDTO resultDTO = new ResultDTO();

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

                if (customerList != null) {
//                    customerList.setCreateBy(customerListDTO.getCreateBy());
                    customerList.setCompanySiteId(customerListDTO.getCompanySiteId());
//                    customerList.setCreateAt(customerListDTO.getCreateAt());
                    customerList.setCustomerListCode(customerListDTO.getCustomerListCode());
                    customerList.setCustomerListName(customerListDTO.getCustomerListName());
                    customerList.setDeptCreate(customerListDTO.getDeptCreate());
                    customerList.setStatus(customerList.getStatus());
                    customerList.setUpdateBy(userName);
                    customerList.setUpdateAt(new Date());
                    customerList.setSource(customerListDTO.getSource());
                    customerList.setCustomerListId(customerListDTO.getCustomerListId());


                    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 deleteCustomerListIds(CustomerRequestDTO customerRequestDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (customerRequestDTO != null) {
                if (DataUtil.isNullOrZero(campaignCustomerListRepository.campaignIdsCount(customerRequestDTO.getIds()))) {
                    if (customerListRepository.findAllCustomerList(customerRequestDTO.getIds(), customerRequestDTO.getCompanySiteId()).size() > 0) {
                        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.DELETE_ERROR);
                        resultDTO.setDescription(Constants.ApiErrorDesc.DELETE_ERROR);
                    }
                } 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(SearchCustomerListRequestDTO searchCustomerListRequestDTO) {
        LOGGER.info("=== Start search customer list::");
        ResultDTO resultDTO = new ResultDTO();

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

        int count = customerListRepository.getAllCustomerListByParams(searchCustomerListRequestDTO, null).size();
        try {
            if (count > 0) {
                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
                resultDTO.setTotalRow(count);
                List<CustomerListDTO> customerList = customerListRepository.getAllCustomerListByParams(searchCustomerListRequestDTO, SQLBuilder.buildPageable(searchCustomerListRequestDTO));
                resultDTO.setListData(customerList);

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

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

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

        } 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
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<CustomizeFields> getDynamicHeader(Long companySiteId) {
        LOGGER.info("------------------GET DYNAMIC HEADER-------------------");
        List<CustomizeFields> headerList;
        try {
            headerList = customizeFieldsRepository.findCustomizeFieldsByFunctionCodeEqualsAndStatusAndActiveAndSiteId("CUSTOMER", 1L, 1L, companySiteId);
        } catch (Exception e) {
            LOGGER.info(e.getMessage());
            return null;
        }
        return headerList;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public Map<String, Object> readAndValidateCustomer(String path, List<CustomizeFields> dynamicHeader, UserSession userSession, Long customerListId) throws IOException {
        LOGGER.info("------------READ AND VALIDATE--------------");
        Locale locale = new Locale("vi", "VN");
        DataFormatter dataFormat = new DataFormatter();
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        Map<String, Object> result = new HashMap<>();
        Map<String, Integer> headerMap = new HashMap<>();
        List<String> stringHeader = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        int failedCount = 0;
        int objectSize;
        XSSFWorkbook workbook = null;
        boolean isMainPhoneNull = false, isSecondPhoneNull = false, isEmailNull = false;
        try {

            //<editor-fold desc="Khởi tạo mảng header tĩnh" defaultstate="collapsed">

            List<CustomizeFields> header = new ArrayList<>();
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.no", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.fullname", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.mainPhone", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.secondPhone", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.email", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.address", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.cusType", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.companyName", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.description", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.callAllowed", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.emailAllowed", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.smsAllowed", locale)));

            header.addAll(dynamicHeader);

            for (CustomizeFields cf : header) {
                stringHeader.add(cf.getTitle().split("#")[0].trim());
            }
            //</editor-fold>

            File file = new File(path);
            FileInputStream fis = new FileInputStream(file);
            workbook = new XSSFWorkbook(fis);
            XSSFSheet sheet = workbook.getSheetAt(0);
            Row row = sheet.getRow(3);

            //<editor-fold desc="Kiểm tra header của template" defaultstate="collapsed">
            if (row.getLastCellNum() > header.size()) {
                for (int i = 0; i < row.getLastCellNum(); i++) {
                    Cell c = row.getCell(i);
                    if (c != null && !c.getStringCellValue().trim().equals("")) {
                        if (stringHeader.contains(c.getStringCellValue().trim()) && !headerMap.containsKey(c.getStringCellValue().trim())) {
                            headerMap.put(c.getStringCellValue().trim(), c.getColumnIndex());
                        }
                    }
                }
                if (headerMap.size() != header.size()) {
                    result.put("content", Files.readAllBytes(file.toPath()));
                    result.put("message", "template-invalid");
                    return result;
                }
                objectSize = row.getLastCellNum();
            } else if (row.getLastCellNum() < header.size()) {
                result.put("content", Files.readAllBytes(file.toPath()));
                result.put("message", "template-invalid");
                return result;
            } else {
                for (int i = 0; i < header.size(); i++) {
                    Cell c = row.getCell(i);
                    if (c != null && !"".equals(c.getStringCellValue().trim())) {
                        if (stringHeader.contains(c.getStringCellValue().trim()) && !headerMap.containsKey(c.getStringCellValue().trim())) {
                            headerMap.put(c.getStringCellValue().trim(), c.getColumnIndex());
                        }
                    }
                }
                if (headerMap.size() != header.size()) {
                    result.put("content", Files.readAllBytes(file.toPath()));
                    result.put("message", "template-invalid");
                    return result;
                }
                objectSize = row.getLastCellNum();
            }
            //</editor-fold>

            List<Object[]> rawDataList = new ArrayList<>();

            //<editor-fold desc="Kiểm tra file dữ liệu rỗng" defaultstate="collapsed">
            if (sheet.getPhysicalNumberOfRows() == 3) {
                result.put("message", "template-no-data");
                result.put("content", Files.readAllBytes(file.toPath()));
                return result;
            }
            //</editor-fold>

            //<editor-fold desc="Đọc dữ liệu từng dòng 1" defaultstate="collapsed">
            for (int i = 4; i < sheet.getPhysicalNumberOfRows(); i++) {
                Row dataRow = sheet.getRow(i);
                if (!isRowEmpty(dataRow)) {
                    Object[] obj = new Object[objectSize + 1];
                    headerMap.forEach((k, v) -> {
                        Cell dataCell = dataRow.getCell(v);
                        if (dataCell != null) {
                            obj[v] = dataFormat.formatCellValue(dataCell);
                        } else {
                            if (k.equals(BundleUtils.getLangString("customer.cusType", locale))) {
                                obj[v] = BundleUtils.getLangString("customer.cusType.normal", locale);
                            } else if (k.equals(BundleUtils.getLangString("customer.callAllowed", locale)) || k.equals(BundleUtils.getLangString("customer.emailAllowed", locale))
                                    || k.equals(BundleUtils.getLangString("customer.smsAllowed", locale))) {
                                obj[v] = BundleUtils.getLangString("customer.yes", locale);
                            } else obj[v] = null;
                        }
                    });
                    rawDataList.add(obj);
                } else break;
            }
            //</editor-fold>

            //<editor-fold desc="Validate dữ liệu" defaultstate="collapsed">

            for (int i = 0; i < rawDataList.size(); i++) {
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.fullname", locale).split("#")[0])
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.fullname", locale).split("#")[0])] != null
                        && !rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.fullname", locale).split("#")[0])].toString().trim().equals("")) {
                    String str = validateLength(BundleUtils.getLangString("customer.fullname", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.fullname", locale).split("#")[0])].toString(), 1000, locale);
                    if (!str.equals("")) {
                        sb.append(str);
                    }
                } else sb.append(BundleUtils.getLangString("customer.nameRequired", locale));
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])
                        && (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])] == null || rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])].toString().trim().equals(""))) {
                    isMainPhoneNull = true;
                } else {
                    String str = validateLength(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])].toString(), 50, locale);
                    if (!str.equals("")) {
                        sb.append(str);
                    } else if (validateNumberOnly(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])].toString().trim())) {
                        sb.append(validateExistPhone(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])].toString().trim(), locale, true));
                    } else {
//                        sb.append(BundleUtils.getLangString("customer.onlyNumber", locale));
                    }
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0]) && (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])] == null || rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])].toString().trim().equals(""))) {
                    isSecondPhoneNull = true;
                } else {
                    String str = validateLength(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])].toString(), 50, locale);
                    if (!str.equals("")) {
                        sb.append(str);
                    } else if (validateNumberOnly(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])].toString().trim())) {
                        sb.append(validateExistPhone(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])].toString(), locale, false));
                    } else {
//                        sb.append(BundleUtils.getLangString("customer.onlyNumber", locale));
                    }
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])
                        && (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])] == null || rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])].toString().trim().equals(""))) {
                    isEmailNull = true;
                } else {
                    if (!validateEmail(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])].toString().trim())) {
                        sb.append(BundleUtils.getLangString("customer.emailInvalid", locale));
                    } else {
                        sb.append(validateDuplicateEmail(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])].toString().trim(), locale));
                        sb.append(validateLength(BundleUtils.getLangString("customer.email", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])].toString(), 100, locale));
                    }
                }
                if (isEmailNull && isMainPhoneNull && isSecondPhoneNull) {
                    sb.append(BundleUtils.getLangString("customer.invalidRecord", locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0]) && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0])] != null) {
                    sb.append(validateLength(BundleUtils.getLangString("customer.address", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0])].toString(), 500, locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.cusType", locale))
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.cusType", locale))] != null) {
                    sb.append(validateCusType(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.cusType", locale))].toString().trim(), locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])] != null) {
                    sb.append(validateLength(BundleUtils.getLangString("customer.companyName", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])].toString(), 100, locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])] != null) {
                    sb.append(validateLength(BundleUtils.getLangString("customer.description", locale).split("#")[0], rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])].toString(), 2000, locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.callAllowed", locale).split("#")[0])
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.callAllowed", locale).split("#")[0])] != null) {
                    sb.append(validateYesNo(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.callAllowed"))].toString().trim(), locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.emailAllowed", locale).split("#")[0])
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.emailAllowed", locale).split("#")[0])] != null) {
                    sb.append(validateYesNo(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.emailAllowed"))].toString().trim(), locale));
                }
                if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.smsAllowed", locale).split("#")[0])
                        && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.smsAllowed", locale).split("#")[0])] != null) {
                    sb.append(validateYesNo(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.smsAllowed"))].toString().trim(), locale));
                }

                //<editor-fold desc="Validate những trường động, chỉ cần uncomment và fix bug là có thể dùng :v">
//                for (int j = 0; j < dynamicHeader.size(); j++) {
//                    if (rawDataList.get(i).length > headerMap.get(dynamicHeader.get(j).getTitle().trim())
//                    && rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())] != null
//                    && !"".equals(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())]))
//                    switch (dynamicHeader.get(j).getType()) {
//                        case "combobox":
//                            List<CustomizeFieldOptionValue> optionValues =
//                                    customizeFieldOptionValueRepository.findCustomizeFieldOptionValuesByFieldOptionIdAndStatus(dynamicHeader.get(j).getFieldOptionsId(), 1L);
//                            String[] arr = new String[optionValues.size()];
//                            int s = 0;
//                            for (CustomizeFieldOptionValue c: optionValues) {
//                                arr[s] = c.getName().trim();
//                                s++;
//                            }
//                            sb.append(validateCombobox(arr, rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString(), locale));
//                            break;
//                        case "number":
//                            if (validateNumberOnly(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString())) {
//                                sb.append(validateDynamicLength(dynamicHeader.get(j).getTitle(), rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString(), dynamicHeader.get(j).getMin(), dynamicHeader.get(j).getMax(), locale));
//                                sb.append(validateUsingRegexp(dynamicHeader.get(j).getTitle(), rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString(), dynamicHeader.get(j).getRegexpForValidation(), locale));
//                            } else {
//                                sb.append(BundleUtils.getLangString("customer.onlyNumber", locale));
//                            }
//                            break;
//                        case "date":
//                            sb.append(validateUsingRegexp(dynamicHeader.get(j).getTitle(), rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString(), dynamicHeader.get(j).getRegexpForValidation(), locale));
//                            break;
//                        case "checkbox":
//                            sb.append(validateYesNo(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString(), locale));
//                            break;
//                        default:
//                            sb.append(validateDynamicLength(dynamicHeader.get(j).getTitle(), rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString(), dynamicHeader.get(j).getMinLength(), dynamicHeader.get(j).getMaxLength(), locale));
//                            break;
//                    }
//                }
                //</editor-fold>

                if (sb.length() > 0) {
                    rawDataList.get(i)[objectSize] = sb.toString();
                    failedCount++;
                } else {
                    rawDataList.get(i)[objectSize] = "Ok";
                }
                sb = new StringBuilder();
                isEmailNull = false;
                isMainPhoneNull = false;
                isSecondPhoneNull = false;
            }
            //</editor-fold>

            byte[] content = buildResultTemplate(rawDataList, header, headerMap, row.getLastCellNum());

            //<editor-fold desc="Insert dữ liệu nếu validate Ok" defaultstate="collapsed">
            if (failedCount == 0) {
                for (int i = 0; i < rawDataList.size(); i++) {
                    Customer c = new Customer();
                    c.setName(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.fullname", locale).split("#")[0])].toString().trim());
                    c.setSiteId(userSession.getSiteId());
                    c.setCode(null);
                    if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])
                            && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])] != null
                            && !rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])].toString().trim().equals("")) {
                        c.setDescription(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.description", locale).split("#")[0])].toString().trim());
                    }
                    if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])
                            && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])] != null
                            && !rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])].toString().trim().equals("")) {
                        c.setCompanyName(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.companyName", locale).split("#")[0])].toString().trim());
                    }
                    c.setCustomerImg(null);
                    c.setCreateDate(new Date());
                    c.setUpdateDate(null);
                    c.setStatus(1L);
                    c.setCreateBy(userSession.getUserName());
                    c.setUpdateBy(null);
                    c.setGender((short) 1);
                    if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0])
                            && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0])] != null
                            && !rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0])].toString().trim().equals("")) {
                        c.setCurrentAddress(rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.address", locale).split("#")[0])].toString().trim());
                    }
//                    c.setPlaceOfBirth();
//                    c.setDateOfBirth();
                    c.setMobileNumber(null);
                    c.setEmail(null);
                    c.setUserName(null);
                    c.setAreaCode(null);
                    switch (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.cusType", locale))].toString().trim()) {
                        case "VIP":
                            c.setCustomerType(2L);
                            break;
                        case "Blacklist":
                            c.setCustomerType(3L);
                            break;
                        default:
                            c.setCustomerType(1L);
                            break;
                    }
                    if (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.callAllowed", locale))].toString().trim().equals(BundleUtils.getLangString("customer.yes", locale))) {
                        c.setCallAllowed(1L);
                    } else {
                        c.setCallAllowed(0L);
                    }
                    if (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.emailAllowed", locale))].toString().trim().equals(BundleUtils.getLangString("customer.yes", locale))) {
                        c.setEmailAllowed(1L);
                    } else {
                        c.setEmailAllowed(0L);
                    }
                    if (rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.smsAllowed", locale))].toString().trim().equals(BundleUtils.getLangString("customer.yes", locale))) {
                        c.setSmsAllowed(1L);
                    } else {
                        c.setSmsAllowed(0L);
                    }
                    c.setIpccStatus("active");
                    Customer saved = customerRepository.save(c);
                    if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])
                            && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])] != null) {
                        String[] mainPhone = rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.mainPhone", locale).split("#")[0])].toString().trim().split("[,;]");
                        for (int j = 0; j < mainPhone.length; j++) {
                            CustomerContact cc = new CustomerContact();
                            cc.setCustomerId(saved.getCustomerId());
                            cc.setSiteId(userSession.getSiteId());
                            cc.setContactType((short) 5);
                            cc.setContact(mainPhone[j].trim());
                            cc.setIsDirectLine((short) 1);
                            cc.setStatus((short) 1);
                            cc.setCreateDate(new Date());
                            cc.setUpdateDate(new Date());
                            cc.setCreateBy(userSession.getUserName());
                            cc.setUpdateBy(userSession.getUserName());
                            customerContactRepository.save(cc);
                        }
                    }
                    if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])
                            && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])] != null) {
                        String[] subPhone = rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.secondPhone", locale).split("#")[0])].toString().trim().split("[,;]");
                        for (int j = 0; j < subPhone.length; j++) {
                            CustomerContact cc = new CustomerContact();
                            cc.setCustomerId(saved.getCustomerId());
                            cc.setSiteId(userSession.getSiteId());
                            cc.setContactType((short) 5);
                            cc.setContact(subPhone[j].trim());
                            cc.setIsDirectLine((short) 0);
                            cc.setStatus((short) 1);
                            cc.setCreateDate(new Date());
                            cc.setUpdateDate(new Date());
                            cc.setCreateBy(userSession.getUserName());
                            cc.setUpdateBy(userSession.getUserName());
                            customerContactRepository.save(cc);
                        }
                    }
                    if (rawDataList.get(i).length > headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])
                            && rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])] != null) {
                        String[] email = rawDataList.get(i)[headerMap.get(BundleUtils.getLangString("customer.email", locale).split("#")[0])].toString().split("[,;]");
                        for (int j = 0; j < email.length; j++) {
                            CustomerContact cc = new CustomerContact();
                            cc.setCustomerId(saved.getCustomerId());
                            cc.setSiteId(userSession.getSiteId());
                            cc.setContactType((short) 2);
                            cc.setContact(email[j].trim());
                            cc.setIsDirectLine((short) 1);
                            cc.setStatus((short) 1);
                            cc.setCreateDate(new Date());
                            cc.setUpdateDate(new Date());
                            cc.setCreateBy(userSession.getUserName());
                            cc.setUpdateBy(userSession.getUserName());
                            customerContactRepository.save(cc);
                        }
                    }
                    for (int j = 0; j < dynamicHeader.size(); j++) {
                        CustomizeFieldObject cfo = new CustomizeFieldObject();
                        cfo.setObjectId(saved.getCustomerId());
                        cfo.setCustomizeFieldId(dynamicHeader.get(j).getCustomizeFieldId());
                        if (rawDataList.get(i).length > headerMap.get(dynamicHeader.get(j).getTitle().trim()) && rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())] != null) {
                            switch (dynamicHeader.get(j).getType()) {
                                case "combobox":
                                    CustomizeFieldOptionValue cfov =
                                            customizeFieldOptionValueRepository.findCustomizeFieldOptionValueByNameEqualsAndStatus(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString().trim(), 1L);
                                    cfo.setFieldOptionValueId(cfov.getFieldOptionValueId());
                                    break;
                                case "checkbox":
                                    if (rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString().trim().equals(BundleUtils.getLangString("customer.yes", locale))) {
                                        cfo.setValueCheckbox(1L);
                                    } else {
                                        cfo.setValueCheckbox(0L);
                                    }
                                    break;
                                case "date":
                                    Date date = dateFormat.parse(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString().trim());
                                    cfo.setValueDate(date);
                                    break;
                                case "number":
                                    cfo.setValueNumber(Long.parseLong(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString().trim()));
                                    break;
                                default:
                                    cfo.setValueText(rawDataList.get(i)[headerMap.get(dynamicHeader.get(j).getTitle().trim())].toString().trim());
                                    break;
                            }
                        }
                        cfo.setCreateBy(userSession.getUserName());
                        cfo.setCreateDate(new Date());
                        cfo.setStatus(1L);
                        cfo.setFunctionCode("CUSTOMER");
                        cfo.setTitle(dynamicHeader.get(j).getTitle().trim());
                        customizeFieldObjectRepository.save(cfo);
                    }
                    CustomerListMapping clm = new CustomerListMapping();
                    clm.setCustomerId(saved.getCustomerId());
                    clm.setCompanySiteId(userSession.getCompanySiteId());
                    clm.setCustomerListId(customerListId);
                    customerListMappingRepository.save(clm);
                }
//                workbook.write(os);
                workbook.close();
                result.put("content", content);
                result.put("message", "import-success");
            } else {
//                workbook.write(os);
                workbook.close();
                result.put("content", content);
                result.put("message", "import-error");
            }
            //</editor-fold>

            return result;
        } catch (Exception e) {
            LOGGER.info(e.getMessage());
            result.put("message", "validate-error");
            return result;
        } finally {
            if (workbook != null) workbook.close();
        }
    }

    //<editor-fold desc="Validate Methods" defaultstate="collapsed">
    private boolean isRowEmpty(Row row) {
        for (int i = 0; i <= row.getLastCellNum(); i++) {
            Cell cell = row.getCell(i);
            if (cell != null && cell.getCellType() != CellType.BLANK) {
                return false;
            }
        }
        return true;
    }

    private String validateExistPhone(String str, Locale locale, boolean isCheckDuplicate) {
        String result = "";
        String[] arr = str.split("[;,]");
        List<CustomerContact> contactList;
        if (str.length() > 50) {
            result += BundleUtils.getLangString("customer.phoneMax50", locale);
        }
        if (arr.length > 3) {
            result += BundleUtils.getLangString("customer.3phone", locale);
        } else {
            for (int i = 0; i < arr.length; i++) {
                if (arr[i].length() < 8 || arr[i].length() > 15) {
                    result += BundleUtils.getLangString("customer.phone8to15", locale);
                    break;
                }
            }
        }
        if (isCheckDuplicate) {
            for (int i = 0; i < arr.length; i++) {
                contactList = customerContactRepository.findCustomerContactsByContactEquals(arr[i]);
                if (contactList.size() != 0) {
                    result += BundleUtils.getLangString("customer.phoneExists", locale);
                    break;
                }
            }
        }
        return result;
    }

    private boolean validateNumberOnly(String str) {
        String regexp = "\\b\\d+\\b";
        String[] arr = str.split("[,;]");
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            if (!arr[i].matches(regexp)) {
                count++;
            }
        }
        return count == 0;
    }

    private String validateDuplicateEmail(String str, Locale locale) {
        String result = "";
        String[] arr = str.split("[;,]");
        List<CustomerContact> contactList;
        for (int i = 0; i < arr.length; i++) {
            contactList = customerContactRepository.findCustomerContactsByContactEquals(arr[i]);
            if (contactList.size() != 0) {
                return result.concat(BundleUtils.getLangString("customer.emailExists", locale));
            }
        }
        return result;
    }

    private String validateUsingRegexp(String header, String data, String regexp, Locale locale) {
        if (data.matches(regexp)) {
            return header + " " + BundleUtils.getLangString("customer.notMatch", locale);
        } else return "";
    }

    private String validateLength(String header, String str, int length, Locale locale) {
        if (str.trim().length() > length) {
            return header + " " + BundleUtils.getLangString("customer.notGreaterThan", locale) + " " + length;
        }
        return "";
    }

    private String validateDynamicLength(String header, String str, Long min, Long max, Locale locale) {
        if (str.trim().length() < min || str.trim().length() > max) {
            return header + " " + BundleUtils.getLangString("customer.notGreaterThan", locale) + " " + max + " " + BundleUtils.getLangString("customer.notLessThan", locale) + " " + min;
        }
        return "";
    }

    private boolean validateEmail(String str) {
        String[] arr = str.split("[;,]");
        for (int i = 0; i < arr.length; i++) {
            Matcher matcher = EMAIL_REGEXP.matcher(arr[i]);
            if (!matcher.matches()) {
                return false;
            }
        }
        return true;
    }

    private String validateCusType(String str, Locale locale) {
        String[] arr = {BundleUtils.getLangString("customer.cusType.normal", locale),
                BundleUtils.getLangString("customer.cusType.vip", locale),
                BundleUtils.getLangString("customer.cusType.blacklist", locale)};
        List<String> cusTypes = Arrays.asList(arr);
        if (cusTypes.contains(str.trim())) {
            return "";
        } else {
            return BundleUtils.getLangString("customer.cusTypeInvalid", locale);
        }
    }

    private String validateYesNo(String str, Locale locale) {
        String[] arr = {BundleUtils.getLangString("customer.yes", locale),
                BundleUtils.getLangString("customer.not", locale)};
        List<String> cusTypes = Arrays.asList(arr);
        if (cusTypes.contains(str.trim())) {
            return "";
        } else {
            return BundleUtils.getLangString("customer.comboboxInvalid", locale);
        }
    }

    private boolean validateLetter(String str) {
        String regexp = "@\"^\\p{L}+$\"";
        return str.matches(regexp);
    }

    private String validateCombobox(String[] optionValue, String str, Locale locale) {
        List<String> arr = Arrays.asList(optionValue);
        if (!arr.contains(str)) {
            return BundleUtils.getLangString("customer.comboboxInvalid", locale);
        } else {
            return "";
        }
    }

    //</editor-fold>

    private byte[] buildResultTemplate(List<Object[]> rawData, List<CustomizeFields> header, Map<String, Integer> dataMap, int lastNum) throws IOException {
        LOGGER.info("---------------CREATE RESULT FILE--------------");
        Locale locale = new Locale("vi", "VN");
        XSSFWorkbook workbook = null;
        Map<String, Integer> headerMap = new HashMap<>();
        try {
            workbook = new XSSFWorkbook();
            CreationHelper creationHelper = workbook.getCreationHelper();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Sheet sheet = workbook.createSheet("RESULT");
            dataMap.put(BundleUtils.getLangString("customer.result", locale), lastNum);

            //<editor-fold desc="Tạo style và font" defaultstate="collapsed">

            Font headerFont = workbook.createFont();
            Font importantFont = workbook.createFont();
            importantFont.setColor(IndexedColors.RED.index);
            headerFont.setBold(true);
            CellStyle headerStyle = workbook.createCellStyle();
            CellStyle importantStyle = workbook.createCellStyle();
            CellStyle columnStyle = workbook.createCellStyle();
            importantStyle.setFont(importantFont);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            headerStyle.setFont(headerFont);
            columnStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            columnStyle.setAlignment(HorizontalAlignment.CENTER);
            columnStyle.setWrapText(true);

            //</editor-fold>

            //<editor-fold desc="Thêm combobox" defaultstate="collapsed">

            //<editor-fold desc="Cho những trường động" defaultstate="collapsed">
            DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
            for (int i = 12; i < header.size(); i++) {
                if (header.get(i).getType().equals("combobox")) {
                    String[] constraint;
                    List<CustomizeFieldOptionValue> list =
                            customizeFieldOptionValueRepository.findCustomizeFieldOptionValuesByFieldOptionIdAndStatus(header.get(i).getFieldOptionsId(), 1L);
                    constraint = new String[list.size()];
                    for (int j = 0; j < list.size(); j++) {
                        constraint[j] = list.get(j).getName();
                    }
                    DataValidationConstraint comboboxConstraint = dataValidationHelper.createExplicitListConstraint(constraint);
                    CellRangeAddressList comboboxCellRange = new CellRangeAddressList(4, 9999, 12 + i, 12 + i);
                    DataValidation comboboxValidation = dataValidationHelper.createValidation(comboboxConstraint, comboboxCellRange);
                    comboboxValidation.setSuppressDropDownArrow(true);
                    comboboxValidation.setShowErrorBox(true);
                    sheet.addValidationData(comboboxValidation);
                } else if (header.get(i).getType().equals("checkbox")) {
                    DataValidationConstraint yesNoConstraint = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("customer.yes", locale), BundleUtils.getLangString("customer.not", locale)});
                    CellRangeAddressList checkboxCellRange = new CellRangeAddressList(4, 9999, 12 + i, 12 + i);
                    DataValidation yesNoValidation = dataValidationHelper.createValidation(yesNoConstraint, checkboxCellRange);
                    yesNoValidation.setShowErrorBox(true);
                    yesNoValidation.setSuppressDropDownArrow(true);
                    sheet.addValidationData(yesNoValidation);
                }
            }
            //</editor-fold>

            //<editor-fold desc="Cho những trường tĩnh" defaultstate="collapsed">
            DataValidationConstraint cusTypeConstraint = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("customer.cusType.normal", locale), BundleUtils.getLangString("customer.cusType.vip", locale), BundleUtils.getLangString("customer.cusType.blacklist", locale)});
            DataValidationConstraint isAllowConstraint = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("customer.yes", locale), BundleUtils.getLangString("customer.not", locale)});
            CellRangeAddressList cusTypeCellRangeAddressList = new CellRangeAddressList(4, 9999, 6, 6);
            CellRangeAddressList callCellRangeAddressList = new CellRangeAddressList(4, 9999, 9, 9);
            CellRangeAddressList emailCellRangeAddressList = new CellRangeAddressList(4, 9999, 10, 10);
            CellRangeAddressList smsCellRangeAddressList = new CellRangeAddressList(4, 9999, 11, 11);
            DataValidation cusTypeValidation = dataValidationHelper.createValidation(cusTypeConstraint, cusTypeCellRangeAddressList);
            DataValidation callValidation = dataValidationHelper.createValidation(isAllowConstraint, callCellRangeAddressList);
            DataValidation emailValidation = dataValidationHelper.createValidation(isAllowConstraint, emailCellRangeAddressList);
            DataValidation smsValidation = dataValidationHelper.createValidation(isAllowConstraint, smsCellRangeAddressList);
            cusTypeValidation.setSuppressDropDownArrow(true);
            cusTypeValidation.setShowErrorBox(true);
            callValidation.setSuppressDropDownArrow(true);
            callValidation.setShowErrorBox(true);
            emailValidation.setSuppressDropDownArrow(true);
            emailValidation.setShowErrorBox(true);
            smsValidation.setSuppressDropDownArrow(true);
            smsValidation.setShowErrorBox(true);
            sheet.addValidationData(cusTypeValidation);
            sheet.addValidationData(callValidation);
            sheet.addValidationData(emailValidation);
            sheet.addValidationData(smsValidation);
            //</editor-fold>

            //</editor-fold>

            //<editor-fold desc="Ghi header" defaultstate="collapsed">

            Drawing drawing = sheet.createDrawingPatriarch();
            ClientAnchor anchor = creationHelper.createClientAnchor();
            Row row0 = sheet.createRow(0);
            Row row2 = sheet.createRow(2);
            Row row3 = sheet.createRow(3);
            Cell cell0 = row0.createCell(0);
            cell0.setCellStyle(headerStyle);
            cell0.setCellValue(BundleUtils.getLangString("customer.importCustomer", locale));
            Cell cell2 = row2.createCell(0);
            cell2.setCellStyle(importantStyle);
            cell2.setCellValue(BundleUtils.getLangString("customer.notice", locale));
            for (int i = 0; i < header.size(); i++) {
                sheet.setDefaultColumnStyle(i, columnStyle);
                Cell headerCell = row3.createCell(i);
                headerCell.setCellValue(header.get(i).getTitle().split("#")[0]);
                headerStyle.setBorderTop(BorderStyle.THIN);
                headerStyle.setBorderRight(BorderStyle.THIN);
                headerStyle.setBorderBottom(BorderStyle.THIN);
                headerStyle.setBorderLeft(BorderStyle.THIN);
                headerFont.setFontHeightInPoints((short) 11);
                headerCell.setCellStyle(headerStyle);
                if (i == 0) {
                    sheet.setColumnWidth(i, 2500);
                } else {
                    sheet.setColumnWidth(i, 6000);
                }
                anchor.setCol1(headerCell.getColumnIndex());
                anchor.setCol2(headerCell.getColumnIndex() + 2);
                anchor.setRow1(row3.getRowNum());
                anchor.setRow2(row3.getRowNum() + 4);
                if (header.get(i).getTitle().contains("#")) {
                    Comment comment = drawing.createCellComment(anchor);
                    RichTextString str = creationHelper.createRichTextString(header.get(i).getTitle().split("#")[1]);
                    comment.setString(str);
                    comment.setAuthor("APACHE POI");
                    headerCell.setCellComment(comment);
                }
                headerMap.put(header.get(i).getTitle().split("#")[0].trim(), i);
            }
            sheet.setColumnWidth(header.size(), 8000);
            Cell resultCell = row3.createCell(header.size());
            resultCell.setCellStyle(headerStyle);
            resultCell.setCellValue(BundleUtils.getLangString("customer.result", locale));
            headerMap.put(BundleUtils.getLangString("customer.result", locale), headerMap.size());
            //</editor-fold>

            //<editor-fold desc="Ghi dữ liệu">

            for (int i = 0; i < rawData.size(); i++) {
                Row dataRow = sheet.createRow(4 + i);
                int finalI = i;
                headerMap.forEach((k, v) -> {
                    Cell c = dataRow.createCell(v);
                    c.setCellType(CellType.STRING);
                    if (rawData.get(finalI).length > dataMap.get(k)
                            && rawData.get(finalI)[dataMap.get(k)] != null
                            && !"".equals(rawData.get(finalI)[dataMap.get(k)].toString().trim())) {
                        c.setCellValue(rawData.get(finalI)[dataMap.get(k)].toString());
                    }
                });
//                for (int j = 0; j < header.size(); j++) {

//                    headerMap.get(header.get(j).getTitle().split("#")[0]);
//                    if (rawData.get(i).length > header.size() + 1 && rawData.get(i)[j] != null && !"".equals(rawData.get(i)[j].toString().trim())) {
//                        Cell c = dataRow.createCell(j);
//                        c.setCellType(CellType.STRING);
//                        c.setCellValue(rawData.get(i)[j].toString());
//                    }
//                }
            }

            //</editor-fold>

            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 13));
            sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 13));
            workbook.write(os);
            os.flush();
            os.close();
            return os.toByteArray();
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            return null;
        } finally {
            if (workbook != null) workbook.close();
        }
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public byte[] buildTemplate(Long companySiteId) throws IOException {
        LOGGER.info("-----------BUILD TEMPLATE-----------");
        Locale locale = new Locale("vi", "VN");
        XSSFWorkbook workbook = null;
        try {
            workbook = new XSSFWorkbook();
            CreationHelper creationHelper = workbook.getCreationHelper();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Sheet sheet = workbook.createSheet("IMPORT");
            DataFormat dataFormat = workbook.createDataFormat();

            //<editor-fold desc="Tạo array header" defaultstate="collapsed">
            List<CustomizeFields> header = new ArrayList<>();
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.no", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.fullname", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.mainPhone", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.secondPhone", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.email", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.address", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.cusType", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.companyName", locale)));
            header.add(new CustomizeFields("text", BundleUtils.getLangString("customer.description", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.callAllowed", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.emailAllowed", locale)));
            header.add(new CustomizeFields("combobox", BundleUtils.getLangString("customer.smsAllowed", locale)));

            List<CustomizeFields> dynamicHeader = getDynamicHeader(companySiteId);
            header.addAll(dynamicHeader);
            //</editor-fold>

            //<editor-fold desc="Tạo style và font" defaultstate="collapsed">
            Font headerFont = workbook.createFont();
            Font importantFont = workbook.createFont();
            importantFont.setColor(IndexedColors.RED.index);
            headerFont.setBold(true);
            CellStyle headerStyle = workbook.createCellStyle();
            CellStyle importantStyle = workbook.createCellStyle();
            CellStyle columnStyle = workbook.createCellStyle();
            importantStyle.setFont(importantFont);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            headerStyle.setFont(headerFont);
            columnStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            columnStyle.setAlignment(HorizontalAlignment.CENTER);
            columnStyle.setWrapText(true);
            columnStyle.setDataFormat(dataFormat.getFormat("@"));
            //</editor-fold>

            //<editor-fold desc="Thêm combobox" defaultstate="collapsed">

            //<editor-fold desc="Cho những trường động" defaultstate="collapsed">
            DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
            for (int i = 0; i < dynamicHeader.size(); i++) {
                if (dynamicHeader.get(i).getType().equals("combobox")) {
                    String[] constraint;
                    List<CustomizeFieldOptionValue> list =
                            customizeFieldOptionValueRepository.findCustomizeFieldOptionValuesByFieldOptionIdAndStatus(dynamicHeader.get(i).getFieldOptionsId(), 1L);
                    constraint = new String[list.size()];
                    for (int j = 0; j < list.size(); j++) {
                        constraint[j] = list.get(j).getName();
                    }
                    DataValidationConstraint comboboxConstraint = dataValidationHelper.createExplicitListConstraint(constraint);
                    CellRangeAddressList comboboxCellRange = new CellRangeAddressList(4, 9999, 12 + i, 12 + i);
                    DataValidation comboboxValidation = dataValidationHelper.createValidation(comboboxConstraint, comboboxCellRange);
                    comboboxValidation.setSuppressDropDownArrow(true);
                    comboboxValidation.setShowErrorBox(true);
                    sheet.addValidationData(comboboxValidation);
                } else if (dynamicHeader.get(i).getType().equals("checkbox")) {
                    DataValidationConstraint yesNoConstraint = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("customer.yes", locale), BundleUtils.getLangString("customer.not", locale)});
                    CellRangeAddressList checkboxCellRange = new CellRangeAddressList(4, 9999, 12 + i, 12 + i);
                    DataValidation yesNoValidation = dataValidationHelper.createValidation(yesNoConstraint, checkboxCellRange);
                    yesNoValidation.setShowErrorBox(true);
                    yesNoValidation.setSuppressDropDownArrow(true);
                    sheet.addValidationData(yesNoValidation);
                }
            }
            //</editor-fold>

            //<editor-fold desc="Cho những trường tĩnh" defaultstate="collapsed">
            DataValidationConstraint cusTypeConstraint = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("customer.cusType.normal", locale), BundleUtils.getLangString("customer.cusType.vip", locale), BundleUtils.getLangString("customer.cusType.blacklist", locale)});
            DataValidationConstraint isAllowConstraint = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("customer.yes", locale), BundleUtils.getLangString("customer.not", locale)});
            CellRangeAddressList cusTypeCellRangeAddressList = new CellRangeAddressList(4, 9999, 6, 6);
            CellRangeAddressList callCellRangeAddressList = new CellRangeAddressList(4, 9999, 9, 9);
            CellRangeAddressList emailCellRangeAddressList = new CellRangeAddressList(4, 9999, 10, 10);
            CellRangeAddressList smsCellRangeAddressList = new CellRangeAddressList(4, 9999, 11, 11);
            DataValidation cusTypeValidation = dataValidationHelper.createValidation(cusTypeConstraint, cusTypeCellRangeAddressList);
            DataValidation callValidation = dataValidationHelper.createValidation(isAllowConstraint, callCellRangeAddressList);
            DataValidation emailValidation = dataValidationHelper.createValidation(isAllowConstraint, emailCellRangeAddressList);
            DataValidation smsValidation = dataValidationHelper.createValidation(isAllowConstraint, smsCellRangeAddressList);
            cusTypeValidation.setSuppressDropDownArrow(true);
            cusTypeValidation.setShowErrorBox(true);
            callValidation.setSuppressDropDownArrow(true);
            callValidation.setShowErrorBox(true);
            emailValidation.setSuppressDropDownArrow(true);
            emailValidation.setShowErrorBox(true);
            smsValidation.setSuppressDropDownArrow(true);
            smsValidation.setShowErrorBox(true);
            sheet.addValidationData(cusTypeValidation);
            sheet.addValidationData(callValidation);
            sheet.addValidationData(emailValidation);
            sheet.addValidationData(smsValidation);
            //</editor-fold>

            //</editor-fold>

            //<editor-fold desc="Ghi header" defaultstate="collapsed">
            Drawing drawing = sheet.createDrawingPatriarch();
            ClientAnchor anchor = creationHelper.createClientAnchor();
            Row row0 = sheet.createRow(0);
            Row row2 = sheet.createRow(2);
            Row row3 = sheet.createRow(3);
            Cell cell0 = row0.createCell(0);
            cell0.setCellStyle(headerStyle);
            cell0.setCellValue(BundleUtils.getLangString("customer.importCustomer", locale));
            Cell cell2 = row2.createCell(0);
            cell2.setCellStyle(importantStyle);
            cell2.setCellValue(BundleUtils.getLangString("customer.notice", locale));
            for (int i = 0; i < header.size(); i++) {
                sheet.setDefaultColumnStyle(i, columnStyle);
                Cell headerCell = row3.createCell(i);
                headerCell.setCellValue(header.get(i).getTitle().split("#")[0].trim());
                headerStyle.setBorderTop(BorderStyle.THIN);
                headerStyle.setBorderRight(BorderStyle.THIN);
                headerStyle.setBorderBottom(BorderStyle.THIN);
                headerStyle.setBorderLeft(BorderStyle.THIN);
                headerFont.setFontHeightInPoints((short) 11);
                headerCell.setCellStyle(headerStyle);
                if (i == 0) {
                    sheet.setColumnWidth(i, 2500);
                } else {
                    sheet.setColumnWidth(i, 6000);
                }
                anchor.setCol1(headerCell.getColumnIndex());
                anchor.setCol2(headerCell.getColumnIndex() + 2);
                anchor.setRow1(row3.getRowNum());
                anchor.setRow2(row3.getRowNum() + 4);
                if (header.get(i).getTitle().contains("#")) {
                    Comment comment = drawing.createCellComment(anchor);
                    RichTextString str = creationHelper.createRichTextString(header.get(i).getTitle().split("#")[1]);
                    comment.setString(str);
                    comment.setAuthor("APACHE POI");
                    headerCell.setCellComment(comment);
                }
            }
            //</editor-fold>

            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 13));
            sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 13));
            workbook.write(os);
            os.flush();
            os.close();
            return os.toByteArray();
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            return null;
        } finally {
            if (workbook != null) workbook.close();
        }
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<CustomizeFieldObject> getCustomizeField(Long customerId) {
        List<CustomizeFieldObject> customizeFieldDTOList;
        try {
            customizeFieldDTOList = customizeFieldObjectRepository.findCustomizeFieldObjectsByFunctionCodeEqualsAndObjectId("CUSTOMER", customerId);
        } catch (Exception e) {
            LOGGER.info(e.getMessage());
            return null;
        }
        return customizeFieldDTOList;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<CustomerListDTO> getCustomerListInfo(CampaignCustomerDTO campaignCustomerDTO) {
        List<CustomerListDTO> customerList;
        try {
            customerList = customerRepository.getCustomerListInfo(campaignCustomerDTO);
        } catch (Exception e) {
            return null;
        }
        return customerList;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public List<CustomerDTO> getIndividualCustomerInfo(CampaignCustomerDTO campaignCustomerDTO) {
        List<CustomerDTO> customerList = new ArrayList<>();
        try {
            customerList = customerRepository.getIndividualCustomerInfo(campaignCustomerDTO);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            return null;
        }
        return customerList;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteCustomerFromCampaign(CampaignCustomerDTO campaignCustomerDTO) {
        ResultDTO resultDTO = new ResultDTO();
        Long companySiteId = campaignCustomerDTO.getCompanySiteId();
        Long campaignId = campaignCustomerDTO.getCampaignId();
        String[] lstCusId = campaignCustomerDTO.getLstCustomerId().split(",");
        List<Short> lstStatus = campaignCustomerRepository.getStatus();
        try {
            for (String cusId : lstCusId) {
                List<CampaignCustomer> listEntity = campaignCustomerRepository.findCampaignCustomersByCampaignIdAndCompanySiteIdAndCustomerIdAndInCampaignStatus(campaignId, companySiteId, Long.parseLong(cusId), (short) 1);
                for (CampaignCustomer entity : listEntity) {
                    if (entity.getStatus() == 0) {
                        campaignCustomerRepository.delete(entity);
                    } else if (lstStatus.contains(entity.getStatus())) {
                        entity.setInCampaignStatus((short) 0);
                        campaignCustomerRepository.save(entity);
                    }
                }
            }
            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 searchCampaignInformation(CampaignCustomerDTO campaignCustomerDTO) {
        ResultDTO resultDTO = new ResultDTO();
        List<CampaignInformationDTO> list = customerRepository.getCampaignInformation(campaignCustomerDTO);
        try {
            if (list.size() > 0) {
                resultDTO.setData(list.get(0));
            } else {
                resultDTO.setData(null);
            }
            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 addCustomerToCampaign(CampaignCustomerDTO campaignCustomerDTO) {
        ResultDTO resultDTO = new ResultDTO();
        Long companySiteId = campaignCustomerDTO.getCompanySiteId();
        Long campaignId = campaignCustomerDTO.getCampaignId();
        String[] lstCusId = campaignCustomerDTO.getLstCustomerId().split(",");
        try {
            for (String cusId : lstCusId) {
                CampaignCustomer entity = new CampaignCustomer();
                entity.setCompanySiteId(companySiteId);
                entity.setStatus((short) 0);
                entity.setCampaignId(campaignId);
                entity.setCustomerId(Long.parseLong(cusId));
                entity.setRecallCount(0L);
                entity.setInCampaignStatus((short) 1);
                campaignCustomerRepository.save(entity);
            }
            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 getDataForCombobox(CampaignCustomerDTO campaignCustomerDTO) {
        ResultDTO resultDTO = new ResultDTO();
        List<ComboboxDTO> list = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(" select distinct name value, field_option_value_id key from customize_field_option_value");
            sb.append(" where field_option_id = :p_field_id");
            sb.append(" order by name");

            params.put("p_field_id", campaignCustomerDTO.getField());

            list = namedParameterJdbcTemplate.query(sb.toString(), params, BeanPropertyRowMapper.newInstance(ComboboxDTO.class));
            resultDTO.setListData(list);
            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 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);
    }

    @Override
    public List<Customer> searchByQuery(String queryString) {
        RSQLVisitor<CriteriaQuery<Customer>, EntityManager> visitor = new JpaCriteriaQueryVisitor<>();
        CriteriaQuery<Customer> query;
        query = getCriteriaQuery(queryString, visitor);
        List<Customer> resultList = entityManager.createQuery(query).getResultList();
        if (resultList == null || resultList.isEmpty()) {
            return Collections.emptyList();
        }
        return resultList;
    }

    @Override
    public Long countByQuery(String queryString) {
        RSQLVisitor<CriteriaQuery<Long>, EntityManager> visitor = new JpaCriteriaCountQueryVisitor<Customer>();
        CriteriaQuery<Long> query;
        query = getCriteriaQuery(queryString, visitor);

        return entityManager.createQuery(query).getSingleResult();
    }


    private <T> CriteriaQuery<T> getCriteriaQuery(String queryString, RSQLVisitor<CriteriaQuery<T>, EntityManager> visitor) {
        Node rootNode;
        CriteriaQuery<T> query;
        try {
            rootNode = new RSQLParser().parse(queryString);
            query = rootNode.accept(visitor, entityManager);
        } catch (Exception e) {
            // e.printStackTrace();
            throw new IllegalArgumentException(e.getMessage());
        }
        return query;
    }

//        params.put('1', ["AND","AGE",">=","30"] )
//        lst.push(params);
//        StringBuilder sql = "Select ..... WHERE 1 = 1 "
//        for(lst){
//            String[] data = lst[i].value
//            sql.append(data[0] + data[1] + data[2] + data[3]);
//        }


//    Map<String, String> params = new HashMap<>();


    //    public ResultDTO searchCustomize(List<CustomizeFields> customizeFields) {
//        Map<String, CustomizeRequestDTo> hashCustomer = new HashMap<>();
//        CustomizeRequestDTo customizeRequestDTo = new CustomizeRequestDTo();
//        hashCustomer.put("1", customizeRequestDTo);
//        hashCustomer.put("2", customizeRequestDTo);
//        hashCustomer.put("3", customizeRequestDTo);
//        StringBuilder sb = new StringBuilder();
//        sb.append("");
//        sb.append("");
//        sb.append("");
//        sb.append("");
    @Override
    public ResultDTO listCustomizeFields(CustomizeFieldsDTO customizeFields) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            List<CustomizeFields> lstCustomizeFields = customizeFieldsRepository.findByFunctionCodeAndActiveAndStatusAndSiteId("CUSTOMER", 1L, 1L, customizeFields.getSiteId());
            String cf[][] = {
                    {"-1", "Mã Khách Hàng", "text"},
                    {"-2", "Tên khách hàng", "text"},
                    {"-3", "Tên công ty", "text"},
                    {"-4", "Giới tính", "combobox"},
                    {"-5", "Địa chỉ", "text"},
                    {"-6", "Nơi sinh", "text"},
                    {"-7", "Ngày sinh", "date"},
                    {"-8", "Số điện thoại", "text"},
                    {"-9", "Email", "text"},
                    {"-10", "Tên đăng nhập", "text"},
                    {"-11", "Loại Khách hàng", "combobox"},
            };
            for (int x = 0; x < 11; x++) {
                CustomizeFields datafill = new CustomizeFields();
                datafill.setCustomizeFieldId(Long.parseLong(cf[x][0]));
                datafill.setTitle(cf[x][1]);
                datafill.setType(cf[x][2]);
                lstCustomizeFields.add(datafill);
            }
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            resultDTO.setListData(lstCustomizeFields);
        } 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 searchCustomizeFields(CampaignCustomerDTO campaignCustomerDTO, UserSession userSession) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            int count = customerRepository.getCustomizeFields(campaignCustomerDTO, userSession, null).size();
            List<CustomerDTO> data = customerRepository.getCustomizeFields(campaignCustomerDTO, userSession, SQLBuilder.buildPageable(campaignCustomerDTO));
            resultDTO.setListData(data);
            resultDTO.setTotalRow(count);
            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;
    }

}
