package org.security.imagePlatformDock.controller;

import lombok.AllArgsConstructor;
import org.owasp.esapi.ESAPI;
import org.security.common.utils.InputStreamAESUtil;
import org.security.config.ImagePlateFormDockProperties;
import org.security.system.user.feign.IUserClient;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

@RestController
@AllArgsConstructor
public class DownloadFileController {
	private final ImagePlateFormDockProperties imagePlateFormDockProperties;
	private final IUserClient userClient;

	@GetMapping("/file/{filename}")
	public void download(@PathVariable("filename") String filename, HttpServletResponse res, @RequestParam(value = "encrypt", required = false) Boolean encrypt) throws IOException {
		// if (!ESAPI.validator().isValidFileName("upload", filename, false)) {
		// 	throw new IOException("非法的文件名");
		// }
		encrypt = Func.isNull(encrypt) ? false : encrypt;
		BladeUser user = AuthUtil.getUser();
		boolean decrypt = false;
		if (null != user) {
			R fileDecrypt = userClient.userHasRoleAlias(user.getTenantId(), user.getUserId(), "fileDecrypt");
			if (fileDecrypt.isSuccess()) {
				if ((Boolean) fileDecrypt.getData()) {
					decrypt = true;
				}
			}
		}
		if (AuthUtil.isAdministrator()) {
			decrypt = true;
		}
		String filePath = imagePlateFormDockProperties.getService_path();
		File file = new File(filePath + "/" + filename);
		filename = URLEncoder.encode(filename, "UTF-8").replaceAll("%20", "\\+").replaceAll("%28", "\\(")
			.replaceAll("%29", "\\)").replaceAll("%3B", ";").replaceAll("%40", "@").replaceAll("%23", "\\#")
			.replaceAll("%26", "\\&").replaceAll("%2C", "\\,").replaceAll("%24", "\\$")
			.replaceAll("%25", "\\%").replaceAll("%5E", "\\^").replaceAll("%3D", "\\=")
			.replaceAll("%2B", "\\+").replaceAll("%5B", "\\[").replaceAll("%5D", "\\]")
			.replaceAll("%7B", "\\{").replaceAll("%7D", "\\}");
		res.setHeader("content-type", "application/octet-stream");
		res.setHeader("Content-Disposition", "attachment;filename=\"" + filename+"\"");
		res.setHeader("Set-Cookie","HttpOnly");
		res.setContentType("application/octet-stream");
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;
		FileInputStream fileInputStream = null;
		try {
			os = res.getOutputStream();
			fileInputStream = new FileInputStream(file);
			// InputStream encryptedStream = InputStreamAESUtil.decryptStream(fileInputStream);
			// bis = new BufferedInputStream(encryptedStream);
			if (decrypt) {
				InputStream encryptedStream = encrypt ? InputStreamAESUtil.decryptStream(fileInputStream) : fileInputStream;
				bis = new BufferedInputStream(encryptedStream);
			} else {
				bis = new BufferedInputStream(fileInputStream);
			}
			int i = bis.read(buff);
			while (-1 != i) {
				os.write(buff, 0, buff.length);
				i = bis.read(buff);
			}
			os.flush();
		} catch (Exception e) {
			e.printStackTrace();
			if (null != fileInputStream) {
				try {
					fileInputStream.close();
				} catch (IOException ex) {
					e.printStackTrace();
				}
			}
			if (null != bis) {
				try {
					bis.close();
				} catch (IOException ex) {
					e.printStackTrace();
				}
			}
			if (null != os) {
				try {
					os.close();
				} catch (IOException ex) {
					e.printStackTrace();
				}
			}
		}
	}
}
