package com.viettel.campaign.service.impl;

import com.viettel.campaign.mapper.CustomerListMapper;
import com.viettel.campaign.model.CustomerList;
import com.viettel.campaign.repository.CampaignCustomerListRepository;
import com.viettel.campaign.repository.CustomerListMappingRepository;
import com.viettel.campaign.repository.CustomerListRepository;
import com.viettel.campaign.service.CustomerService;
import com.viettel.campaign.utils.Constants;
import com.viettel.campaign.utils.HibernateUtil;
import com.viettel.campaign.utils.SQLBuilder;
import com.viettel.campaign.web.dto.CustomerDTO;
import com.viettel.campaign.web.dto.CustomerListDTO;
import com.viettel.campaign.web.dto.ResultDTO;
import com.viettel.campaign.mapper.CustomerMapper;
import com.viettel.campaign.model.Customer;
import com.viettel.campaign.repository.CustomerRepository;
import com.viettel.campaign.utils.DataUtil;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.*;

@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    EntityManager entityManager;

    @Autowired
    CustomerRepository customerRepository;

    @Autowired
    CustomerListRepository customerListRepository;

    @Autowired
    CampaignCustomerListRepository campaignCustomerListRepository;

    @Autowired
    CustomerListMappingRepository customerListMappingRepository;

    @Override
    public Map listAllCustomer(int page, int pageSize, String sort) {
        Map result = new HashMap();
        List<Customer> lst = new ArrayList<>();

        Pageable pageable = PageRequest.of(page, pageSize, Sort.by(sort));
        Page<Customer> pc = customerRepository.findAll(pageable);

        result.put("totalItem", pc.getTotalElements());
        result.put("customers", pc.iterator());

        return result;
    }

    @Override
    public Map listCustByName(int page, int pageSize, String sort, String name) {
        Map result = new HashMap();
        List<Customer> lst = new ArrayList<>();

        Pageable pageable = PageRequest.of(page, pageSize, Sort.by(sort));
        lst = customerRepository.findByName(name, pageable);

        result.put("totalItem", lst.size());
        result.put("customers", lst);

        return result;
    }

    @Override
    @Transactional
    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
    public ResultDTO deleteCustomer(CustomerDTO customerDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (customerDTO != null) {
                // delete
                customerRepository.deleteById(customerDTO.getCustomerId());

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

    @Transactional
    @Override
    public ResultDTO deleteIds(List<Long> ids) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (ids != null) {
                customerRepository.deleteIds(ids);
                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;
    }

    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
    public Map getCustomerList(int page, int pageSize, String sort) {
        Map result = new HashMap();
        List<CustomerList> list = new ArrayList<>();

        Pageable pageable = PageRequest.of(page, pageSize, Sort.by(sort));
        Page<CustomerList> pc = customerListRepository.findAll(pageable);

        result.put("totalItem", pc.getTotalElements());
        result.put("customerList", pc.iterator());

        return result;
    }

    @Override
    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
    public ResultDTO updateCustomerList(CustomerListDTO customerListDTO) {
        ResultDTO resultDTO = new ResultDTO();
        CustomerListMapper customerListMapper = new CustomerListMapper();
        CustomerList customerList = customerListRepository.findCustomerListByCustomerListId(customerListDTO.getCustomerListId());

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

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

    @Transactional
    @Override
    public ResultDTO deleteCustomerList(CustomerListDTO customerListDTO) {
        ResultDTO resultDTO = new ResultDTO();
        CustomerListMapper customerListMapper = new CustomerListMapper();
        CustomerList customerList = customerListRepository.findCustomerListByCustomerListId(customerListDTO.getCustomerListId());

        try {
            // delete
            if (DataUtil.isNullOrZero(campaignCustomerListRepository.campaignCount(customerListDTO.getCustomerListId()))) {
                customerList = customerListMapper.toPersistenceBean(customerListDTO);
                customerList = customerListRepository.save(customerList);

                customerListMappingRepository.deleteMappingByCustomerListId(customerListDTO.getCustomerListId());

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

    @Transactional
    @Override
    public ResultDTO deleteCustomerListIds(List<Long> ids) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (ids != null) {
                if (DataUtil.isNullOrZero(campaignCustomerListRepository.campaignIdsCount(ids))) {
                    customerListRepository.deleteCustomerListIds(ids);
                    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
    public ResultDTO searchCustomerList(String customerListCode, String customerListName, Date dateFrom, Date dateTo, int page, int pageSize, String sort) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        StringBuilder sqlStrBuilder = new StringBuilder();
        sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "search-campaign-customer-by-params"));
        if (!customerListCode.equals("undefined")) {
            sqlStrBuilder.append(" AND CUSTOMER_LIST_CODE LIKE :p_list_code");
        }
        if (!customerListName.equals("undefined")) {
            sqlStrBuilder.append(" AND CUSTOMER_LIST_NAME LIKE :p_list_name");
        }

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

        query.setParameter("p_date_from", dateFrom);
        query.setParameter("p_date_to", dateTo);

        if (!customerListCode.equals("undefined")) {
            query.setParameter("p_list_code", "%" +
                    customerListCode
                            .replace("\\", "\\\\")
                            .replaceAll("%", "\\\\%")
                            .replaceAll("_", "\\\\_")
                    + "%");
        }

        if (!customerListName.equals("undefined")) {
            query.setParameter("p_list_name", "%" +
                    customerListName
                            .replace("\\", "\\\\")
                            .replaceAll("%", "\\\\%")
                            .replaceAll("_", "\\\\_")
                    + "%");
        }

//        Pageable pageable = PageRequest.of(page, pageSize, Sort.by(sort));
//        Page<CustomerList> pc = customerListRepository.search();
//
//        result.put("totalItem", pc.getTotalElements());
//        result.put("searchList", pc.iterator());
        query.setResultTransformer(Transformers.aliasToBean(CustomerListDTO.class));
        int count = 0;
        List<CustomerListDTO> dtoList = query.list();
        if (dtoList.size() > 0) {
            count = query.list().size();
        }
//        Pageable pageable = buildPageable();
//        if (pageable != null) {
//            query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
//            query.setMaxResults(pageable.getPageSize());
//        }

        Pageable pageable = PageRequest.of(page, pageSize, Sort.by(sort));

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

        return resultDTO;
    }
}
