package com.viettel.campaign.service.impl;

import com.viettel.campaign.model.Campaign;
import com.viettel.campaign.model.TimeRangeDialMode;
import com.viettel.campaign.model.TimeZoneDialMode;
//import com.viettel.campaign.model.UserActionLog;
import com.viettel.campaign.repository.CampaignRepository;
import com.viettel.campaign.repository.TimeRangeDialModeRepository;
import com.viettel.campaign.repository.TimeZoneDialModeRepository;
//import com.viettel.campaign.repository.UserActionLogRepository;
import com.viettel.campaign.repository.UserActionLogRepositoryCustom;
import com.viettel.campaign.repository.impl.CampaignRepositoryImpl;
import com.viettel.campaign.service.CampaignService;
import com.viettel.campaign.utils.Constants;
import com.viettel.campaign.web.dto.*;
import com.viettel.campaign.web.dto.request_dto.CampaignRequestDTO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class CampaignServiceImpl implements CampaignService {
    private static final Logger logger = LogManager.getLogger(CampaignRepositoryImpl.class);

    @Autowired
    CampaignRepository campaignRepository;

    @Autowired
    TimeZoneDialModeRepository timeZoneDialModeRepository;

    @Autowired
    TimeRangeDialModeRepository timeRangeDialModeRepository;

    @Autowired
    UserActionLogRepositoryCustom userActionLogRepository;

    @Autowired
    ModelMapper modelMapper;

    @Override
    public ResultDTO searchCampaignExecute(CampaignRequestDTO requestDto) {
        return campaignRepository.searchCampaignExecute(requestDto);
    }

    @Override
    public ResultDTO search(CampaignRequestDTO requestDto) {
        return campaignRepository.search(requestDto);
    }

    @Override
    public ResultDTO findByCampaignCode(CampaignRequestDTO requestDTO) {
        return campaignRepository.findByCampaignCode(requestDTO);
    }

    @Override
    public List<Campaign> findAllCondition(Long companySiteId) {
        return campaignRepository.findAllByCompanySiteId(companySiteId);
    }

    @Override
    public List<Campaign> findCampaignByCompanySiteIdAndStartTimeIsLessThanEqualAndStatusIn(Long siteId, Date startTime, List<Long> status) {
        return campaignRepository.findCampaignByCompanySiteIdAndStartTimeIsLessThanEqualAndStatusIn(siteId, startTime, status);
    }

    @Override
    public List<Campaign> findCampaignByCompanySiteIdAndEndTimeIsLessThanEqualAndStatusIn(Long siteId, Date endTime, List<Long> status) {
        return campaignRepository.findCampaignByCompanySiteIdAndEndTimeIsLessThanEqualAndStatusIn(siteId, endTime, status);
    }

    @Override
    public Campaign updateProcess(Campaign c) {
        return campaignRepository.save(c);
    }

    @Override
    public ResultDTO findByCampaignId(Long campaignId) {
        ResultDTO result = new ResultDTO();
        Campaign campaign = campaignRepository.findByCampaignId(campaignId);

        if (campaign != null) {
            result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            result.setErrorCode(Constants.ApiErrorDesc.SUCCESS);
            result.setData(campaign);
        } else {
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setErrorCode(Constants.ApiErrorDesc.ERROR);
        }

        return result;
    }

    @Override
    public ResultDTO addNewCampaign(CampaignDTO campaignDTO) {
        logger.info("=== Start add new  campaign ");
        ResultDTO resultDTO = new ResultDTO();
        Campaign campaign = modelMapper.map(campaignDTO, Campaign.class);
        Long campaignId;
        List<TimeZoneDialModeDTO> timeZoneDialModes = new ArrayList<>();
        List<TimeRangeDialModeDTO> timeRangeDialModes = new ArrayList<>();
        List<TimeRangeDialMode> lstTimeRangeModeToInsert = new ArrayList<>();
        List<TimeZoneDialMode> lstTimeZoneModeToInser = new ArrayList<>();
        try {
            String campaignCode = generateCampaignCode(campaignDTO.getCampaignType(), campaignDTO.getChanel());
            campaign.setCampaignCode(campaignCode);
            Campaign campaignResult = campaignRepository.save(campaign);
            campaignId = campaign.getCampaignId();
            //insert sub tables

            if (campaignDTO.getLstTimeRange().size() > 0) {
                timeRangeDialModes = campaignDTO.getLstTimeRange();
                timeRangeDialModes.forEach(item -> {
                    item.setCampaignId(campaignId);
                    TimeRangeDialMode timeRangeDialMode = modelMapper.map(item, TimeRangeDialMode.class);
                    lstTimeRangeModeToInsert.add(timeRangeDialMode);
                });
                timeRangeDialModeRepository.saveAll(lstTimeRangeModeToInsert);
            }
            if (campaignDTO.getLstTimeZone().size() > 0) {
                timeZoneDialModes = campaignDTO.getLstTimeZone();
                timeZoneDialModes.forEach(item -> {
                    item.setCampaignId(campaignId);
                    TimeZoneDialMode timeZoneDialMode = modelMapper.map(item, TimeZoneDialMode.class);
                    lstTimeZoneModeToInser.add(timeZoneDialMode);
                });
                timeZoneDialModeRepository.saveAll(lstTimeZoneModeToInser);
            }
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            resultDTO.setData(campaignResult);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    public Map countRecallCustomer(Long companySiteId, Long agentId) {
        Map result = new HashMap();
        Long count = campaignRepository.countRecallCustomer(companySiteId, agentId);
        ResultDTO resultDTO = new ResultDTO();
        if (count != null) {
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            result.put("info", resultDTO);
            result.put("result", count);
        } else {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
            result.put("info", resultDTO);
            result.put("result", 0);
        }

        return result;
    }

    @Override
    public ResultDTO findCampaignById(Long campaignId) {
        logger.info("=== Start find campaign by id: " + campaignId);
        ResultDTO resultDTO = new ResultDTO();
        try {
            Campaign campaign = campaignRepository.findById(campaignId).orElse(null);
            if (campaign != null) {
                resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
                resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
                resultDTO.setData(campaign);
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    public ResultDTO changeCampaignStatus(CampaignDTO dto) {
        ResultDTO result = new ResultDTO();
        try {
            Campaign entity = campaignRepository.findCampaignByCampaignIdAndCompanySiteId(dto.getCampaignId(), dto.getCompanySiteId());
            if (entity != null) {
                entity.setStatus(dto.getStatus().longValue());
                entity.setUpdateTime(new Date());
                entity.setUpdateBy(dto.getUpdateBy());
                campaignRepository.save(entity);
                UserActionLogDTO userActionLog = new UserActionLogDTO();
                userActionLog.setAgentId(null);
                userActionLog.setSessionId(dto.getSessionId());
                userActionLog.setCompanySiteId(dto.getCompanySiteId());
                userActionLog.setDescription(null);
                userActionLog.setStartTime(new Date());
                userActionLog.setEndTime(null);
                userActionLog.setObjectId(entity.getCampaignId());
                if (dto.getStatus().equals((short) -1)) {
                    userActionLog.setActionType((short) 2);
                }
                else if(dto.getStatus().equals((short) 4)) {
                    userActionLog.setActionType((short) 7);
                }
                else if(dto.getStatus().equals((short) 3)) {
                    userActionLog.setActionType((short) 4);
                }
                else if(dto.getStatus().equals((short) 2)) {
                } else if (dto.getStatus().equals((short) 5)) {
                    userActionLog.setActionType((short) 7);
                } else if (dto.getStatus().equals((short) 4)) {
                    userActionLog.setActionType((short) 4);
                } else if (dto.getStatus().equals((short) 3)) {
                    userActionLog.setActionType((short) 5);
                }

                userActionLogRepository.insertToUserActionLog(userActionLog);
                result.setData(entity);
                result.setDescription(Constants.ApiErrorDesc.SUCCESS);
                result.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            } else {
                result.setErrorCode(Constants.ApiErrorCode.ERROR);
                result.setDescription("Entity not found");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result.setErrorCode(Constants.ApiErrorCode.ERROR);
            result.setDescription(e.getMessage());
        }
        return result;
    }

    @Override
    public ResultDTO checkAllowStatusToPrepare(Long campaignId) {
        return campaignRepository.checkAllowStatusToPrepare(campaignId);
    }

    private String generateCampaignCode(String campaignType, Short chanel) {
        int year = Calendar.getInstance().get(Calendar.YEAR);
        String maxIndexStr = campaignRepository.getMaxCampaignIndex();
        if (maxIndexStr != null) {
            Long maxIndex = Long.valueOf(maxIndexStr) + 1;
            String result = campaignType + "_" + chanel + "_" + year + "_" + maxIndex.toString();
            return result;
        }
        return null;
    }
}
