
package com.tmerclub.cloud.biz.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.biz.config.AwsS3Config;
import com.tmerclub.cloud.biz.dto.AttachFileDTO;
import com.tmerclub.cloud.biz.mapper.AttachFileMapper;
import com.tmerclub.cloud.biz.model.AttachFile;
import com.tmerclub.cloud.biz.service.AttachFileGroupService;
import com.tmerclub.cloud.biz.service.AttachFileService;
import com.tmerclub.cloud.biz.vo.AttachFileGroupVO;
import com.tmerclub.cloud.biz.vo.AttachFileVO;
import com.tmerclub.cloud.biz.vo.PreSignUrlVO;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 上传文件记录表
 *
 * @author YXF
 */
@SuppressWarnings("CommentedOutCode")
@Service
public class AttachFileServiceImpl implements AttachFileService {

    /**
     * 上传的文件夹(根据时间确定)
     */
    public static final String NORM_DAY_PATTERN = "yyyy/MM/dd";

    @Autowired
    private AttachFileMapper attachFileMapper;

    @Autowired
    private AttachFileGroupService attachFileGroupService;

    @Autowired
    private AwsS3Config awsS3Config;

    @Override
    public PageVO<AttachFileVO> page(PageDTO pageDTO, AttachFileDTO attachFileDTO) {
        if (Objects.equals(AuthUserContext.get().getTenantId(), Constant.DEFAULT_SHOP_ID) || Objects.equals(AuthUserContext.get().getTenantId(), Constant.DEFAULT_SUPPLIER_ID)) {
            // 如果店铺id还没有生成，使用uid查找文件信息
            attachFileDTO.setShopId(null);
            attachFileDTO.setUid(AuthUserContext.getAccountUid());
        } else {
            attachFileDTO.setUid(null);
            attachFileDTO.setShopId(AuthUserContext.get().getTenantId());
        }
        attachFileDTO.setSysType(AuthUserContext.get().getSysType());
        return PageUtil.doPage(pageDTO, () -> attachFileMapper.list(attachFileDTO));
    }

    @Override
    public AttachFileVO getById(Long fileId) {
        return BeanUtil.map(attachFileMapper.getById(fileId), AttachFileVO.class);
    }

    @Override
    public void save(List<AttachFile> attachFiles) {
        attachFileMapper.save(attachFiles, AuthUserContext.get().getTenantId(), AuthUserContext.getAccountUid(), AuthUserContext.get().getSysType());
    }

    @Override
    public void update(AttachFile attachFile) {
        attachFileMapper.update(attachFile);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long fileId) {
        AttachFile attachFile = attachFileMapper.getById(fileId);
        // 获取文件的实际路径--数据库中保存的文件路径为： / + 实际的文件路径
        String filePath = attachFile.getFilePath();
        if (StrUtil.isNotBlank(filePath)) {
            filePath = filePath.substring(1);
        }
        awsS3Config.deleteFile(filePath);
        attachFileMapper.deleteById(fileId);
    }

    @Override
    public void updateFileName(AttachFile attachFile) {
        if (Objects.isNull(attachFile.getFileName()) && Objects.isNull(attachFile.getAttachFileGroupId())) {
            return;
        }
        attachFileMapper.update(attachFile);
    }

    @Override
    public void deleteByIdsAndShopId(List<Long> ids, Long shopId) {
        List<AttachFileVO> attachFileList = attachFileMapper.getByIds(ids);
        // 获取文件的实际路径--数据库中保存的文件路径为： / + 实际的文件路径
        List<String> filePaths = attachFileList.stream().map(item -> {
            if (!Objects.equals(item.getShopId(), shopId)) {
                throw new LuckException("存在非本店铺下的文件，删除失败");
            }
            return item.getFilePath().substring(1);
        }).collect(Collectors.toList());
        awsS3Config.deleteBatchFile(filePaths);
        attachFileMapper.batchDeleteByIds(ids);
    }

    @Override
    public void batchMoveByShopIdAndIdsAndGroupId(Long shopId, List<Long> ids, Long groupId, Integer sysType) {
        if (Objects.nonNull(groupId)) {
            AttachFileGroupVO attachFileGroupVO = attachFileGroupService.getByAttachFileGroupId(groupId);
            if (Objects.isNull(attachFileGroupVO)) {
                throw new LuckException("当前分组已不存在，请刷新后重试");
            }
            if (!Objects.equals(attachFileGroupVO.getShopId(), shopId)) {
                throw new LuckException("分组信息错误");
            }
        }
        attachFileMapper.batchMoveByShopIdAndIdsAndGroupId(shopId, ids, groupId, sysType);
    }

    @Override
    public void updateShopIdByUid(Long shopId, Long uid) {
        attachFileMapper.updateShopIdByUid(shopId, uid);
    }

    @Override
    public void saveFile(AttachFile attachFile) {
        attachFileMapper.saveFile(attachFile, AuthUserContext.getAccountUid());
    }

    @Override
    public String getfileTypeByfilePath(String filePath) {
        return attachFileMapper.getfileTypeByfilePath(filePath);
    }

    @Override
    public List<PreSignUrlVO> getBatchPreSignUrl(List<String> fileNames) {
        if (CollectionUtils.isEmpty(fileNames)) {
            return new ArrayList<>();
        }
        List<PreSignUrlVO> preSignUrlVOList = new ArrayList<>(fileNames.size());
        List<String> filePaths = new ArrayList<>(fileNames.size());
        PreSignUrlVO preSignUrlVO;
        for (String fileName : fileNames) {
            this.checkFileName(fileName);
            preSignUrlVO = new PreSignUrlVO();
            preSignUrlVO.setDir(DateUtil.format(new Date(), NORM_DAY_PATTERN) + "/");
            preSignUrlVO.setFileName(IdUtil.simpleUUID() + "." + FileUtil.extName(fileName));
            preSignUrlVOList.add(preSignUrlVO);
            filePaths.add(preSignUrlVO.getDir() + preSignUrlVO.getFileName());
        }
        // 批量获取预签名
        List<String> preSignUrls = awsS3Config.getBatchPreSignUrl(filePaths);
        for (int i=0; i<fileNames.size(); i++) {
            preSignUrlVOList.get(i).setPreSignUrl(preSignUrls.get(i));
        }
        return preSignUrlVOList;
    }

    /**
     * 检查文件名
     * @param fileName 文件名
     */
    private void checkFileName(String fileName) {
        // 只允许特定文件后缀名上传
        String extName = FileUtil.extName(fileName).toLowerCase();
        if (ObjectUtils.isEmpty(extName) ||
                !Constant.FILE_SUFFIX_NAMES.contains(extName)) {
            throw new LuckException(String.format("[%s]类型的文件禁止上传", extName));
        }
    }
}
