package cn.iocoder.yudao.module.infra.service.file;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.file.core.client.FileClient;
import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.BpmFileUploadReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.BpmFileDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.BpmFileMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;

/**
 * 文件 Service 实现类
 *

 */
@Service
public class FileServiceImpl implements FileService {

    @Resource
    private FileConfigService fileConfigService;

    @Resource
    private FileMapper fileMapper;
    @Resource
    private BpmFileMapper bpmFileMapper;

    @Override
    public PageResult<FileDO> getFilePage(FilePageReqVO pageReqVO) {
        return fileMapper.selectPage(pageReqVO);
    }


    @Override
    @SneakyThrows
    public BpmFileDO createReturnFile(MultipartFile file) {

        Long userId = SecurityFrameworkUtils.getLoginUserId();
        long timestamp = System.currentTimeMillis();

        String[] fileInfo = new String[4] ;
        String name = file.getOriginalFilename() ;
        String path = null ;
        byte[] content =  IoUtil.readBytes(file.getInputStream()) ;

        // 计算默认的 path 名
        String type = FileTypeUtils.getMineType(content, name);

        if (StrUtil.isEmpty(path)) {
            //path = FileUtils.generatePath(content, name);
            path = userId+"_"+timestamp+"";
            String beginPath = name.replace(".","_") ;
            path = beginPath+"_"+path+"."+ FileNameUtil.extName(name);;
        }
        // 如果 name 为空，则使用 path 填充
        if (StrUtil.isEmpty(name)) {
            name = path;
        }

        // 上传到文件存储器
        FileClient client = fileConfigService.getMasterFileClient();
        Assert.notNull(client, "客户端(master) 不能为空");
        String url = client.upload(content, path, type);

        // 保存到数据库
        BpmFileDO fileDo = new BpmFileDO();
        fileDo.setConfigId(client.getId());
        fileDo.setName(name);
        fileDo.setPath(path);
        fileDo.setUrl(url);
        fileDo.setType(type);
        fileDo.setSize(content.length);
        fileDo.setUploadUserId(userId) ;
        bpmFileMapper.insert(fileDo);

        fileInfo[0] = name ;
        fileInfo[1] = fileDo.getUrl() ;
        fileInfo[2] = fileDo.getType() ;
        // 返回上传文件的访问路径
        //return "{\"name\": \""+ fileInfo[0]+"\",   \"path\": \""+ fileInfo[1]+"\",   \"type\": \""+ fileInfo[2]+"\" }";
        return fileDo ;
    }

    @Override
    @SneakyThrows
    public String createFile(String name, String path, byte[] content) {
        // 计算默认的 path 名
        String type = FileTypeUtils.getMineType(content, name);
        if (StrUtil.isEmpty(path)) {
            path = FileUtils.generatePath(content, name);
        }
        // 如果 name 为空，则使用 path 填充
        if (StrUtil.isEmpty(name)) {
            name = path;
        }

        // 上传到文件存储器
        FileClient client = fileConfigService.getMasterFileClient();
        Assert.notNull(client, "客户端(master) 不能为空");
        String url = client.upload(content, path, type);

        // 保存到数据库
        FileDO file = new FileDO();
        file.setConfigId(client.getId());
        file.setName(name);
        file.setPath(path);
        file.setUrl(url);
        file.setType(type);
        file.setSize(content.length);
        fileMapper.insert(file);
        return url;
    }

    @Override
    public void deleteFile(Long id) throws Exception {
        // 校验存在
        FileDO file = validateFileExists(id);

        // 从文件存储器中删除
        FileClient client = fileConfigService.getFileClient(file.getConfigId());
        Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId());
        client.delete(file.getPath());

        // 删除记录
        fileMapper.deleteById(id);
    }

    private FileDO validateFileExists(Long id) {
        FileDO fileDO = fileMapper.selectById(id);
        if (fileDO == null) {
            throw exception(FILE_NOT_EXISTS);
        }
        return fileDO;
    }

    @Override
    public byte[] getFileContent(Long configId, String path) throws Exception {
        FileClient client = fileConfigService.getFileClient(configId);
        Assert.notNull(client, "客户端({}) 不能为空", configId);
        return client.getContent(path);
    }

    @Override
    public void deleteFile(String url) throws Exception {
        String path = url.substring( url.lastIndexOf("/")+1 ) ;
        PageResult<FileDO> fileDOPageResult =fileMapper.selectPage(new FilePageReqVO().setPath(path));
        FileDO file = null ;
        if(fileDOPageResult != null && fileDOPageResult.getTotal() >0 ) {
            file = fileDOPageResult.getList().get(0) ;

        }
        if (file == null) {
            throw exception(FILE_NOT_EXISTS);
        }

        // 从文件存储器中删除
        FileClient client = fileConfigService.getFileClient(file.getConfigId());
        Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId());
        client.delete(file.getPath());

        // 删除记录
        fileMapper.deleteById(file.getId());
    }

    @Override
    public void deleteBpmFile(String url) throws Exception {
        String path = url.substring( url.lastIndexOf("/")+1 ) ;
        PageResult<BpmFileDO> fileDOPageResult =bpmFileMapper.selectPage(new FilePageReqVO().setPath(path));
        BpmFileDO file = null ;
        if(fileDOPageResult != null && fileDOPageResult.getTotal() >0 ) {
            file = fileDOPageResult.getList().get(0) ;
        }
        if (file == null) {
            throw exception(FILE_NOT_EXISTS);
        }

        // 从文件存储器中删除
        FileClient client = fileConfigService.getFileClient(file.getConfigId());
        Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId());
        client.delete(file.getPath());

        // 删除记录
        bpmFileMapper.deleteById(file.getId());
    }

    @Override
    public void uploadBpmFileProcessInstanceId(BpmFileUploadReqVO reqVO) {
        String processInstanceId = reqVO.getProcessInstanceId() ;
        List<String> urls = reqVO.getUrls() ;
        LambdaUpdateWrapper<BpmFileDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.in(BpmFileDO::getUrl, urls) ;
        lambdaUpdateWrapper.set(BpmFileDO::getProcessInstanceId, processInstanceId); // 假设 bid 是要更新的 bid 值
        // 调用 MyBatis Plus 的 update 方法执行批量更新
        bpmFileMapper.update(null, lambdaUpdateWrapper);
    }
}
