/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.service.impl;

import java.io.*;
import java.util.Date;
import java.util.Objects;

import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.obs.services.ObsClient;
import com.qiniu.common.Zone;
import com.yami.shop.common.bean.AliOss;
import com.yami.shop.common.bean.HuaWeiOss;
import com.yami.shop.common.enums.QiniuZone;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.config.ShopConfig;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import com.qiniu.common.QiniuException;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.yami.shop.bean.model.AttachFile;
import com.yami.shop.common.bean.Qiniu;
import com.yami.shop.dao.AttachFileMapper;
import com.yami.shop.service.AttachFileService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author lgh
 * @date 2018/07/27
 */
@Service
@AllArgsConstructor
public class AttachFileServiceImpl extends ServiceImpl<AttachFileMapper, AttachFile> implements AttachFileService {

    private final AttachFileMapper attachFileMapper;

	private final ShopConfig shopConfig;

    public final static String NORM_MONTH_PATTERN = "yyyy/MM/";

	@Override
	@Transactional(rollbackFor = Exception.class)
	public String uploadFile(byte[] bytes,String originalName) throws IOException {
		String extName = FileUtil.extName(originalName);
		String imgName = FileUtil.mainName(originalName);
		String filePath =randomFilePath(extName);


		AttachFile attachFile = new AttachFile();
		attachFile.setFilePath(filePath);
		attachFile.setFileSize(bytes.length);
		attachFile.setFileType(extName);
		attachFile.setFileName(imgName);
		attachFile.setUploadTime(new Date());
		attachFileMapper.insert(attachFile);

		upload(bytes, filePath);
		return filePath;
	}

	@Override
	public String uploadImg(byte[] bytes, AttachFile attachFile) throws IOException {
		String filePath =randomFilePath(attachFile.getFileType());
		//数据存入数据库
		attachFile.setFilePath(filePath);
		attachFile.setFileSize(bytes.length);
		attachFileMapper.insert(attachFile);

		// 上传
		upload(bytes, filePath);
		return filePath;
	}

	private void upload(byte[] bytes, String filePath) throws IOException {
		Qiniu qiniu = shopConfig.getQiniu();
		if (qiniu.getIsOpen()) {
			String upToken = auth(qiniu).uploadToken(qiniu.getBucket(),filePath);
			uploadManager(qiniu).put(bytes, filePath, upToken);
			return;
		}

		AliOss aliOss = shopConfig.getAliOss();
		if (aliOss.getIsOpen()) {

			OSS ossClient = new OSSClientBuilder().build(aliOss.getEndpoint(), aliOss.getAccessKeyId(), aliOss.getAccessKeySecret());
			try {
				InputStream input = new ByteArrayInputStream(bytes);
				ossClient.putObject(new PutObjectRequest(aliOss.getBucketName(), filePath, input));
				String url = "https://" + aliOss.getBucketName() + "." + aliOss.getEndpoint() + "/" + filePath;
				System.out.println("AliOSS upload success, URL: " + url);
			} catch (Exception e) {
				e.printStackTrace();
				System.err.println(e.getMessage());
			} finally {
				ossClient.shutdown();
			}
			return;
		}

		HuaWeiOss huaWeiOss = shopConfig.getHuaWeiObs();
		if (huaWeiOss.getIsOpen()){
			// 创建ObsClient实例
			ObsClient obsClient = new ObsClient(huaWeiOss.getAccessKeyId(), huaWeiOss.getSecretAccessKey(), huaWeiOss.getEndpoint());
			InputStream input = new ByteArrayInputStream(bytes);
			obsClient.putObject(huaWeiOss.getBucketName(), filePath, input);
			return;
		}
	}

	private String randomFilePath(String fileType) {
		return DateUtil.format(new Date(), NORM_MONTH_PATTERN)+ IdUtil.simpleUUID() + "." + fileType;
	}

	@Override
	public void deleteFile(String filePath){
		attachFileMapper.delete(new LambdaQueryWrapper<AttachFile>().eq(AttachFile::getFilePath,filePath));
		try {
			Qiniu qiniu = shopConfig.getQiniu();
			if (qiniu.getIsOpen()) {
				bucketManager(qiniu).delete(qiniu.getBucket(), filePath);
				return;
			}

			AliOss aliOss = shopConfig.getAliOss();
			if (aliOss.getIsOpen()) {
				OSS ossClient = new OSSClientBuilder().build(aliOss.getEndpoint(), aliOss.getAccessKeyId(), aliOss.getAccessKeySecret());
				try {
					ossClient.deleteObject(aliOss.getBucketName(), filePath);
				} catch (Exception e) {
					e.printStackTrace();
					System.err.println(e.getMessage());
				} finally {
					ossClient.shutdown();
				}
				return;
			}
			HuaWeiOss huaWeiOss = shopConfig.getHuaWeiObs();
			if (huaWeiOss.getIsOpen()){
				ObsClient obsClient = new ObsClient(huaWeiOss.getAccessKeyId(), huaWeiOss.getSecretAccessKey(), huaWeiOss.getEndpoint());
				obsClient.deleteObject(huaWeiOss.getBucketName(), filePath);
			}
		} catch (QiniuException e) {
			throw new RuntimeException(e);
		}
	}
	@Override
	public Boolean updateFileName(AttachFile attachFile) {
		return attachFileMapper.updateFileName(attachFile);
	}

	@Override
	public IPage<AttachFile> getPage(PageParam<AttachFile> page, AttachFile attachFile) {
		return attachFileMapper.getPage(page,attachFile);
	}


	// ================== 七牛云配置 ======================


	/**
	 * 构建一个七牛上传工具实例
	 */
	private UploadManager uploadManager(Qiniu qiniu) {
		return new UploadManager(qiniuConfig(qiniu));
	}

	/**
	 * 认证信息实例
	 * @return
	 */
	private Auth auth(Qiniu qiniu) {
		return Auth.create(qiniu.getAccessKey(), qiniu.getSecretKey());
	}

	/**
	 * 构建七牛空间管理实例
	 */
	private BucketManager bucketManager(Qiniu qiniu) {
		return new BucketManager(auth(qiniu), qiniuConfig(qiniu));
	}

	/**
	 * 根据配置文件选择机房
	 */
	private com.qiniu.storage.Configuration qiniuConfig(Qiniu qiniu) {

		Zone zone = null;
		if (Objects.equals(qiniu.getZone(), QiniuZone.HUA_BEI)) {
			zone = Zone.huabei();
		} else if (Objects.equals(qiniu.getZone(), QiniuZone.HUA_DONG)) {
			zone = Zone.huadong();
		} else if (Objects.equals(qiniu.getZone(), QiniuZone.HUA_NAN)) {
			zone = Zone.huanan();
		} else if (Objects.equals(qiniu.getZone(), QiniuZone.BEI_MEI)) {
			zone = Zone.beimei();
		} else if (Objects.equals(qiniu.getZone(), QiniuZone.XIN_JIA_PO)) {
			zone = Zone.xinjiapo();
		}
		return new com.qiniu.storage.Configuration(zone);
	}

}
