package cn.com.qmth.stmms.ms.collect.util;

import cn.com.qmth.stmms.ms.commons.config.AliYunOssConfig;
import cn.com.qmth.stmms.ms.commons.config.ImageServerConfig;
import cn.com.qmth.stmms.ms.commons.config.SystemConfig;
import cn.com.qmth.stmms.ms.commons.utils.MD5Util;
import cn.com.qmth.stmms.ms.core.cache.ParamCache;
import cn.com.qmth.stmms.ms.core.domain.Attachment;
import cn.com.qmth.stmms.ms.core.domain.Student;
import cn.com.qmth.stmms.ms.core.repository.AttachmentRepo;
import cn.com.qmth.stmms.ms.core.vo.Subject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.Objects;
import java.util.StringJoiner;

/**
 *
 */
@Component
public class OssUploadUtil {

    private static final String SUCCESS = "SUCCESS", FAIL = "FAIL";

    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(OssUploadUtil.class);

    @Resource
    AliYunOssConfig aliYunOssConfig;

    @Autowired
    ImageServerConfig imageServerConfig;

    @Autowired
    SystemConfig systemConfig;

    @Autowired
    private AttachmentRepo attachmentRepo;

    /**
     * 上传oss并校验md5，成功删除本地文件
     *
     * @param student
     * @param subject
     * @param file
     * @param type    图片类型
     * @param dir     不同类型对应的存储目录
     */
    public void ossUpload(Student student, Subject subject, File file, String type, String dir, String md5) {
        if (!imageServerConfig.isAliyunOss()) {
            return;
        }
        Attachment att = null;
        try {
            //是否存在
            att = attachmentRepo.findByWorkIdAndSubjectAndFileTypeAndExamNumber(student.getWorkId(), subject.name(), type, student.getExamNumber());
            if (att == null) {
                att = new Attachment();
            }
            att.setWorkId(student.getWorkId());
            att.setSubject(subject.name());
            att.setExamNumber(student.getExamNumber());
            att.setFilePathLocal(file.getPath());
            att.setFileName(file.getName());
            att.setFileType(type);
            String ext = getExtension(file.getName());
            att.setFileExt(ext);
            att.setTime(new Date());
            String fileName = student.getExamNumber();
            //0：随机码 1：考号
            if (ParamCache.paramMap.get(student.getWorkId()).getNameRule() == 1) {
                fileName = MD5Util.getImageRuleMd5(student.getWorkId(), subject.ordinal(), student.getAreaCode(), student.getExamNumber(), student.getId());
            }
            StringJoiner ossSavePath = new StringJoiner("/").add(imageServerConfig.getDir()).add(dir.replace("\\", "/")).add(String.valueOf(student.getWorkId())).add(subject.name()).add(student.getAreaCode());
            String saveFileName = fileName + ".jpg";
            String saveFile = ossSavePath.toString().concat("/").concat(saveFileName);

            att.setObjectKey(saveFile);
            att.setOssName(saveFileName);

            //默认给FAIL，如果成功更新状态
            att.setOssStatus(FAIL);
            att.setDeleteStatus(FAIL);

            String endpoint = aliYunOssConfig.getEndpoint();
            String accessKeyId = aliYunOssConfig.getAccessKeyId();
            String accessKeySecret = aliYunOssConfig.getAccessKeySecret();
            String bucketName = aliYunOssConfig.getBucket();
            att.setBucket(bucketName);
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, saveFile, file);
            PutObjectResult por = ossClient.putObject(putObjectRequest);
            if (Objects.nonNull(por.getRequestId()) && por.getResponse() == null) {
                if (Objects.nonNull(por.getETag()) && por.getETag().equalsIgnoreCase(md5)) {
                    att.setOssStatus(SUCCESS);
                    //成功后，清除失败信息
                    att.setOssFailMsg(null);
                    boolean del = file.delete();
                    att.setDeleteStatus(del ? SUCCESS : FAIL);
                }
            }
            // 关闭OSSClient。
            ossClient.shutdown();
        } catch (Exception e) {
            if (att != null) {
                att.setOssFailMsg(e.getMessage());
            }
        }

        if (att != null) {
            attachmentRepo.save(att);
        }
    }

    public InputStream ossDownload(String objectName) {
        String endpoint = aliYunOssConfig.getEndpoint();
        String accessKeyId = aliYunOssConfig.getAccessKeyId();
        String accessKeySecret = aliYunOssConfig.getAccessKeySecret();
        String bucketName = aliYunOssConfig.getBucket();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        InputStream inputStream = ossObject.getObjectContent();
        String requestId = ossObject.getRequestId();

        // 读取文件内容。
        /*System.out.println("Object content:");
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        while (true) {
            String line = reader.readLine();
            if (line == null) break;

            System.out.println("\n" + line);
        }
// 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
        reader.close();*/

// 关闭OSSClient。
        ossClient.shutdown();
        return inputStream;
    }

    /**
     * 获取文件的后缀
     */
    protected String getExtension(String fileName) {
        int k = fileName.lastIndexOf(".");
        String ext = "";
        if (k > 0) {
            ext = fileName.substring(k + 1);
        }
        return ext;
    }
}
