package com.bocloud.ims.booter.controller.resource.azure.blob;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.model.DeleteParam;
import com.bocloud.common.annotations.Log;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.ims.entity.resource.azure.blob.Blob;
import com.bocloud.ims.interfaces.resource.azure.blob.BlobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * azure blob对象存储访问
 *
 * @author wangyu
 * @version 5.0.0-SNAPSHOT
 * @since 2021/2/2
 */
@Slf4j
@RestController
@RequestMapping("/v1/azure/blobs")
@Api(value = "blob管理", tags = "blob管理")
public class BlobController {

    @Autowired
    private BlobService blobService;

    @ApiOperation(value = "获取blob列表")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "获取blob列表")
    @GetMapping
    public BocloudResult<GridBean<Blob>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.list(pager, context);
    }

    @ApiOperation(value = "获取blob列表")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "获取blob列表")
    @GetMapping("/condition")
    public BocloudResult condition(@RequestParam(value = Common.CONDITION, required = false) String condition, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.condition(condition, context);
    }

    @ApiOperation(value = "添加blob")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "添加blob")
    @PostMapping
    public BocloudResult<Blob> create(@RequestParam(value = "filePath") String filePath,
                                      @RequestParam(value = "blobType", required = false) String blobType,
                                      @RequestParam(value = "standardBlobTier", required = false) String standardBlobTier,
                                      @RequestParam(value = "containerId") Long containerId,
                                      @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.create(filePath, blobType, standardBlobTier, containerId, context);
    }


    @ApiOperation(value = "下载blob")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "下载blob")
    @GetMapping("/{id}/download")
    public void download(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context, HttpServletRequest request, HttpServletResponse response) throws IOException {
        File file = null;
        BufferedInputStream bufferedInputStream = null;
        try {
            String filePath = blobService.download(id, context);
            log.info("blob服务器临时文件路径：{}", filePath);
            if (StringUtils.isEmpty(filePath)) {
                this.processError(response, new BocloudResult(false, "文件不存在"));
                return;
            }
            file = new File(filePath);
            if (null == file || !file.exists()) {
                this.processError(response, new BocloudResult(false, "文件不存在"));
                return;
            }
            BocloudResult result = blobService.detail(id, context);
            if (result.isFailed()) {
                this.processError(response, result);
                return;
            }
            Blob blob = (Blob) result.getData();
            response.reset();
            log.info("content-type:{}", blob.getContentType());
            response.setContentType(blob.getContentType());
            String fileName = blob.getName();
            final String userAgent = request.getHeader("user-agent").toLowerCase();
            if (userAgent.contains("trident") || userAgent.contains("edge")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
            }
            log.info("file name:{}", fileName);
            log.info("file length:{}", file.length());
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
            bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            //从文件中按字节读取内容，到文件尾部时read方法将返回-1
            while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, bytesRead);
            }
            response.getOutputStream().flush();
            response.getOutputStream().close();
            file.delete();
        } catch (Exception e) {
            log.error("Get error message:{}", e);
        } finally {
            if (null != file) {
                file.deleteOnExit();
            }
            if (null != bufferedInputStream) {
                bufferedInputStream.close();
            }
        }
    }

    @ApiOperation(value = "删除blob")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "删除blob")
    @DeleteMapping("/{id}")
    public BocloudResult remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.remove(id, context);
    }

    @ApiOperation(value = "查看blob详情")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "查看blob详情")
    @GetMapping("/{id}")
    public BocloudResult<Blob> detail(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.detail(id, context);
    }

    @ApiOperation(value = "批量删除blob")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "批量删除blob")
    @DeleteMapping
    public BocloudResult batchRemove(@RequestBody DeleteParam params,
                                     @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.batchRemove(params, context);
    }


    @ApiOperation(value = "添加blob快照")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "添加blob快照")
    @PostMapping("/snapshots")
    public BocloudResult<Blob> createSnapshot(@RequestBody Blob blob, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.createSnapshot(blob, context);
    }

    @ApiOperation(value = "删除blob快照")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "删除blob")
    @DeleteMapping("/snapshots/{id}")
    public BocloudResult removeSnapshot(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.removeSnapshot(id, context);
    }


    @ApiOperation(value = "批量删除blob快照")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "批量删除blob快照")
    @DeleteMapping("/snapshots")
    public BocloudResult batchRemoveSnapshot(@RequestBody DeleteParam params,
                                             @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.batchRemoveSnapshot(params, context);
    }

    @ApiOperation(value = "下载blob快照")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "下载blob快照")
    @GetMapping("/{id}/snapshots/download")
    public void downloadSnapshot(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context, HttpServletRequest request, HttpServletResponse response) throws IOException {
        File file = null;
        BufferedInputStream bufferedInputStream = null;
        try {
            String filePath = blobService.downloadSnapshot(id, context);
            if (StringUtils.isEmpty(filePath)) {
                this.processError(response, new BocloudResult(false, "文件不存在"));
                return;
            }
            file = new File(filePath);
            if (null == file) {
                this.processError(response, new BocloudResult(false, "文件不存在"));
                return;
            }
            BocloudResult result = blobService.detail(id, context);
            if (result.isFailed()) {
                this.processError(response, result);
                return;
            }
            Blob blob = (Blob) result.getData();
            response.reset();
            log.info("content-type:{}", blob.getContentType());
            response.setContentType(blob.getContentType());
            String fileName = blob.getName();
            final String userAgent = request.getHeader("user-agent").toLowerCase();
            if (userAgent.contains("trident") || userAgent.contains("edge")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
            }
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
            bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            //从文件中按字节读取内容，到文件尾部时read方法将返回-1
            while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, bytesRead);
            }
            file.delete();
            response.getOutputStream().flush();
            response.getOutputStream().close();
        } catch (Exception e) {
            log.error("Get error message:{}", e);
        } finally {
            if (null != file) {
                file.deleteOnExit();
            }
            if (null != bufferedInputStream) {
                bufferedInputStream.close();
            }
        }
    }

    @ApiOperation(value = "blob操作")
    @Log(module = BoCloudService.IMS, target = "blob", operation = "blob操作")
    @PatchMapping("/{id}")
    public BocloudResult action(@PathVariable(value = Common.ID) Long id, @RequestParam(value = Common.PARAMS) String params, @RequestParam(value = Common.ACTION) String action,
                                @Value(Common.REQ_CONTEXT) RequestContext context) {
        return blobService.action(id, action, JSONObject.parseObject(params), context);
    }


    /**
     * 处理异常请求
     *
     * @param response
     * @throws IOException
     */
    private void processError(HttpServletResponse response, BocloudResult result) throws IOException {
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.getWriter().println(JSONObject.toJSON(result));
        response.flushBuffer();
    }
}
