package com.sf.file.service.impl;

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

import javax.servlet.http.HttpServletResponse;

import com.sf.common.utils.openssl.RsaSignUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.sf.common.exception.ServiceException;
import com.sf.common.utils.DateUtils;
import com.sf.common.utils.file.FileUtils;
import com.sf.file.domain.SysOss;
import com.sf.file.entity.UploadResult;
import com.sf.file.mapper.SysOssMapper;
import com.sf.file.service.ISysOssService;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;

/**
 * OSS对象存储Service业务层处理
 * 
 * @author ztzh
 * @date 2024-03-14
 */
@Service
public class SysOssServiceImpl implements ISysOssService {
	@Autowired
	private SysOssMapper sysOssMapper;

	@Autowired
	private AmazonS3 amazonS3;

	@Value("${file.ceph.endpoint}")
	private String FILE_CEPH_POINT;

	@Value("${file.ceph.bucket.name}")
	private String FILE_CEPH_BUCKET_NAME;

	/**
	 * 查询OSS对象存储
	 * 
	 * @param id OSS对象存储主键
	 * @return OSS对象存储
	 */
	@Override
	public SysOss selectSysOssById(String id) {
		return sysOssMapper.selectSysOssById(id);
	}

	/**
	 * 查询OSS对象存储列表
	 * 
	 * @param sysOss OSS对象存储
	 * @return OSS对象存储
	 */
	@Override
	public List<SysOss> selectSysOssList(SysOss sysOss) {
		return sysOssMapper.selectSysOssList(sysOss);
	}

	/**
	 * 新增OSS对象存储
	 * 
	 * @param sysOss OSS对象存储
	 * @return 结果
	 */
	@Override
	public int insertSysOss(SysOss sysOss) {
		sysOss.setId(UUID.randomUUID().toString());
		sysOss.setCreateTime(DateUtils.getNowDate());
		return sysOssMapper.insertSysOss(sysOss);
	}

	/**
	 * 修改OSS对象存储
	 * 
	 * @param sysOss OSS对象存储
	 * @return 结果
	 */
	@Override
	public int updateSysOss(SysOss sysOss) {
		sysOss.setUpdateTime(DateUtils.getNowDate());
		return sysOssMapper.updateSysOss(sysOss);
	}

	/**
	 * 批量删除OSS对象存储
	 * 
	 * @param ids 需要删除的OSS对象存储主键
	 * @return 结果
	 */
	@Override
	public int deleteSysOssByIds(String[] ids) {
		return sysOssMapper.deleteSysOssByIds(ids);
	}

	/**
	 * 删除OSS对象存储信息
	 * 
	 * @param id OSS对象存储主键
	 * @return 结果
	 */
	@Override
	public int deleteSysOssById(String id) {
		return sysOssMapper.deleteSysOssById(id);
	}

	@Override
	public SysOss upload(MultipartFile file) {
		String originalfileName = file.getOriginalFilename();
		String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."),
				originalfileName.length());
		UploadResult uploadResult;
		try {
			uploadResult = upload(file.getBytes(), suffix, file.getContentType());
		} catch (Exception e) {
			throw new ServiceException(e.getMessage());
		}
		// 保存文件信息
		return buildResultEntity(originalfileName, suffix, uploadResult);
	}

	@Override
	public SysOss upload(File file) {
		String originalfileName = file.getName();
		String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."),
				originalfileName.length());
		UploadResult uploadResult = upload(file, suffix);
		// 保存文件信息
		return buildResultEntity(originalfileName, suffix, uploadResult);
	}

	@Override
	public void download(String ossId, HttpServletResponse response) throws Exception {
		SysOss sysOss = selectSysOssById(ossId);
		if (ObjectUtil.isNull(sysOss)) {
			throw new ServiceException("文件数据不存在!");
		}
		FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
		response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
		try (InputStream inputStream = getObjectContent(sysOss.getFileName())) {
			int available = inputStream.available();
			IoUtil.copy(inputStream, response.getOutputStream(), available);
			response.setContentLength(available);
		} catch (Exception e) {
			throw new ServiceException(e.getMessage());
		}
	}
	@Override
	public SysOss uploadSignZip(MultipartFile file) throws Exception {
		return upload(RsaSignUtil.signZip(file));
	}

	public UploadResult uploadSuffix(File file, String suffix) {
		return upload(file, getPath(null, suffix));
	}

	public UploadResult upload(File file, String path) {
		try {
			PutObjectRequest putObjectRequest = new PutObjectRequest(FILE_CEPH_BUCKET_NAME, path, file);
			// 设置上传对象的 Acl 为公共读
			putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
			amazonS3.putObject(putObjectRequest);
		} catch (Exception e) {
			throw new ServiceException("上传文件失败，请检查配置信息:[" + e.getMessage() + "]");
		}
		return UploadResult.builder().url(path).filename(path).build();
	}

	public UploadResult upload(byte[] data, String suffix, String contentType) {
		return upload(new ByteArrayInputStream(data), getPath(null, suffix), contentType);
	}

	public UploadResult upload(InputStream inputStream, String path, String contentType) {
		if (!(inputStream instanceof ByteArrayInputStream)) {
			inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
		}
		try {
			ObjectMetadata metadata = new ObjectMetadata();
			metadata.setContentType(contentType);
			metadata.setContentLength(inputStream.available());
			PutObjectRequest putObjectRequest = new PutObjectRequest(FILE_CEPH_BUCKET_NAME, path, inputStream,
					metadata);
			// 设置上传对象的 Acl 为公共读
			putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
			amazonS3.putObject(putObjectRequest);
		} catch (Exception e) {
			throw new ServiceException("上传文件失败，请检查配置信息:[" + e.getMessage() + "]");
		}
		return UploadResult.builder().url(path).filename(path).build();
	}

	public InputStream getObjectContent(String path) {
		S3Object object = amazonS3.getObject(FILE_CEPH_BUCKET_NAME, path);
		return object.getObjectContent();
	}

	public String getPath(String prefix, String suffix) {
		// 生成uuid
		String uuid = IdUtil.fastSimpleUUID();
		// 文件路径
		String path = DateUtils.datePath() + "/" + uuid;
		if (StringUtils.isNotBlank(prefix)) {
			path = prefix + "/" + path;
		}
		return path + suffix;
	}

	private SysOss buildResultEntity(String originalfileName, String suffix, UploadResult uploadResult) {
		SysOss oss = new SysOss();
		oss.setId(UUID.randomUUID().toString());
		oss.setUrl(FILE_CEPH_POINT + "/" + FILE_CEPH_BUCKET_NAME + "/" + uploadResult.getUrl());
		oss.setFileSuffix(suffix);
		oss.setFileName(uploadResult.getFilename());
		oss.setOriginalName(originalfileName);
		this.insertSysOss(oss);
		return oss;
	}
}
