package com.jwipc.supplier.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.jwipc.constant.EnableStatus;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.constant.SequenceConst;
import com.jwipc.supplier.convert.SupplierTemplateQuestionnaireConvert;
import com.jwipc.supplier.convert.SupplierTemplateQuestionnaireItemConvert;
import com.jwipc.supplier.dto.SupplierTemplateQuestionnaireBaseDTO;
import com.jwipc.supplier.dto.SupplierTemplateQuestionnaireItemBaseDTO;
import com.jwipc.supplier.dto.SupplierTemplateQuestionnaireSaveDTO;
import com.jwipc.supplier.entity.SupplierTemplateQuestionnaire;
import com.jwipc.supplier.entity.SupplierTemplateQuestionnaireItem;
import com.jwipc.supplier.entity.SupplierTemplateQuestionnaireRelation;
import com.jwipc.supplier.logic.QuestionnaireLogic;
import com.jwipc.supplier.model.query.QuestionnaireQuery;
import com.jwipc.supplier.service.ISupplierTemplateQuestionnaireItemService;
import com.jwipc.supplier.service.ISupplierTemplateQuestionnaireRelationService;
import com.jwipc.supplier.service.ISupplierTemplateQuestionnaireService;
import com.jwipc.sys.client.SequenceClient;
import com.jwipc.sys.client.UserClient;
import com.jwipc.sys.client.dto.UserDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class QuestionnaireLogicImpl implements QuestionnaireLogic {
    private final ISupplierTemplateQuestionnaireService supplierTemplateQuestionnaireService;
    private final ISupplierTemplateQuestionnaireItemService supplierTemplateQuestionnaireItemService;
    private final SupplierTemplateQuestionnaireItemConvert templateQuestionnaireItemConvert;
    private final SupplierTemplateQuestionnaireConvert templateQuestionnaireConvert;
    private final UserClient userClient;
    private final SequenceClient sequenceClient;
    private final ISupplierTemplateQuestionnaireRelationService questionnaireRelations;

    @Override
    public SupplierTemplateQuestionnaireBaseDTO getDetail(Long id) {
        final SupplierTemplateQuestionnaire byId = supplierTemplateQuestionnaireService.getById(id);
        SupplierTemplateQuestionnaireBaseDTO moduleTemplateQuestionnaireBaseDTO;
        if (Objects.nonNull(byId)) {
            moduleTemplateQuestionnaireBaseDTO = templateQuestionnaireConvert.entity2Dto(byId);
        } else {
            moduleTemplateQuestionnaireBaseDTO = new SupplierTemplateQuestionnaireBaseDTO();
        }
        return moduleTemplateQuestionnaireBaseDTO;
    }

    @Override
    public PageView getList(QuestionnaireQuery query) {
        final LambdaQueryWrapper<SupplierTemplateQuestionnaire> queryWrapper =
                new LambdaQueryWrapper<SupplierTemplateQuestionnaire>().eq(
                                Objects.nonNull(query.getState()), SupplierTemplateQuestionnaire::getStatus,
                                query.getState())
                        .like(StrUtil.isNotEmpty(query.getCode()), SupplierTemplateQuestionnaire::getQuestionCode,
                                query.getCode())
                        .like(StrUtil.isNotEmpty(query.getName()), SupplierTemplateQuestionnaire::getQuestionTitle,
                                query.getName())
                        .orderBy(true, false, SupplierTemplateQuestionnaire::getCreateTime);
        final Page<SupplierTemplateQuestionnaire> page = PageUtil.toPage(query);
        final List<SupplierTemplateQuestionnaire> list = supplierTemplateQuestionnaireService.list(page, queryWrapper);
        final List<Long> userIds = list.stream().filter(a -> Objects.nonNull(a.getCreateId())).map(a -> a.getCreateId())
                .collect(Collectors.toSet()).stream().toList();
        Map<Long, String> userMap = Maps.newHashMap();
        if (CollUtil.isNotEmpty(userIds)) {
            final List<UserDTO> byUserIds = userClient.getByUserIds(userIds);
            userMap = byUserIds.stream().collect(Collectors.toMap(a -> a.getId(), a -> a.getUsername()));
        }
        List<SupplierTemplateQuestionnaireBaseDTO> baseDTOS = templateQuestionnaireConvert.entities2Dtos(list);
        for (SupplierTemplateQuestionnaireBaseDTO baseDTO : baseDTOS) {
            if (Objects.nonNull(baseDTO.getCreateId())) {
                baseDTO.setCreateName(userMap.get(baseDTO.getCreateId()));
            }
        }
        return PageUtil.getPV(baseDTOS, page.getTotal());
    }

    @Override
    public PageView getItemList(Long questionnaireId) {
        final List<SupplierTemplateQuestionnaireItem> list = supplierTemplateQuestionnaireItemService.list(
                new LambdaQueryWrapper<SupplierTemplateQuestionnaireItem>().eq(
                        SupplierTemplateQuestionnaireItem::getQuestionId, questionnaireId));
        List<SupplierTemplateQuestionnaireItemBaseDTO> questionnaireItemBaseDTOS =
                templateQuestionnaireItemConvert.entities2Dtos(
                        list);
        return PageUtil.getPV(questionnaireItemBaseDTOS, questionnaireItemBaseDTOS.size());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(SupplierTemplateQuestionnaireSaveDTO questionnaireSaveDTO) {
        final Long id = questionnaireSaveDTO.getId();
        SupplierTemplateQuestionnaire moduleTemplateQuestionnaire = templateQuestionnaireConvert.saveDto2Entity(
                questionnaireSaveDTO);
        final String sequenceNo;
        if (Objects.nonNull(id)) {
            //需要删除之前的答案选项
            supplierTemplateQuestionnaireItemService.remove(
                    new LambdaQueryWrapper<SupplierTemplateQuestionnaireItem>().eq(
                            SupplierTemplateQuestionnaireItem::getQuestionId, id));
            moduleTemplateQuestionnaire.setUpdateId(LoginUtil.getUserId());
            moduleTemplateQuestionnaire.setUpdateTime(LocalDateTime.now());
        } else {
            sequenceNo = sequenceClient.createSequenceNo(
                    SequenceConst.MODULE_TEMPLATE_QUESTIONNAIRE.getCode());
            moduleTemplateQuestionnaire.setQuestionCode(sequenceNo);
            moduleTemplateQuestionnaire.setCreateTime(LocalDateTime.now());
            moduleTemplateQuestionnaire.setCreateId(LoginUtil.getUserId());
        }
        supplierTemplateQuestionnaireService.saveOrUpdate(moduleTemplateQuestionnaire);
        final List<SupplierTemplateQuestionnaireItemBaseDTO> item = questionnaireSaveDTO.getItem();
        if (CollUtil.isNotEmpty(item)) {
            //需要校验编号是否重复
            Set<String> codeSet = new HashSet<>();
            List<SupplierTemplateQuestionnaireItem> moduleTemplateQuestionnaireItems =
                    templateQuestionnaireItemConvert.dtos2Entities(item);
            int i = 1;
            for (SupplierTemplateQuestionnaireItem moduleTemplateQuestionnaireItem : moduleTemplateQuestionnaireItems) {
                moduleTemplateQuestionnaireItem.setQuestionId(moduleTemplateQuestionnaire.getId());
                moduleTemplateQuestionnaireItem.setCreateTime(LocalDateTime.now());
                moduleTemplateQuestionnaireItem.setCreateId(LoginUtil.getUserId());
                String code = moduleTemplateQuestionnaireItem.getAnswerCode();
                if (codeSet.contains(code)) {
                    // 存在重复的code
                    throw new DaoException("选项编码重复!");
                } else {
                    codeSet.add(code);
                }
                moduleTemplateQuestionnaireItem.setAnswerSort(i);
                i++;
            }
            supplierTemplateQuestionnaireItemService.saveBatch(moduleTemplateQuestionnaireItems);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        supplierTemplateQuestionnaireService.removeById(id);
        supplierTemplateQuestionnaireItemService.remove(new LambdaQueryWrapper<SupplierTemplateQuestionnaireItem>().eq(
                SupplierTemplateQuestionnaireItem::getQuestionId, id));
    }

    @Override
    public void updateStatus(Long id) {
        final SupplierTemplateQuestionnaire byId = supplierTemplateQuestionnaireService.getById(id);
        if (Objects.nonNull(byId)) {
            int status = EnableStatus.ENABLE.getStatus() ==
                    byId.getStatus() ? EnableStatus.DISABLE.getStatus() : EnableStatus.ENABLE.getStatus();
            byId.setStatus(status);
            byId.setUpdateId(LoginUtil.getUserId());
            byId.setUpdateTime(LocalDateTime.now());
            supplierTemplateQuestionnaireService.updateById(byId);
        }
    }

    @Override
    public List<SupplierTemplateQuestionnaireBaseDTO> getListByTemplateId(Long templateId) {
        final List<SupplierTemplateQuestionnaireRelation> list = questionnaireRelations.list(
                new LambdaQueryWrapper<SupplierTemplateQuestionnaireRelation>().eq(
                        SupplierTemplateQuestionnaireRelation::getTemplateId, templateId));
        final List<Long> questionIds = list.stream().map(SupplierTemplateQuestionnaireRelation::getQuestionnaireId).collect(Collectors.toSet())
                .stream()
                .toList();
        if (CollUtil.isEmpty(questionIds)) {
            return Collections.emptyList();
        }
        final List<SupplierTemplateQuestionnaire> supplierTemplateQuestionnaires =
                supplierTemplateQuestionnaireService.listByIds(
                        questionIds);
        return templateQuestionnaireConvert.entities2Dtos(supplierTemplateQuestionnaires);
    }
}