package com.viettel.campaign.service.impl;

import com.viettel.campaign.config.DataSourceQualify;
import com.viettel.campaign.model.ccms_full.*;
import com.viettel.campaign.repository.ccms_full.*;
import com.viettel.campaign.service.ScenarioService;
import com.viettel.campaign.utils.BundleUtils;
import com.viettel.campaign.utils.Constants;
import com.viettel.campaign.utils.WorkBookBuilder;
import com.viettel.campaign.web.dto.*;
import com.viettel.econtact.filter.UserSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.XSSFWorkbook;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author anhvd_itsol
 */

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

    @Autowired
    ScenarioRepository scenarioRepository;

    @Autowired
    ScenarioQuestionRepository questionRepository;

    @Autowired
    ScenarioAnswerRepository answerRepository;

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    ContactQuestResultRepository questResultRepository;

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public Scenario findScenarioByCampaignIdAndCompanySiteId(Long campaignId, Long companySiteId) {
        try {
            return scenarioRepository.findScenarioByCampaignIdAndCompanySiteId(campaignId, companySiteId);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO update(ScenarioDTO scenarioDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            scenarioDTO.setUpdateBy(null);
            scenarioDTO.setUpdateTime(new Date());

            Scenario scenario = modelMapper.map(scenarioDTO, Scenario.class);
            scenarioRepository.save(scenario);
            resultDTO.setData(scenario);
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public ResultDTO sortQuestionAndAnswer(ScenarioDTO scenarioDTO) {
        ResultDTO resultDTO = new ResultDTO();
        try {
            List<ScenarioQuestionDTO> lstQuestion = scenarioDTO.getLstQuestion();
            List<ScenarioAnswerDTO> lstAnswer = scenarioDTO.getLstAnswer();
            List<ScenarioQuestion> questionsToSort = new ArrayList<>();
            List<ScenarioAnswer> answersToSort = new ArrayList<>();
            if (lstQuestion.size() > 0) {
                lstQuestion.forEach(item -> {
                    ScenarioQuestion question = questionRepository.findScenarioQuestionByScenarioQuestionId(item.getScenarioQuestionId());
                    if (question != null) {
                        question.setOrderIndex(item.getOrderIndex());
                        questionsToSort.add(question);
                    }
                });
                questionRepository.saveAll(questionsToSort);
            }
            if (lstAnswer.size() > 0) {
                lstAnswer.forEach(item -> {
                    ScenarioAnswer answer = answerRepository.findScenarioAnswerByScenarioAnswerId(item.getScenarioAnswerId());
                    if (answer != null) {
                        answer.setOrderIndex(item.getOrderIndex());
                        answersToSort.add(answer);
                    }
                });
                answerRepository.saveAll(answersToSort);
            }

            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }
        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public Integer countDuplicateScenarioCode(Long companySiteId, String code, Long scenarioId) {
        try {
            return scenarioRepository.countDuplicateScenarioCode(companySiteId, code, scenarioId);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public ResultDTO saveContacQuestResult(ContactQuestResultDTO dto) {
        ResultDTO resultDTO = new ResultDTO();

        if (dto != null) {
            ContactQuestResult cqr = questResultRepository.save(modelMapper.map(dto, ContactQuestResult.class));
            resultDTO.setErrorCode(Constants.ApiErrorCode.SUCCESS);
            resultDTO.setDescription(Constants.ApiErrorDesc.SUCCESS);
            resultDTO.setData(cqr);
        } else {
            resultDTO.setErrorCode(Constants.ApiErrorCode.ERROR);
            resultDTO.setDescription(Constants.ApiErrorDesc.ERROR);
        }

        return resultDTO;
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public XSSFWorkbook buildTemplate() {
        Locale locale = new Locale("vi", "VN");
        try {
            XSSFWorkbook workbook = new XSSFWorkbook();
            Sheet sheet;

            CellStyle styleTitle = WorkBookBuilder.buildDefaultStyleTitle(workbook);
            CellStyle styleRowHeader = WorkBookBuilder.buildDefaultStyleRowHeader(workbook);
            CellStyle styleRow = WorkBookBuilder.buildDefaultStyleRow(workbook);

            // list header
            List<String> fileHeaderList = new ArrayList<>();
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.questionCode", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.questionType", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.question", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.answer", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.hashInput", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.required", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.default", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.mappingQuestion", locale));
            //
            String sheetName = BundleUtils.getLangString("campaign", locale);
            sheet = workbook.createSheet(sheetName);

            // Title
            String title = BundleUtils.getLangString("scenario.template.title", locale);

            int rowTitleStart = 0;
            Row rowTitle = sheet.createRow(rowTitleStart);
            rowTitle.setHeight((short) 800);
            sheet.addMergedRegion(new CellRangeAddress(rowTitleStart, rowTitleStart, 0, 7));
            WorkBookBuilder.writeCellContent(rowTitle, styleTitle, 0, title);

            // Header
            int startRowTable = 2;
            Row rowHeader = sheet.createRow(startRowTable);
            for (int i = 0; i < fileHeaderList.size(); i++) {
                sheet.setColumnWidth(i, 6000);
                WorkBookBuilder.writeCellContent(rowHeader, styleRowHeader, i, fileHeaderList.get(i));
            }
            DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();

            //QuestionType
            DataValidationConstraint questionType = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("scenario.template.singleChoice", locale),
                    BundleUtils.getLangString("scenario.template.multiChoice", locale), BundleUtils.getLangString("scenario.template.text", locale)});
            CellRangeAddressList typeCellRangeAddressList = new CellRangeAddressList(3, 9999, 1, 1);
            DataValidation typeValidation = dataValidationHelper.createValidation(questionType, typeCellRangeAddressList);
            typeValidation.setSuppressDropDownArrow(true);
            sheet.addValidationData(typeValidation);

            //HashInputCombobox
            DataValidationConstraint hasInput = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("scenario.template.yes", locale), BundleUtils.getLangString("scenario.template.no", locale)});
            CellRangeAddressList hasInputCellRangeAddressList = new CellRangeAddressList(3, 9999, 4, 4);
            DataValidation hasInputValidation = dataValidationHelper.createValidation(hasInput, hasInputCellRangeAddressList);
            hasInputValidation.setSuppressDropDownArrow(true);
            sheet.addValidationData(hasInputValidation);

            //Required
            DataValidationConstraint required = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("scenario.template.yes", locale), BundleUtils.getLangString("scenario.template.no", locale)});
            CellRangeAddressList requiredCellRangeAddressList = new CellRangeAddressList(3, 9999, 5, 5);
            DataValidation requiredValidation = dataValidationHelper.createValidation(required, requiredCellRangeAddressList);
            requiredValidation.setSuppressDropDownArrow(true);
            sheet.addValidationData(requiredValidation);

            //Required
            DataValidationConstraint defaultValue = dataValidationHelper.createExplicitListConstraint(new String[]{BundleUtils.getLangString("scenario.template.yes", locale), BundleUtils.getLangString("scenario.template.no", locale)});
            CellRangeAddressList defaultValueCellRangeAddressList = new CellRangeAddressList(3, 9999, 6, 6);
            DataValidation defaultValueValidation = dataValidationHelper.createValidation(defaultValue, defaultValueCellRangeAddressList);
            defaultValueValidation.setSuppressDropDownArrow(true);
            sheet.addValidationData(defaultValueValidation);


            return workbook;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }

    @Override
    @Transactional(DataSourceQualify.CCMS_FULL)
    public Map<String, Object> readAndValidateCustomer(String path, UserSession userSession) {
        Locale locale = new Locale("vi", "VN");
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        Map<String, Object> result = new HashMap<>();
        StringBuilder sb = new StringBuilder();
        boolean isValid = false;
        try {
            List<String> fileHeaderList = new ArrayList<>();
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.questionCode", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.questionType", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.question", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.answer", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.hashInput", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.required", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.default", locale));
            fileHeaderList.add(BundleUtils.getLangString("scenario.template.mappingQuestion", locale));

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

            Font resultFont = workbook.createFont();
            resultFont.setBold(true);
            resultFont.setFontHeightInPoints((short) 11);
            CellStyle resultStyle = workbook.createCellStyle();
            resultStyle.setFont(resultFont);
            resultStyle.setBorderLeft(BorderStyle.THIN);
            resultStyle.setBorderRight(BorderStyle.THIN);
            resultStyle.setBorderBottom(BorderStyle.THIN);
            resultStyle.setBorderTop(BorderStyle.THIN);

            //kt file du lieu rong
            if (sheet.getPhysicalNumberOfRows() == 3) {
                result.put("message", BundleUtils.getLangString("customer.noData", locale));
                result.put("file", file);
                return result;
            } else {
                Cell resultCell = sheet.getRow(3).createCell(sheet.getRow(3).getPhysicalNumberOfCells());
                resultCell.setCellValue(BundleUtils.getLangString("customer.result", locale));
                resultCell.setCellStyle(resultStyle);
            }

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

            //validate row
            for (int i = 4; i < sheet.getPhysicalNumberOfRows(); i++) {
                Row dataRow = sheet.getRow(i);
                if (dataRow != null) {
                    Object[] obj = new Object[row.getPhysicalNumberOfCells()];
                    for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
                        Cell dataCell = dataRow.getCell(j);
                        if (dataCell != null) {
//                            switch (dataCell.getCellTypeEnum()) {
//                                case NUMERIC:
//                                    obj[j] = dataCell.getNumericCellValue();
//                                    break;
//                                default:
//                                    obj[j] = dataCell.getStringCellValue();
//                                    break;
//                            }
                        } else {
//                            Cell headerCell = row.getCell(j);
//                            if (headerCell.getStringCellValue().equals(BundleUtils.getLangString("customer.cusType", locale))) {
//                                obj[j] = BundleUtils.getLangString("customer.cusType.normal", locale);
//                            } else if (headerCell.getStringCellValue().equals(BundleUtils.getLangString("customer.callAllowed", locale)) || headerCell.getStringCellValue().equals(BundleUtils.getLangString("customer.emailAllowed", locale))
//                                    || headerCell.getStringCellValue().equals(BundleUtils.getLangString("customer.smsAllowed", locale))) {
//                                obj[j] = BundleUtils.getLangString("customer.yes", locale);
//                                break;
//                            } else {
//                                obj[j] = null;
//                            }
                        }
                    }
                    rawDataList.add(obj);
                }
            }

            //insert data
            if (isValid) {
                for (int i = 0; i < rawDataList.size(); i++) {

                }
            }
        } catch (Exception ex) {
            logger.info(ex.getMessage(), ex);
            result.put("message", BundleUtils.getLangString("customer.errorValidate", locale));
        }
        return result;
    }
}
