package pwc.taxtech.atms.service.impl;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.constant.Constant;
import pwc.taxtech.atms.dto.*;
import pwc.taxtech.atms.entitiy.CellTemplate;
import pwc.taxtech.atms.entitiy.CellTemplateExample;
import pwc.taxtech.atms.entitiy.Template;
import pwc.taxtech.atms.entitiy.TemplateExample;
import pwc.taxtech.atms.service.TemplateService;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Service
public class TemplateServiceImpl extends AbstractService implements TemplateService {

    @Override
    public List<TemplateDto> get(Long templateGroupID, Integer reportType) {

        TemplateExample example = new TemplateExample();

        TemplateExample.Criteria criteria = example.createCriteria().andTemplateGroupIdEqualTo(templateGroupID);

        if (reportType != null) {
            criteria.andReportTypeEqualTo(reportType.intValue());
        }

        example.setOrderByClause("order_index asc");

        List<Template> templates = templateMapper.selectByExample(example);
        List<TemplateDto> templateDtos = new ArrayList<>();
        for (Template template : templates) {
            TemplateDto dto = new TemplateDto();
            CommonUtils.copyProperties(template, dto);
            templateDtos.add(dto);
        }
        return templateDtos;
    }

    @Override
    public String getTemplatePath(Long templateID) {
        String result = "";
        Template template = templateMapper.selectByPrimaryKey(templateID);
        if (template != null) {

            String PREFIX_VALUE = "~";
            if (template.getPath().startsWith(PREFIX_VALUE)) {
                result = template.getPath().substring(1, template.getPath().length());
            } else {
                result = template.getPath();
            }
        }
        return result;
    }

    @Override
    public Template getTemplateByID(Long templateID) {
        return templateMapper.selectByPrimaryKey(templateID);
    }

    @Override
    public List<TemplateUniqDto> getTemplateUniqList(String serviceTypeID, Integer payTaxType, Integer reportType, String industryIDs) {

        Map<String, Object> map = new HashMap<>(4);
        map.put("serviceTypeID", serviceTypeID);
        map.put("payTaxType", payTaxType);
        map.put("reportType", reportType);
        map.put("industryIDs", industryIDs);

        List<TemplateUniqDto> templatedbList = templateMapper.getTemplateUniqDtosByTemplateAndTemplateGroup(map);
        Map<Long, Map<String, List<TemplateUniqDto>>> groupList = templatedbList.stream()
                .filter(sa -> sa.getIsActiveAssociation())
                .collect(groupingBy(TemplateUniqDto::getTemplateGroupId, Collectors.groupingBy(TemplateUniqDto::getTemplateGroupName)));
        List<NameDto> groupListResult = new ArrayList<>();
        groupList.forEach((key, value) -> {
            NameDto temp = new NameDto();
            temp.setID(key);
            value.forEach((key2, value2) -> {
                temp.setName(key2);
            });
            groupListResult.add(temp);
        });

        List<TemplateUniqDto> result = new ArrayList<>();

        for (NameDto group : groupListResult) {
            TemplateUniqDto parent = new TemplateUniqDto();
            parent.setId(group.getID());
            parent.setCode("");
            parent.setName(group.getName());
            result.add(parent);

            List<TemplateUniqDto> subList = templatedbList.stream()
                    .filter(sa -> sa.getTemplateGroupId() == group.getID() && sa.getIsActiveAssociation())
                    .collect(Collectors.toList());

            subList.forEach(sa -> {
                sa.setParentId(sa.getTemplateGroupId());
                sa.setParentName(sa.getTemplateGroupName());
            });
            result.addAll(subList);
        }

        List<TemplateUniqDto> noGroupTemplateList = templatedbList.stream().filter(sa -> !sa.getIsActiveAssociation()).collect(Collectors.toList());

        if (!noGroupTemplateList.isEmpty()) {
            TemplateUniqDto parent = new TemplateUniqDto();
            parent.setId(0L);
            parent.setCode("");
            parent.setName(Constant.Other);

            result.add(parent);

            noGroupTemplateList.forEach(sa -> {
                sa.setParentId(parent.getId());
                sa.setParentName(parent.getName());
            });

            result.addAll(noGroupTemplateList);
        }
        return result;
    }

    @Override
    public OperationResultDto<Object> updateTemplateName(UpateNameParam param) {
        OperationResultDto<Object> result = new OperationResultDto<>();

        TemplateAndGroupDbDto templateDb = templateMapper.getTemplateAndGroupByID(param.getID());

        if (templateDb == null) {
            result.setResult(false);
            result.setResultMsg("TemplateNotExist");
            return result;
        }
        Map<String, Object> map = new HashMap<>(3);
        map.put("templateGroupID", templateDb.getTemplateGroupId());
        map.put("templateID", param.getID());
        map.put("templateName", param.getName());

        long templateDbCount = templateMapper.getCountOfTemplateAndGroupByTemplateName(map);

        if (templateDbCount > 0) {
            result.setResult(false);
            result.setData(templateDb.getTemplateCode() + "_" + param.getName());
            result.setResultMsg("SameNameTemplateRepeat");
            return result;
        }

        Template updateTemplate = templateMapper.selectByPrimaryKey(templateDb.getTemplateId());
        updateTemplate.setName(param.getName());
        updateTemplate.setUpdateTime(new Date());
        templateMapper.updateByPrimaryKey(updateTemplate);

        result.setResult(true);
        return result;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public OperationResultDto<String> deleteTemplate(DeleteTemplateParam param) {
        OperationResultDto<String> result = new OperationResultDto<>();
        Template templateDb = templateMapper.selectByPrimaryKey(param.getID());

        String path = "";
        if (templateDb != null) {
            TemplateExample example = new TemplateExample();
            example.createCriteria().andCodeEqualTo(templateDb.getCode()).andIdEqualTo(templateDb.getId()).andIsActiveAssociationEqualTo(false);
            long count = templateMapper.countByExample(example);
            if (count > 0) {
                path = templateDb.getPath();
                //物理删除
                deleteIsAtiveAssociation(templateDb);
            } else {
                if (param.isDeletePermanent() && !templateDb.getIsSystemType()) {
                    path = templateDb.getPath();
                    //物理删除
                    deleteIsAtiveAssociation(templateDb);
                } else {
                    //逻辑删除
                    logicDeleteIsActiveAssociation(templateDb);
                }
            }
        }

        result.setResult(true);
        result.setData(path);
        return result;
    }

    @Override
    public OperationResultDto setRowColName(Long id, List<CellBriefDto> cellInfo) {
        OperationResultDto result = new OperationResultDto();
        CellTemplateExample example = new CellTemplateExample();
        example.createCriteria().andReportTemplateIdEqualTo(id);
        example.setOrderByClause("ColumnIndex,RowIndex");
        List<CellTemplate> cellTemplates = cellTemplateMapper.selectByExample(example);

        for (CellTemplate cellTemplate : cellTemplates) {
            boolean isUpdate = false;
            Optional<CellBriefDto> rowNameCell = cellInfo.stream().filter(a -> a.getRowIndex() == cellTemplate.getRowIndex()).findFirst();
            if (rowNameCell.isPresent()) {
                cellTemplate.setRowName(rowNameCell.get().getValue());
                isUpdate = true;
            }

            Optional<CellBriefDto> colNameCell = cellInfo.stream().filter(a -> a.getColumnIndex() == cellTemplate.getColumnIndex()).findFirst();
            if (colNameCell.isPresent()) {
                cellTemplate.setColumnName(colNameCell.get().getValue());
                isUpdate = true;
            }

            if (isUpdate) {
                cellTemplateMapper.updateByPrimaryKey(cellTemplate);
            }
        }

        result.setResult(true);
        return result;
    }

    private void logicDeleteIsActiveAssociation(Template templateDb) {
        templateDb.setIsActiveAssociation(false);
        templateMapper.updateByPrimaryKeySelective(templateDb);
    }

    private void deleteIsAtiveAssociation(Template templateDb) {
        cellTemplateConfigMapper.deleteCellTemplateConfigByCellTemplate(templateDb.getId());
        keyValueReferenceMapper.deleteKeyValueReferenceByCellTemplate(templateDb.getId());
        CellTemplateExample example = new CellTemplateExample();
        example.createCriteria().andReportTemplateIdEqualTo(templateDb.getId());
        cellTemplateMapper.deleteByExample(example);
    }
}