package cn.reghao.tnb.oss.store.service;

import cn.reghao.jutil.jdk.security.DigestUtil;
import cn.reghao.tnb.common.web.ServletUtil;
import cn.reghao.tnb.oss.store.config.props.OssProperties;
import cn.reghao.tnb.oss.store.db.repository.ObjectRepository;
import cn.reghao.tnb.oss.store.model.po.DataBlock;
import cn.reghao.tnb.oss.store.model.po.FileMeta;
import cn.reghao.tnb.oss.store.model.vo.ObjectProp;
import cn.reghao.tnb.oss.store.model.vo.ObjectResult;
import cn.reghao.tnb.oss.store.util.FileType;
import cn.reghao.tnb.oss.store.util.StringUtil;
import cn.reghao.tnb.oss.api.dto.ObjectMeta;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.List;
import java.util.UUID;

/**
 * @author reghao
 * @date 2023-05-10 13:28:18
 */
@Slf4j
@Service
public class PutObjectService {
    private final ObjectRepository objectRepository;
    private final ObjectNameService objectNameService;
    private final String nodeAddress;
    private final ConsoleServiceWrapper consoleServiceWrapper;

    public PutObjectService(ObjectRepository objectRepository, ObjectNameService objectNameService,
                            OssProperties ossProperties, ConsoleServiceWrapper consoleServiceWrapper) {
        this.objectRepository = objectRepository;
        this.objectNameService = objectNameService;
        this.nodeAddress = ossProperties.getStoreHost();
        this.consoleServiceWrapper = consoleServiceWrapper;
    }

    public ObjectResult putObject(ObjectProp objectProp, String contentId, File savedFile, String originalFilename, String sha256sum) {
        String pid = objectProp.getPid();
        String objectName = objectProp.getObjectName();
        FileMeta fileMeta = objectRepository.getBySha256sum(sha256sum);
        if (fileMeta != null) {
            FileUtils.deleteQuietly(savedFile);
            return copyObject(objectProp, originalFilename, fileMeta);
        } else {
            String savedPath = savedFile.getAbsolutePath();
            long size = savedFile.length();
            String objectId = UUID.randomUUID().toString().replace("-", "");
            String contentType = FileType.getMediaType(savedPath);
            int fileType = FileType.getFileType(contentType);
            int scope = objectProp.getScope();
            fileMeta = new FileMeta(objectName, objectId, contentId, originalFilename, size,
                    fileType, contentType, sha256sum, pid, scope, objectProp.isSetCallback());
            String blockId = UUID.randomUUID().toString();
            List<DataBlock> list = List.of(new DataBlock(contentId, blockId, nodeAddress, savedPath, size));
            objectRepository.saveObject(fileMeta, list);
            return new ObjectResult(objectName, objectId, fileType, savedPath);
        }
    }

    public ObjectResult putObject(String originalObjectName, String contentId, String suffix, File savedFile) throws Exception {
        ObjectProp objectProp = objectNameService.getObjectProp(originalObjectName, suffix);
        String sha256sum = DigestUtil.sha256sum(savedFile.getAbsolutePath());
        return putObject(objectProp, contentId, savedFile, "", sha256sum);
    }

    public void putObject(String objectName, byte[] bytes) {
    }

    public ObjectResult copyObject(ObjectProp objectProp, String filename, FileMeta fileMeta) {
        String dupObjectId = fileMeta.getObjectId();
        String domain = ServletUtil.getHeader("host");
        int owner = consoleServiceWrapper.getNodeProperties(domain).getOwner();
        ObjectMeta objectMeta = objectRepository.getObjectMetaByName(fileMeta.getObjectName(), owner);

        int fileType = fileMeta.getFileType();
        String savedPath = objectMeta.getAbsolutePath();
        String objectName = objectProp.getObjectName();
        String objectId = UUID.randomUUID().toString().replace("-", "");
        int scope = objectProp.getScope();
        String pid = objectProp.getPid();
        FileMeta fileMeta1 = new FileMeta(objectName, objectId, filename, fileMeta, pid, scope, objectProp.isSetCallback());
        objectRepository.saveFileMeta(fileMeta1);
        return new ObjectResult(objectName, objectId, fileType, savedPath, dupObjectId);
    }

    @Deprecated
    public ObjectResult copyFromObjectId(String fromObjectId) {
        FileMeta fileMeta = objectRepository.getByObjectId(fromObjectId);
        int fileType = fileMeta.getFileType();

        String fromObjectName = fileMeta.getObjectName();
        String suffix = StringUtil.getSuffix(fromObjectName);
        String filename = fileMeta.getFilename();
        String savedPath = "";
        int scope = fileMeta.getScope();
        String toObjectName = objectNameService.getObjectNameFromOriginal(fromObjectName, suffix);
        String toObjectId = UUID.randomUUID().toString().replace("-", "");
        String pid = fileMeta.getPid();
        FileMeta fileMeta1 = new FileMeta(toObjectName, toObjectId, filename, fileMeta, pid, scope, false);
        objectRepository.saveFileMeta(fileMeta1);
        return new ObjectResult(toObjectName, toObjectId, fileType, savedPath);
    }

    public void deleteObject(String objectId) {
        FileMeta fileMeta = objectRepository.getByObjectId(objectId);
        objectRepository.deleteObject(fileMeta);
    }
}
