package org.jetlinks.community.io.file.web;

import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.jetlinks.community.io.file.FileInfo;
import org.jetlinks.community.io.file.FileManager;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpRange;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

@RestController
@RequestMapping("/file")
@AllArgsConstructor
public class FileManagerController {

    private final FileManager fileManager;

    @PostMapping("/upload")
    @Authorize(merge = false)
    @Operation(summary = "上传文件")
    public Mono<FileInfo> upload(@RequestPart("file") Mono<FilePart> partMono) {
        return partMono.flatMap(fileManager::saveFile);
    }

    @GetMapping("/{fileId}")
    @Authorize(merge = false)
    @Operation(summary = "获取文件")
    public Mono<Void> read(@PathVariable String fileId,
                           ServerWebExchange exchange) {

        return exchange
            .getResponse()
            .writeWith(fileManager
                           .read(fileId, ctx -> {
                               List<HttpRange> ranges = exchange
                                   .getRequest()
                                   .getHeaders()
                                   .getRange();
                               long position = 0;
                               if (ranges.size() != 0) {
                                   position = ranges.get(0).getRangeStart(ctx.info().getLength());
                               }
                               ctx.position(position);
                               MediaType mediaType = ctx.info().mediaType();
                               exchange.getResponse().getHeaders().setContentType(mediaType);
                               exchange.getResponse().getHeaders().setContentLength(ctx.info().getLength());
                               //文件流时下载文件
                               if (mediaType.includes(MediaType.APPLICATION_OCTET_STREAM)) {
                                   exchange.getResponse().getHeaders().setContentDisposition(
                                       ContentDisposition
                                           .builder("attachment")
                                           .filename(ctx.info().getName(), StandardCharsets.UTF_8)
                                           .build()
                                   );
                               }
                               return Mono.empty();
                           }));
    }
}
