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.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.jwipc.aggregation.ModelAggregationService;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.convert.QualificationConvert;
import com.jwipc.supplier.convert.QualificationTemplateConvert;
import com.jwipc.supplier.convert.QualificationTemplateItemConvert;
import com.jwipc.supplier.convert.SupplierQualificationConvert;
import com.jwipc.supplier.dto.*;
import com.jwipc.supplier.entity.Qualification;
import com.jwipc.supplier.entity.QualificationTemplate;
import com.jwipc.supplier.entity.QualificationTemplateItem;
import com.jwipc.supplier.entity.SupplierQualification;
import com.jwipc.supplier.logic.QualificationLogic;
import com.jwipc.supplier.model.query.QualificationQuery;
import com.jwipc.supplier.service.IQualificationService;
import com.jwipc.supplier.service.IQualificationTemplateItemService;
import com.jwipc.supplier.service.IQualificationTemplateService;
import com.jwipc.supplier.service.ISupplierQualificationService;
import com.jwipc.sys.client.DictClient;
import com.jwipc.sys.client.FileClient;
import com.jwipc.sys.client.UserClient;
import com.jwipc.sys.client.dto.DictDTO;
import com.jwipc.sys.client.dto.FileResposeCDTO;
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.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.jwipc.constant.DictCode.QUALIFICATIONS_SCENE;


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class QualificationLogicImpl implements QualificationLogic {
    private final IQualificationService qualificationService;
    private final QualificationConvert qualificationConvert;
    private final UserClient userClient;
    private final FileClient fileClient;
    private final DictClient dictClient;
    private final IQualificationTemplateService qualificationTemplateService;
    private final QualificationTemplateConvert qualificationTemplateConvert;
    private final IQualificationTemplateItemService qualificationTemplateItemService;
    private final QualificationTemplateItemConvert qualificationTemplateItemConvert;
    private final ISupplierQualificationService supplierQualificationService;
    private final SupplierQualificationConvert supplierQualificationConvert;
    private final ModelAggregationService modelAggregationService;

    @Override
    public PageView getList(QualificationQuery query) {
        final LambdaQueryWrapper<Qualification> queryWrapper = new LambdaQueryWrapper<Qualification>().eq(
                        StrUtil.isNotEmpty(query.getScene()), Qualification::getScene, query.getScene())
                .eq(Objects.nonNull(query.getState()), Qualification::getState, query.getState())
                .like(StrUtil.isNotEmpty(query.getCode()), Qualification::getCode, query.getCode())
                .like(StrUtil.isNotEmpty(query.getName()), Qualification::getName, query.getName());
        Set<String> codes = Sets.newHashSet();
        if (StrUtil.isNotEmpty(query.getTemplate())) {
            final QualificationTemplate templateServiceOne = qualificationTemplateService.getOne(
                    new LambdaQueryWrapper<>(QualificationTemplate.class).eq(QualificationTemplate::getCode,
                            query.getTemplate()));
            if (Objects.nonNull(templateServiceOne)) {
                final List<QualificationTemplateItem> list = qualificationTemplateItemService.list(
                        new LambdaQueryWrapper<>(QualificationTemplateItem.class)
                                .eq(QualificationTemplateItem::getTemplateId, templateServiceOne.getId()));
                codes.addAll(list.stream().map(QualificationTemplateItem::getCode)
                        .collect(Collectors.toSet()));
            }
        }
        if (CollUtil.isNotEmpty(codes)) {
            queryWrapper.in(Qualification::getCode, codes);
        }
        if (StrUtil.isNotEmpty(query.getCodes())) {
            queryWrapper.in(Qualification::getCode, StrUtil.split(query.getCodes(), StrUtil.COMMA));
        }
        final Page<Qualification> page = PageUtil.toPage(query);
        final List<Qualification> list = qualificationService.list(page, queryWrapper);
        List<QualificationBaseDTO> qualificationBaseDTOS = qualificationConvert.entities2DTOs(list);
        final List<Long> fileIds = qualificationBaseDTOS.stream().filter(a -> Objects.nonNull(a.getFileId()))
                .map(a -> Long.valueOf(a.getFileId())).collect(Collectors.toSet()).stream().toList();
        Map<Long, String> fileMap = Maps.newHashMap();
        if (CollUtil.isNotEmpty(fileIds)) {
            final List<FileResposeCDTO> fileInfos = fileClient.getFileInfos(fileIds);
            fileMap = fileInfos.stream()
                    .collect(Collectors.toMap(a -> a.getId(), a -> a.getFileName()));
        }
        final List<Long> userIds = qualificationBaseDTOS.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()));
        }
        for (QualificationBaseDTO qualificationBaseDTO : qualificationBaseDTOS) {
            if (Objects.nonNull(qualificationBaseDTO.getFileId())) {
                final String fileName = fileMap.get(qualificationBaseDTO.getFileId());
                qualificationBaseDTO.setFileName(fileName);
            }
            if (Objects.nonNull(qualificationBaseDTO.getCreateId())) {
                qualificationBaseDTO.setCreateName(userMap.get(qualificationBaseDTO.getCreateId()));
            }
        }
        return PageUtil.getPV(qualificationBaseDTOS, page.getTotal());
    }

    @Override
    public QualificationBaseDTO getDetail(Long id) {
        QualificationBaseDTO qualificationBaseDTO;
        final Qualification qualification = qualificationService.getById(id);
        if (Objects.nonNull(qualification)) {
            qualificationBaseDTO = qualificationConvert.entity2DTO(qualification);
            //获取文件名
            final Long fileId = qualificationBaseDTO.getFileId();
            if (Objects.nonNull(fileId)) {
                final FileResposeCDTO fileInfo = fileClient.getFileInfo(fileId);
                if (Objects.nonNull(fileInfo)) {
                    qualificationBaseDTO.setFileName(fileInfo.getFileName());
                }
            }
        } else {
            qualificationBaseDTO = new QualificationBaseDTO();
        }
        return qualificationBaseDTO;
    }

    @Override
    public void saveOrUpdate(QualificationBaseDTO qualificationBaseDTO) {
        Qualification qualification = qualificationConvert.dto2Entity(qualificationBaseDTO);
        final LambdaQueryWrapper<Qualification> queryWrapper = new LambdaQueryWrapper<Qualification>()
                .eq(Qualification::getCode, qualification.getCode())
                .ne(Objects.nonNull(qualification.getId()), Qualification::getId, qualification.getId());
        final long count = qualificationService.count(queryWrapper);
        if (count > 0) {
            throw new DaoException("编码已存在");
        }
        if (Objects.nonNull(qualification.getId())) {
            qualification.setCreateId(LoginUtil.getUserId());
            qualification.setCreateTime(LocalDateTime.now());
        }
        qualificationService.saveOrUpdate(qualification);
    }

    @Override
    public void updateState(Long id, Integer state) {
        qualificationService.update(new LambdaUpdateWrapper<Qualification>().eq(Qualification::getId, id)
                .set(Qualification::getState, state));
    }

    @Override
    public PageView getTemplateList(QualificationQuery query) {
        final LambdaQueryWrapper<QualificationTemplate> queryWrapper =
                new LambdaQueryWrapper<QualificationTemplate>().eq(
                                StrUtil.isNotEmpty(query.getScene()), QualificationTemplate::getScene, query.getScene())
                        .like(StrUtil.isNotEmpty(query.getCode()), QualificationTemplate::getCode, query.getCode())
                        .like(StrUtil.isNotEmpty(query.getName()), QualificationTemplate::getName, query.getName());
        final Page<QualificationTemplate> page = PageUtil.toPage(query);
        final List<QualificationTemplate> list = qualificationTemplateService.list(page, queryWrapper);
        List<QualificationTemplateBaseDTO> qualificationTemplateBaseDTOS =
                qualificationTemplateConvert.entities2BaseDtos(
                        list);
        final List<Long> userIds = qualificationTemplateBaseDTOS.stream().filter(a -> Objects.nonNull(a.getCreateId()))
                .map(a -> a.getCreateId()).collect(Collectors.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()));
        }
        final List<DictDTO> dicByType = dictClient.getDicByType(QUALIFICATIONS_SCENE.getCode());
        final Map<String, String> dictMap = dicByType.stream()
                .collect(Collectors.toMap(a -> a.getCode(), a -> a.getName()));
        for (QualificationTemplateBaseDTO qualificationBaseDTO : qualificationTemplateBaseDTOS) {
            if (Objects.nonNull(qualificationBaseDTO.getCreateId())) {
                qualificationBaseDTO.setCreateName(userMap.get(qualificationBaseDTO.getCreateId()));
            }
            if (Objects.nonNull(qualificationBaseDTO.getScene())) {
                qualificationBaseDTO.setSceneName(dictMap.get(qualificationBaseDTO.getScene()));
            }
        }
        return PageUtil.getPV(qualificationTemplateBaseDTOS, page.getTotal());
    }

    @Override
    public void templateUpdateState(Long id, Integer state) {
        qualificationTemplateService.update(
                new LambdaUpdateWrapper<QualificationTemplate>().eq(QualificationTemplate::getId, id)
                        .set(QualificationTemplate::getState, state));
    }

    @Override
    public QualificationTemplateBaseDTO getTemplateDetail(Long id) {
        QualificationTemplateBaseDTO qualificationTemplateBaseDTO;
        final QualificationTemplate byId = qualificationTemplateService.getById(id);
        if (Objects.nonNull(byId)) {
            qualificationTemplateBaseDTO = qualificationTemplateConvert.entity2BaseDto(byId);
        } else {
            qualificationTemplateBaseDTO = new QualificationTemplateBaseDTO();
        }
        return qualificationTemplateBaseDTO;
    }

    @Override
    public PageView getTemplateItemListByTemplateId(Long templateId) {
        final LambdaQueryWrapper<QualificationTemplateItem> eq = new LambdaQueryWrapper<QualificationTemplateItem>().eq(
                QualificationTemplateItem::getTemplateId, templateId);
        final List<QualificationTemplateItemBaseDTO> templateItemList = getTemplateItemList(eq);
        return PageUtil.getPV(templateItemList, templateItemList.size());

    }

    private List<QualificationTemplateItemBaseDTO> getTemplateItemList(
            LambdaQueryWrapper<QualificationTemplateItem> eq)
    {
        final List<QualificationTemplateItem> list = qualificationTemplateItemService.list(eq);
        //需要组装数据
        final List<Long> fileIds = list.stream().filter(a -> Objects.nonNull(a.getFileId()))
                .map(a -> a.getFileId()).collect(Collectors.toSet()).stream().toList();
        Map<Long, String> fileMap = Maps.newHashMap();
        if (CollUtil.isNotEmpty(fileIds)) {
            final List<FileResposeCDTO> fileInfos = fileClient.getFileInfos(fileIds);
            fileMap = fileInfos.stream()
                    .collect(Collectors.toMap(a -> a.getId(), a -> a.getFileName()));
        }
        List<QualificationTemplateItemBaseDTO> qualificationTemplateItemBaseDTOS =
                qualificationTemplateItemConvert.entities2Dtos(list);
        for (QualificationTemplateItemBaseDTO qualificationTemplateItemBaseDTO : qualificationTemplateItemBaseDTOS) {
            if (Objects.nonNull(qualificationTemplateItemBaseDTO.getFileId())) {
                final String fileName = fileMap.get(qualificationTemplateItemBaseDTO.getFileId());
                qualificationTemplateItemBaseDTO.setFileName(fileName);
            }
        }
        return qualificationTemplateItemBaseDTOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void templateSaveOrUpdate(QualificationTemplateSaveDTO qualificationTemplateSaveDTO) {
        final Long id = qualificationTemplateSaveDTO.getId();
        final LambdaQueryWrapper<QualificationTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(QualificationTemplate::getCode, qualificationTemplateSaveDTO.getCode());
        if (Objects.nonNull(id) && qualificationTemplateSaveDTO.isCopyFlag()) {
            //复制
            qualificationTemplateSaveDTO.setId(null);
            qualificationTemplateSaveDTO.setCreateId(LoginUtil.getUserId());
            qualificationTemplateSaveDTO.setCreateTime(LocalDateTime.now());
            //需要判断模板的id是否存在
        } else if (Objects.nonNull(id)) {
            //编辑
            //需要删除之前的明细数据
            queryWrapper.ne(QualificationTemplate::getId, id);
            qualificationTemplateItemService.remove(
                    new LambdaQueryWrapper<QualificationTemplateItem>().eq(QualificationTemplateItem::getTemplateId,
                            id));
        } else {
            //新增
            qualificationTemplateSaveDTO.setCreateId(LoginUtil.getUserId());
            qualificationTemplateSaveDTO.setCreateTime(LocalDateTime.now());
        }
        final long count = qualificationTemplateService.count(queryWrapper);
        if (count > 0) {
            throw new DaoException("编号重复!");
        }
        QualificationTemplate qualificationTemplate = qualificationTemplateConvert.saveDto2Entity(
                qualificationTemplateSaveDTO);
        qualificationTemplateService.saveOrUpdate(qualificationTemplate);
        final List<QualificationTemplateItemBaseDTO> item = qualificationTemplateSaveDTO.getItem();
        List<QualificationTemplateItem> qualificationTemplateItems = qualificationTemplateItemConvert.dtos2Entities(
                item);
        for (QualificationTemplateItem qualificationTemplateItem : qualificationTemplateItems) {
            qualificationTemplateItem.setTemplateId(qualificationTemplate.getId());
            qualificationTemplateItem.setId(null);
        }
        if (CollUtil.isNotEmpty(qualificationTemplateItems)) {
            qualificationTemplateItemService.saveBatch(qualificationTemplateItems);
        }

    }

    @Override
    public List<QualificationTemplateItemBaseDTO> getTemplateItemListByTemplateCode(String templateCode,
                                                                                    String version)
    {
        final QualificationTemplate qualificationTemplate = qualificationTemplateService.getOne(
                new LambdaQueryWrapper<QualificationTemplate>().eq(QualificationTemplate::getCode, templateCode)
                        .eq(QualificationTemplate::getVersion, version), false);
        final LambdaQueryWrapper<QualificationTemplateItem> eq = new LambdaQueryWrapper<QualificationTemplateItem>().eq(
                QualificationTemplateItem::getTemplateId, qualificationTemplate.getId());
        return getTemplateItemList(eq);
    }

    @Override
    public List<QualificationTemplateBaseDTO> getTemplateListAll(QualificationQuery query) {
        final LambdaQueryWrapper<QualificationTemplate> queryWrapper =
                new LambdaQueryWrapper<QualificationTemplate>().eq(
                        StrUtil.isNotEmpty(query.getScene()), QualificationTemplate::getScene, query.getScene());
        final List<QualificationTemplate> list = qualificationTemplateService.list(queryWrapper);
        List<QualificationTemplateBaseDTO> qualificationTemplateBaseDTOS =
                qualificationTemplateConvert.entities2BaseDtos(
                        list);
        return qualificationTemplateBaseDTOS;
    }

    @Override
    public List<SupplierQualificationListDTO> getSupplierQualifications(Long supplierId, String typeStr, String codes) {
        List<String> codesArr = Lists.newArrayList();
        if (StrUtil.isNotEmpty(codes)) {
            codesArr = StrUtil.split(codes, StrUtil.COMMA);
        }
        final List<SupplierQualification> list = supplierQualificationService.list(
                new LambdaQueryWrapper<SupplierQualification>()
                        .eq(SupplierQualification::getSupplierId, supplierId)
                        .in(CollUtil.isNotEmpty(codesArr), SupplierQualification::getQualificationCode, codesArr)
                        .in(StrUtil.isNotEmpty(typeStr), SupplierQualification::getScene,
                                StrUtil.split(typeStr, StrUtil.COMMA))
                        .orderByAsc(SupplierQualification::getScene));
        List<SupplierQualificationListDTO> supplierQualificationListDTOS =
                supplierQualificationConvert.entities2ListDtos(
                        list);
        modelAggregationService.processRelationAggregation(supplierQualificationListDTOS);
        return supplierQualificationListDTOS;
    }
}