package com.ruoyi.project.business.service.system.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.exception.ServiceErrorException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.project.business.domain.system.SysAttachment;
import com.ruoyi.project.business.domain.system.SysAttachmentHistory;
import com.ruoyi.project.business.dto.SysAttachmentDto;
import com.ruoyi.project.business.enums.CategoryEnum;
import com.ruoyi.project.business.enums.FunctionEnum;
import com.ruoyi.project.business.enums.ModuleEnum;
import com.ruoyi.project.business.mapper.system.SysAttachmentMapper;
import com.ruoyi.project.business.service.system.ISysAttachmentHistoryService;
import com.ruoyi.project.business.service.system.ISysAttachmentService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.apache.commons.collections4.CollectionUtils.isEmpty;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;

/**
 * <p>
 * 附件表 服务实现类
 * </p>
 *
 * @author CAC
 * @since 2023-09-28
 */
@Service
public class SysAttachmentServiceImpl extends ServiceImpl<SysAttachmentMapper, SysAttachment> implements ISysAttachmentService {

    @Value("${app.uploadFolder}")
    private String uploadFolder;
    @Resource
    private ISysAttachmentHistoryService sysAttachmentHistoryService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAttachments(Integer id, ModuleEnum module, FunctionEnum func, CategoryEnum category, List<SysAttachment> attachments) {
        if (isNotEmpty(attachments)) {
            attachments.forEach(sysAttachment -> sysAttachment.setBusinessId(id));
        }
        updateAttachmentsBatch(Lists.newArrayList(id), module, func, category, attachments);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAttachmentsBatch(List<Integer> ids, ModuleEnum module, FunctionEnum func, CategoryEnum category, List<SysAttachment> attachments) {
        if (isNotEmpty(ids)) {
            // 1. 删除历史附件
            remove(Wrappers.<SysAttachment>lambdaQuery()
                    .in(SysAttachment::getBusinessId, ids)
                    .eq(SysAttachment::getModule, module.getValue())
                    .eq(SysAttachment::getFunc, func.getValue())
                    .eq(SysAttachment::getCategory, category.getValue()));
        }
        ;

        // 2. 插入新数据
        if (isEmpty(attachments)) {
            return;
        }
        attachments.forEach(sysAttachment -> {
            sysAttachment.setAttaId(null);
            sysAttachment.setModule(module.getValue());
            sysAttachment.setFunc(func.getValue());
            sysAttachment.setCategory(category.getValue());
            sysAttachment.setStatus("0");
            sysAttachment.setCreateBy(SecurityUtils.getUserId().toString());
            sysAttachment.setCreateTime(new Date());
        });
        saveBatch(attachments);
    }

    @Override
    public List<SysAttachment> getAttachments(Integer id, ModuleEnum module, FunctionEnum func, CategoryEnum category) {
        Map<Integer, List<SysAttachment>> map = getAttachmentsMap(Lists.newArrayList(id), module, func, category);
        List<SysAttachment> result = map.get(id);
        return isEmpty(result) ? Lists.newArrayList() : result;
    }

    @Override
    public Map<Integer, List<SysAttachment>> getAttachmentsMap(List<Integer> ids, ModuleEnum module, FunctionEnum func, CategoryEnum category) {
        if (isEmpty(ids)) {
            return Maps.newHashMap();
        }
        return list(Wrappers.<SysAttachment>lambdaQuery()
                .in(SysAttachment::getBusinessId, ids)
                .eq(SysAttachment::getModule, module.getValue())
                .eq(SysAttachment::getFunc, func.getValue())
                .eq(SysAttachment::getCategory, category.getValue()))
                .stream().collect(Collectors.groupingBy(SysAttachment::getBusinessId));
    }

    @Override
    public List<SysAttachmentHistory> getHistoryAttachments(Integer id, ModuleEnum module, FunctionEnum func, CategoryEnum category) {
        Map<Integer, List<SysAttachmentHistory>> map = getHistoryAttachmentsMap(Lists.newArrayList(id), module, func, category);
        List<SysAttachmentHistory> result = map.get(id);
        return isEmpty(result) ? Lists.newArrayList() : result;
    }

    public Map<Integer, List<SysAttachmentHistory>> getHistoryAttachmentsMap(List<Integer> ids, ModuleEnum module, FunctionEnum func, CategoryEnum category) {
        if (isEmpty(ids)) {
            return Maps.newHashMap();
        }
        return sysAttachmentHistoryService.list(Wrappers.<SysAttachmentHistory>lambdaQuery()
                        .in(SysAttachmentHistory::getBusinessHistoryId, ids)
                        .eq(SysAttachmentHistory::getModule, module.getValue())
                        .eq(SysAttachmentHistory::getFunc, func.getValue())
                        .eq(SysAttachmentHistory::getCategory, category.getValue()))
                .stream().collect(Collectors.groupingBy(SysAttachmentHistory::getBusinessHistoryId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveHistory(Map<Integer, Integer> idMap, ModuleEnum module, FunctionEnum func, CategoryEnum category) {
        if (Objects.isNull(idMap) || isEmpty(idMap.keySet())) {
            return;
        }

        List<SysAttachment> attachmentList = list(Wrappers.<SysAttachment>lambdaQuery()
                .in(SysAttachment::getBusinessId, idMap.keySet())
                .eq(SysAttachment::getModule, module.getValue())
                .eq(SysAttachment::getFunc, func.getValue())
                .eq(SysAttachment::getCategory, category.getValue()));
        if (isEmpty(attachmentList)) {
            return;
        }

        List<SysAttachmentHistory> historyList = attachmentList.stream().map(sysAttachment -> {
            SysAttachmentHistory history = new SysAttachmentHistory();
            BeanUtils.copyBeanProp(history, sysAttachment);
            history.setAttaId(null);
            history.setBusinessHistoryId(idMap.get(sysAttachment.getBusinessId()));
            history.setCreateBy(SecurityUtils.getUserId().toString());
            history.setCreateTime(new Date());
            return history;
        }).collect(Collectors.toList());
        sysAttachmentHistoryService.saveBatch(historyList);
    }

    @Override
    public void saveAttachment(Integer businessId, String path, ModuleEnum moduleEnum, FunctionEnum functionEnum, CategoryEnum categoryEnum) {
        SysAttachment attachment = new SysAttachment();
        attachment.setBusinessId(businessId);
        attachment.setAttaName(path.substring(path.lastIndexOf("/") + 1));
        attachment.setUploadName(path.split("__.__")[1]);
        attachment.setStaticUrl(path.replace(uploadFolder, ""));
        attachment.setUploadUrl(path);
        attachment.setModule(moduleEnum.getValue());
        attachment.setFunc(functionEnum.getValue());
        attachment.setCategory(categoryEnum.getValue());
        attachment.setStatus("0");
        attachment.setCreateBy(SecurityUtils.getUserId().toString());
        attachment.setCreateTime(new Date());
        // 文件路径更新
        remove(Wrappers.<SysAttachment>lambdaQuery()
                .in(SysAttachment::getBusinessId, attachment.getBusinessId())
                .eq(SysAttachment::getModule, attachment.getModule())
                .eq(SysAttachment::getFunc, attachment.getFunc())
                .eq(SysAttachment::getCategory, attachment.getCategory()));
        save(attachment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int attachmentsBatchUpdate(SysAttachmentDto dto) {
        List<Integer> ids = dto.getIds();
        List<Integer> distinctIds = ids.stream().distinct().collect(Collectors.toList());
        if (isEmpty(distinctIds)) {
            throw new ServiceErrorException("请选择需要上传附件的数据");
        }
        List<SysAttachment> fileMainList = dto.getFileMainList();
        if (isEmpty(fileMainList)) {
            throw new ServiceErrorException("上传的附件不能为空");
        }
        List<SysAttachment> uploadList = Lists.newArrayList();
        distinctIds.forEach(id -> {
            uploadList.addAll(fileMainList.stream().map(sysAttachment -> {
                SysAttachment attachment = new SysAttachment();
                BeanUtils.copyBeanProp(attachment, sysAttachment);
                attachment.setBusinessId(id);
                return attachment;
            }).collect(Collectors.toList()));
        });
        ModuleEnum module = ModuleEnum.from(dto.getModule());
        FunctionEnum storage = FunctionEnum.from(dto.getStorage());
        CategoryEnum categoryEnum = CategoryEnum.from(dto.getCategory());
        this.updateAttachmentsBatch(dto.isReplace() ? distinctIds : null, module, storage, categoryEnum, uploadList);
        return 0;
    }

}
