package com.viettel.campaign.repository.impl;

import com.viettel.campaign.dto.CampaignDTO;
import com.viettel.campaign.dto.ResultDTO;
import com.viettel.campaign.dto.request_dto.CampaignRequestDTO;
import com.viettel.campaign.model.Campaign;
import com.viettel.campaign.repository.CampaignRepositoryCustom;
import com.viettel.campaign.utils.*;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.hql.internal.ast.util.SessionFactoryHelper;
import org.hibernate.transform.Transformers;
import org.hibernate.type.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.jdbc.object.SqlQuery;
import org.springframework.stereotype.Repository;
import sun.jvm.hotspot.ui.action.ShowAction;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.ArrayList;
import java.util.List;

@Repository
public class CampaignRepositoryImpl implements CampaignRepositoryCustom {

    @Autowired
    EntityManager entityManager;

    @Override
    public List<CampaignDTO> searchCampaignExecute(String agentId, Pageable pageable) {
        List<CampaignDTO> lst = new ArrayList<>();
        String expression = new StringBuilder()
                .append(" SELECT C.CAMPAIGN_ID, C.CAMPAIGN_NAME, C.STATUS ")
                .append(" FROM CAMPAIGN C ")
                .append(" INNER JOIN CAMPAIGN_AGENT CA ON C.CAMPAIGN_ID = CA.CAMPAIGN_ID ")
                .append(" WHERE 1 = 1 ")
                .append(" AND CA.AGENT_ID = :pAgentId ")
                .append(" AND C.STATUS IN (2,3) ")
                .toString();

        Query query = entityManager.createNativeQuery(expression);
        query.setParameter("pAgentId", agentId);

        List<Object[]> data = query.getResultList();

        for (Object[] obj : data) {
            CampaignDTO item = new CampaignDTO();
            item.setCampaignId((Long) obj[0]);
            item.setCampaignName((String) obj[1]);
            item.setStatus((Short) obj[0]);

            lst.add(item);
        }

        return lst;
    }

    @Override
    public ResultDTO search(CampaignRequestDTO requestDto) {
        ResultDTO result = new ResultDTO();
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

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

        try {
            StringBuilder sqlStr = new StringBuilder();
            sqlStr.append(SQLBuilder.getSqlQueryById(SQLBuilder.SQL_MODULE_CAMPAIGN_MNG, "search-campaign-by-params"));
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignCode())) {
                sqlStr.append(" AND UPPER(CAMPAIGN_CODE) LIKE :p_code");
            }
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignName())) {
                sqlStr.append(" AND UPPER(CAMPAIGN_NAME) LIKE :p_name");
            }
            if (requestDto.getStatus() != null) {
                sqlStr.append(" AND STATUS = :p_status");
            }
            if (requestDto.getFromDateFr() != null && DateTimeUtil.isValid(requestDto.getFromDateFr().getTime())) {
                sqlStr.append(" AND START_TIME >= :p_frDateFr");
            }
            if (requestDto.getFromDateTo() != null && DateTimeUtil.isValid(requestDto.getFromDateTo().getTime())) {
                sqlStr.append(" AND START_TIME <= :p_frDateTo");
            }
            if (requestDto.getToDateFr() != null && DateTimeUtil.isValid(requestDto.getToDateFr().getTime())) {
                sqlStr.append(" AND END_TIME >= :p_toDateFr");
            }
            if (requestDto.getToDateTo() != null && DateTimeUtil.isValid(requestDto.getToDateTo().getTime())) {
                sqlStr.append(" AND END_TIME <= :p_toDateTo");
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusFr())) {
//            sqlStr.append(" AND ")
            }
            if (!DataUtil.isNullOrZero(requestDto.getNumOfCusTo())) {

            }
            if (requestDto.getType() != null) {
                sqlStr.append(" AND CAMPAIGN_TYPE = :p_type");
            }
            if (requestDto.getChanel() != null) {
                sqlStr.append(" AND CHANEL = :p_chanel");
            }

//            Query query = entityManager.createNativeQuery(sqlStr.toString(), Campaign.class);
            SQLQuery query = session.createSQLQuery(sqlStr.toString());
            if (!DataUtil.isNullOrEmpty(requestDto.getCampaignCode())) {
                query.setParameter("p_code", "%" +
                        requestDto.getCampaignCode().toUpperCase()
                                .replace("\\", "\\\\")
                                .replaceAll("%", "\\\\%")
                                .replaceAll("_", "\\\\_")
                        + "%");
            }

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

            if (requestDto.getStatus() != null) {
                query.setParameter("p_status", requestDto.getStatus());
            }
            if (requestDto.getFromDateFr() != null && DateTimeUtil.isValid(requestDto.getFromDateFr().getTime())) {
                query.setParameter("p_frDateFr", requestDto.getFromDateFr());
            }
            if (requestDto.getFromDateTo() != null && DateTimeUtil.isValid(requestDto.getFromDateTo().getTime())) {
                query.setParameter("p_frDateTo", requestDto.getFromDateTo());
            }
            if (requestDto.getToDateFr() != null && DateTimeUtil.isValid(requestDto.getToDateFr().getTime())) {
                query.setParameter("p_toDateFr", requestDto.getToDateFr());
            }
            if (requestDto.getToDateTo() != null && DateTimeUtil.isValid(requestDto.getToDateTo().getTime())) {
                query.setParameter("p_toDateTo", requestDto.getToDateTo());
            }
            if (requestDto.getType() != null) {
                query.setParameter("p_type", requestDto.getType());
            }
            if (requestDto.getChanel() != null) {
                query.setParameter("p_chanel", requestDto.getChanel());
            }

            query.addScalar("campaignId", new LongType());
            query.addScalar("campaignCode", new StringType());
            query.addScalar("campaignName", new StringType());
            query.addScalar("campaignType", new StringType());
            query.addScalar("chanel", new ShortType());
            query.addScalar("startTime", new DateType());
            query.addScalar("endTime", new DateType());
            query.addScalar("customerNumber", new LongType());
            query.addScalar("status", new ShortType());

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

    private Pageable buildPageable(CampaignRequestDTO obj) {
        Pageable pageable = null;
        String[] sorts = obj.getSort().split(",");
        Sort sort = new Sort(Sort.Direction.fromString(sorts[1]), sorts[0]);
        pageable = new PageRequest(obj.getPage(), obj.getPageSize(), sort);
        return pageable;
    }

//    private CampaignDTO mappingData(Object[] object) {
//        CampaignDTO dto = new CampaignDTO();
//
//    }
}
