package com.testor.common.api;

import com.testor.biz.file.FileEnumCode;
import com.testor.biz.file.controller.SysFileController;
import com.testor.biz.file.model.domain.SysFile;
import com.testor.biz.file.model.dto.FileAjaxDTO;
import com.testor.biz.file.model.dto.FileDTO;
import com.testor.biz.file.service.SysFileService;
import com.testor.biz.file.service.TSysFileBizService;
import com.testor.biz.helper.CommonHelper;
import com.testor.biz.sys.file.util.MinioUtilS;
import com.testor.module.sys.service.NewSysFileService;
import com.tongtech.tfw.backend.common.biz.models.BaseResponse;
import com.tongtech.tfw.backend.common.models.exceptions.ApiException;
import com.tongtech.tfw.backend.common.models.supers.SuperController;
import com.tongtech.tfw.backend.core.constants.IoConstants;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.codec.Base64Helper;
import com.tongtech.tfw.backend.core.helper.datetime.DatetimeHelper;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Random;

/**
 * @author rsq
 * @program zlmy_boot
 * @return
 **/
@RestController
@RequestMapping({"/new/file"})
public class FileController extends SuperController {

    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
    @Autowired
    private SysFileService sysFileService;
    @Autowired
    private NewSysFileService newSysFileService;
    @Autowired
    private TSysFileBizService tSysFileBizService;
    @Autowired
    private MinioClient minioClient;
    @Value("${minio.bucket}")
    private String bucketName;
    @Value("${minio.endpoint}")
    private String address;
    @Autowired
    private MinioUtilS minioUtilS;
    @Value("${apisix.minioroute.url}")
    private String apisixUrl;
    @Value("${file.path}")
    private String fileRootPath;


    @ApiOperation(
            value = "上传文件BASE64",
            notes = "上传文件BASE64 Upload File Base 64"
    )
    @PostMapping({"/uploadBase64"})
    public BaseResponse<FileDTO> uploadBase64(@RequestBody FileAjaxDTO fileAjaxDTO) {
        BaseResponse<FileDTO> baseResponse = new BaseResponse();
        if (!ObjectHelper.isEmpty(fileAjaxDTO) && !StringHelper.isEmpty(fileAjaxDTO.getFile()) && fileAjaxDTO.getFile().split(",").length >= 2) {
            String fileName = fileAjaxDTO.getFileName();
            long size = new BigDecimal(fileAjaxDTO.getFileSize()).longValue();

            int beginIndex = fileName.indexOf(".") + 1;
            String ext = StringHelper.substring(fileName, beginIndex, fileName.length());
            String filePath = DatetimeHelper.getDateTime8Length();
            String saveName = IdHelper.getId32bitTime();
            byte[] fileContent = Base64Helper.decode(fileAjaxDTO.getFile().split(",")[1]);
            if (!CommonHelper.checkFileType(fileContent, ext)) {
                throw new ApiException(FileEnumCode.TYPE_CHECK_FAILD.transform());
            } else {
                InputStream input = new ByteArrayInputStream(fileContent);
                String contentType = ((MediaType) MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM)).toString();
                this.uploadMinio(input, fileName, contentType);
                log.info("保存成功：FileId：" + saveName + ", ext: " + ext + ", path:" + filePath + ", name:" + fileName + ", user: " + this.getUserId());
                SysFile sysFile = ((SysFile.SysFileBuilder)((SysFile.SysFileBuilder)SysFile.builder().fileId(saveName).fileName(fileName).fileSize(BigDecimal.valueOf(size)).fileExt(ext).filePath(filePath + IoConstants.PATH_SLASH + saveName).createBy(this.getUserId())).updateBy(this.getUserId())).build();
                boolean result = this.sysFileService.save(sysFile);
                if (result) {
                    String Path = this.apisixUrl + "/" + this.bucketName + "/" + fileName;
                    FileDTO newEntity = FileDTO.builder().fileId(saveName).fileName(fileName).filePath(Path).build();
                    baseResponse.setData(newEntity);
                }

                return baseResponse;
            }
        } else {
            throw new ApiException(FileEnumCode.NOT_FOUND.transform());
        }
    }

    private void uploadMinio(InputStream input, String fileName, String contentType) {
        try {
            this.minioClient.putObject((PutObjectArgs)((PutObjectArgs.Builder)((PutObjectArgs.Builder)PutObjectArgs.builder().bucket(this.bucketName)).object(fileName)).stream(input, (long)input.available(), -1L).contentType(contentType).build());
        } catch (Exception var13) {
            var13.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException var12) {
                    var12.printStackTrace();
                }
            }

        }

    }

    @ApiOperation(
            value = "下载文件",
            notes = "下载文件 Download File"
    )
    @GetMapping({"/download"})
    public ResponseEntity<byte[]> download(@RequestParam String fileId) throws IOException {
        ResponseEntity<byte[]> download = null;
        if (StringHelper.isNotEmpty(fileId)) {
            SysFile sysFile = (SysFile)this.sysFileService.getById(fileId);
            if (ObjectHelper.isEmpty(sysFile)) {
                throw new ApiException(FileEnumCode.LOCAL_FILE_NOT_EXISTED.transform());
            }

            String filename = sysFile.getFileDowName();
            download = downloadBuild(filename);
        }

        return download;
    }

    @ApiOperation(
            value = "下载文件",
            notes = "下载文件 Download File"
    )
    @GetMapping({"/getFileUrlById"})
    public BaseResponse<String> getFileUrlById(@RequestParam String fileIds) throws IOException {
        BaseResponse<String> response = new BaseResponse();
        if (StringHelper.isNotEmpty(fileIds)) {
            String urls = newSysFileService.getFileUrlByIds(fileIds);
            response.setData(urls);
        }
        return response;
    }


    public ResponseEntity<byte[]> downloadBuild(String fileName) {
        ResponseEntity<byte[]> responseEntity = null;
        InputStream in = null;
        ByteArrayOutputStream out = null;

        try {
            in = this.minioClient.getObject((GetObjectArgs)((GetObjectArgs.Builder)((GetObjectArgs.Builder)GetObjectArgs.builder().bucket(this.bucketName)).object(fileName)).build());
            out = new ByteArrayOutputStream();
            IOUtils.copy(in, out);
            byte[] bytes = out.toByteArray();
            HttpHeaders headers = new HttpHeaders();

            try {
                headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            } catch (UnsupportedEncodingException var21) {
                var21.printStackTrace();
            }

            headers.setContentLength((long)bytes.length);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setAccessControlExposeHeaders(Arrays.asList("*"));
            responseEntity = new ResponseEntity(bytes, headers, HttpStatus.OK);
        } catch (Exception var22) {
            var22.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException var19) {
                        var19.printStackTrace();
                    }
                }

                if (out != null) {
                    out.close();
                }
            } catch (IOException var20) {
                var20.printStackTrace();
            }

        }

        return responseEntity;
    }


    public static void main(String[] args) {
        long size = new BigDecimal("8119.999999999999999999999999999999999999").longValue();
        System.out.println(size);
    }

}
