package com.viettel.campaign.service.impl;

import com.viettel.campaign.config.DataSourceQualify;
import com.viettel.campaign.mapper.CampaignCompleteCodeMapper;

import com.viettel.campaign.model.ccms_full.CampaignCfg;
import com.viettel.campaign.repository.ccms_full.CampaignCfgRepository;
import com.viettel.campaign.repository.ccms_full.CampaignRepository;
import com.viettel.campaign.service.CampaignCfgService;
import com.viettel.campaign.utils.Constants;
import com.viettel.campaign.utils.DataUtil;
import com.viettel.campaign.utils.HibernateUtil;
import com.viettel.campaign.utils.SQLBuilder;
import com.viettel.campaign.web.dto.CampaignCfgDTO;
import com.viettel.campaign.web.dto.ResultDTO;
import com.viettel.campaign.web.dto.request_dto.CampaignCfgRequestDTO;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.hibernate.type.DateType;
import org.hibernate.type.LongType;
import org.hibernate.type.ShortType;
import org.hibernate.type.StringType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class CampaignCfgServiceImpl implements CampaignCfgService {

    protected Logger logger = LoggerFactory.getLogger(CampaignCfgServiceImpl.class);

    @Autowired
    CampaignCfgRepository completeCodeRepository;

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

        Session session = null;

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

        try {
            session = sessionFactory.openSession();
            session.beginTransaction();
//            StringBuilder sqlStrBuilder = new StringBuilder();
//            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_STATUS_MNG, "findAll-CampaignCompleteCode"));
            StringBuilder sb = new StringBuilder();

            sb.append("SELECT");
            sb.append("    CAMPAIGN_COMPLETE_CODE_ID campaignCompleteCodeId,");
            sb.append("    IS_RECALL isRecall ,");
            sb.append("    CAMPAIGN_ID campaignId,");
            sb.append("    COMPLETE_VALUE completeValue,");
            sb.append("    COMPLETE_NAME completeName,");
            sb.append("    COMPLETE_TYPE completeType,");
            sb.append("    CAMPAIGN_TYPE campaignType,");
            sb.append("    DESCRIPTION description,");
            sb.append("    STATUS  status,");
            sb.append("    COMPANY_SITE_ID companySiteId,");
            sb.append("    UPDATE_BY updateBy ,");
            sb.append("    UPDATE_AT updateAt,");
            sb.append("    CREATE_BY createBy,");
            sb.append("    CREATE_AT createAt,");
            sb.append("    IS_FINISH isFinish,");
            sb.append("    IS_LOCK isLock,");
            sb.append("    DURATION_LOCK durationLock,");
            sb.append("    CHANEL chanel");
            sb.append(" FROM CAMPAIGN_COMPLETE_CODE");
            sb.append(" where 1 = 1");
            sb.append("  AND STATUS = 1");
            sb.append("  and COMPANY_SITE_ID = :p_company_site_id");
            sb.append(" and COMPLETE_VALUE not in (1,2,3,4)");
            sb.append("ORDER BY to_number(COMPLETE_VALUE) ");
            logger.info("SQL statement: " + sb);



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

            query.setParameter("p_company_site_id", companySiteId);

            query.addScalar("campaignCompleteCodeId", new LongType());
            query.addScalar("campaignId", new LongType());
            query.addScalar("completeName", new StringType());
            query.addScalar("completeValue", new StringType());
            query.addScalar("description", new StringType());
            query.addScalar("status", new ShortType());
            query.addScalar("completeType", new ShortType());
            query.addScalar("isRecall", new ShortType());
            query.addScalar("updateAt", new DateType());
            query.addScalar("updateBy", new StringType());
            query.addScalar("createBy", new StringType());
            query.addScalar("createAt", new DateType());
            query.addScalar("campaignType", new StringType());
            query.addScalar("isFinish", new ShortType());
            query.addScalar("isLock", new ShortType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("durationLock", new LongType());
            query.addScalar("chanel", new LongType());
            query.setResultTransformer(Transformers.aliasToBean(CampaignCfgDTO.class));
            int count = 0;
            List<CampaignCfgDTO> dtoList = query.list();
            if (dtoList.size() > 0) {
                count = query.list().size();
            }

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

            List<CampaignCfgDTO>data = query.list();
            Page<CampaignCfgDTO> dataPage = new PageImpl<>(data, pageable, count);
            resultDTO.setData(dataPage);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            logger.error(e.getMessage(), e);
        } finally {
            if(session != null) session.close();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public Map listCompleteCodeByName(int page, int pageSize, String sort, String name) {
        Map result = new HashMap();
        List<CampaignCfg> lst = new ArrayList<>();
        List<CampaignCfg> count = new ArrayList<>();

        lst = completeCodeRepository.findByCompleteNameContains(name, PageRequest.of(page, pageSize, Sort.by(sort)));
        count = completeCodeRepository.findByCompleteNameContains(name, null);

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

        return result;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO createCompleteCode(CampaignCfgDTO completeCodeDTO, Long userId) {
        ResultDTO resultDTO = new ResultDTO();
        CampaignCompleteCodeMapper compCodeMapper = new CampaignCompleteCodeMapper();
        Date today = new Date();
        CampaignCfg compCode = new CampaignCfg();

        try {
            if (completeCodeDTO != null) {

                // insert
//                compCode = compCodeMapper.toPersistenceBean(completeCodeDTO);
//                compCode = completeCodeRepository.save(compCode);
//
//                resultDTO.setErrorCode("0");
//                resultDTO.setDescription("Complete Code: " + compCode.getCampaignCompleteCodeId() + " created!");
                CampaignCfg cl = new CampaignCfg();
                cl.setStatus((short) 1);
                cl.setCreateBy(String.valueOf(userId));
                cl.setCreateAt(new Date());
                cl.setUpdateBy(null);
                cl.setUpdateAt(null);
                cl.setChanel(completeCodeDTO.getChanel());
                cl.setCompleteName(completeCodeDTO.getCompleteName().trim());
                cl.setCompleteValue(completeCodeDTO.getCompleteValue());
                cl.setCampaignType(completeCodeDTO.getCampaignType());
                cl.setDescription(completeCodeDTO.getDescription().trim());
                cl.setCompleteType(completeCodeDTO.getCompleteType());
                cl.setCompanySiteId(completeCodeDTO.getCompanySiteId());
                cl.setCampaignCompleteCodeId(completeCodeDTO.getCampaignCompleteCodeId());
                cl.setCampaignId(completeCodeDTO.getCampaignId());
                cl.setDurationLock(completeCodeDTO.getDurationLock());
                cl.setIsFinish(completeCodeDTO.getIsFinish());
                cl.setIsLock(completeCodeDTO.getIsLock());
                cl.setIsRecall(completeCodeDTO.getIsRecall());

                resultDTO.setErrorCode("0");
                resultDTO.setDescription("Complete Code: " + compCode.getCampaignCompleteCodeId() + " created!");
                resultDTO.setData(completeCodeRepository.save(cl));
                return resultDTO;
            } else {
                resultDTO.setErrorCode("-2");
                resultDTO.setDescription("CompleteCodeDTO null");
            }
        } catch (Exception e) {
            // e.printStackTrace();
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO updateCompleteCode(CampaignCfgDTO completeCodeDTO) {
        ResultDTO resultDTO = new ResultDTO();
        CampaignCompleteCodeMapper compCodeMapper = new CampaignCompleteCodeMapper();
        Date today = new Date();
        CampaignCfg compCode = new CampaignCfg();

        try {
            if (completeCodeDTO != null) {
                // update
                compCode = compCodeMapper.toPersistenceBean(completeCodeDTO);
                completeCodeRepository.save(compCode);

                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription("Complete Code: " + compCode.getCampaignCompleteCodeId() + " updated!");
            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription("CompleteCodeDTO null");
            }
        } 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 deleteCompleteCode(CampaignCfgRequestDTO completeCodeDTO) {
        ResultDTO resultDTO = new ResultDTO();
        List<Long> listId = new ArrayList<>();
        listId.add(completeCodeDTO.getCampaignCompleteCodeID());
        try {
            // delete
            if (completeCodeDTO != null) {
//                completeCodeRepository.deleteCampaignCompleteCodeBy(completeCodeDTO.getCampaignCompleteCodeID(), completeCodeDTO.getCompanySiteId());

                if (completeCodeRepository.findAllCampaignCfg(listId, completeCodeDTO.getCompanySiteId()).size() > 0) {
                    completeCodeRepository.deleteCampaignCompleteCodeBy(completeCodeDTO.getCampaignCompleteCodeID(), completeCodeDTO.getCompanySiteId());

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

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

        } catch (Exception e) {
            // e.printStackTrace();
            logger.error(e.getMessage(), e);
        }

        return resultDTO;
    }


    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteList(CampaignCfgRequestDTO completeCodeDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            if (completeCodeDTO != null) {
                if (completeCodeRepository.findAllCampaignCfg(completeCodeDTO.getListId(), completeCodeDTO.getCompanySiteId()).size() > 0) {
                    completeCodeRepository.deletedList(completeCodeDTO.getListId(), completeCodeDTO.getCompanySiteId());

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

            } else {
                resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
                resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            // e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO deleteById(CampaignCfgRequestDTO completeCodeDTO) {
        ResultDTO result = new ResultDTO();
        try {
            if (completeCodeDTO != null) {
                if (completeCodeRepository.findAllCampaignCfg(completeCodeDTO.getListId(), completeCodeDTO.getCompanySiteId()).size() > 0) {
                    completeCodeRepository.deletedList(completeCodeDTO.getListId(), completeCodeDTO.getCompanySiteId());

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

            } else {
                result.setErrorCode(Constants.ApiErrorCode.ERROR);
                result.setDescription(Constants.ApiErrorDesc.ERROR);
            }
        } catch (Exception e) {
            // e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
        return  result;
    }


    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO findMaxValueCampaignCompleteCode(CampaignCfgDTO completeCodeDTO) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        Session session = null;

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

        try {
            session = sessionFactory.openSession();
            session.beginTransaction();
//            StringBuilder sqlStrBuilder = new StringBuilder();
//            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_STATUS_MNG, "get-max-value-completevalue"));
            StringBuilder sb = new StringBuilder();

            sb.append("SELECT max(to_number(COMPLETE_VALUE)) completeValue, COMPANY_SITE_ID ");
            sb.append(" companySiteId from CAMPAIGN_COMPLETE_CODE where COMPANY_SITE_ID = :p_site_id ");
            sb.append(" GROUP BY COMPANY_SITE_ID ");


            SQLQuery query = session.createSQLQuery(sb.toString());
            query.setParameter("p_site_id", completeCodeDTO.getCompanySiteId());

            query.addScalar("completeValue", new StringType());
            query.addScalar("companySiteId", new LongType());
            query.setResultTransformer(Transformers.aliasToBean(CampaignCfgDTO.class));

            List<CampaignCfgDTO> data = query.list();
            if (data != null && data.size() > 0) {
                int tmp = 5;
                String completeValue = data.get(0).getCompleteValue();
                if (completeValue != null && !completeValue.trim().equals("")) {
                    tmp = Integer.parseInt(completeValue) + 1;
                }
                resultDTO.setData(tmp);
            } else {
                resultDTO.setData(null);
            }

            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            logger.error(e.getMessage(), e);
        } finally {
            if(session != null) session.close();
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getListStatus(String completeValue, Short completeType, Long companySiteId) {
        ResultDTO resultDTO = new ResultDTO();
        List<CampaignCfg> list = new ArrayList<>();

        try {
            if (completeValue == null || completeValue.equalsIgnoreCase("null"))
                list = completeCodeRepository.getCustomerStatusByType(completeType, companySiteId);
            else
                list = completeCodeRepository.getCustomerStatus(completeValue, completeType, companySiteId);

            resultDTO.setListData(list);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(e.getMessage());
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO getListStatusWithoutType(String completeValue, Short completeType, Long companySiteId) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            List<CampaignCfg> list = completeCodeRepository.getCustomerStatusWithoutValue(completeValue, completeType, companySiteId);
            resultDTO.setListData(list);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(e.getMessage());
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO editCampaignCompleteCode(Long campaignCompleteCodeId) {
        ResultDTO resultDTO = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        Session session = null;

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

        try {
            session = sessionFactory.openSession();
            session.beginTransaction();
//            StringBuilder sqlStrBuilder = new StringBuilder();
//            sqlStrBuilder.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_STATUS_MNG,"findCampaignCodeById"));


            StringBuilder sb = new StringBuilder();

            sb.append("SELECT  CAMPAIGN_COMPLETE_CODE_ID campaignCompleteCodeId,");
            sb.append("        IS_RECALL isRecall ,");
            sb.append("        CAMPAIGN_ID campaignId,");
            sb.append("        COMPLETE_VALUE completeValue,");
            sb.append("        COMPLETE_NAME completeName,");
            sb.append("        COMPLETE_TYPE completeType,");
            sb.append("        CAMPAIGN_TYPE campaignType,");
            sb.append("        DESCRIPTION description,");
            sb.append("        STATUS  status,");
            sb.append("        COMPANY_SITE_ID companySiteId,");
            sb.append("        UPDATE_BY updateBy ,");
            sb.append("        UPDATE_AT updateAt,");
            sb.append("        CREATE_BY createBy,");
            sb.append("        CREATE_AT createAt,");
            sb.append("        IS_FINISH isFinish,");
            sb.append("        IS_LOCK isLock,");
            sb.append("        DURATION_LOCK durationLock,");
            sb.append("        CHANEL chanel");
            sb.append("        from CAMPAIGN_COMPLETE_CODE WHERE ");
            sb.append(" CAMPAIGN_COMPLETE_CODE_ID=:p_campaignComleteCode");


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

            query.setParameter("p_campaignComleteCode",campaignCompleteCodeId);

            query.addScalar("campaignCompleteCodeId", new LongType());
            query.addScalar("campaignId", new LongType());
            query.addScalar("completeName", new StringType());
            query.addScalar("completeValue", new StringType());
            query.addScalar("description", new StringType());
            query.addScalar("status", new ShortType());
            query.addScalar("completeType", new ShortType());
            query.addScalar("isRecall", new ShortType());
            query.addScalar("updateAt", new DateType());
            query.addScalar("updateBy", new StringType());
            query.addScalar("createBy", new StringType());
            query.addScalar("createAt", new DateType());
            query.addScalar("campaignType", new StringType());
            query.addScalar("isFinish", new ShortType());
            query.addScalar("isLock", new ShortType());
            query.addScalar("companySiteId", new LongType());
            query.addScalar("durationLock", new LongType());
            query.addScalar("chanel", new LongType());
            query.setResultTransformer(Transformers.aliasToBean(CampaignCfgDTO.class));
            List<CampaignCfgDTO>data = query.list();
            resultDTO.setData(data);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception e) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            logger.error(e.getMessage(), e);
        } finally {
            if(session != null) session.close();
        }

        return resultDTO;
    }

}
