package cn.reghao.oss.store.controller;

import cn.reghao.oss.storeapi.dto.ObjectChannel;
import cn.reghao.oss.store.model.vo.ObjectProp;
import cn.reghao.oss.store.model.vo.ObjectResult;
import cn.reghao.oss.store.service.*;
import cn.reghao.oss.store.util.JwtUtil;
import cn.reghao.jutil.jdk.result.Result;
import cn.reghao.jutil.jdk.result.WebResult;
import cn.reghao.jutil.jdk.security.DigestUtil;
import cn.reghao.jutil.web.ServletUtil;
import cn.reghao.oss.storeapi.dto.OssPayload;
import cn.reghao.oss.storeapi.rest.UploadFileRet;
import cn.reghao.oss.store.util.UserContext;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.UUID;

/**
 * @author reghao
 * @date 2023-05-19 16:20:12
 */
@RestController
public class ObjectUploadController {
    private final ChannelValidateService channelValidateService;
    private final FileStoreService fileStoreService;
    private final ObjectNameService objectNameService;
    private final PutObjectService putObjectService;
    private final StoreLocalService storeLocalService;

    public ObjectUploadController(ChannelValidateService channelValidateService, FileStoreService fileStoreService,
                                  ObjectNameService objectNameService, PutObjectService putObjectService,
                                  StoreLocalService storeLocalService) {
        this.channelValidateService = channelValidateService;
        this.fileStoreService = fileStoreService;
        this.objectNameService = objectNameService;
        this.putObjectService = putObjectService;
        this.storeLocalService = storeLocalService;
    }

    @PutMapping(value = "/**")
    public String putObject(@RequestBody File file) {
        return WebResult.failWithMsg("not implement");
    }

    @PostMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> postObject(MultipartFile file, Integer channelId, String objectName,
                                             String client, String sha256sum) throws Exception {
        /* permission check */
        String token = ServletUtil.getBearerToken();
        if (token == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(WebResult.failWithMsg("no token in request"));
        }

        String secretKey = storeLocalService.getSecretKey();
        OssPayload ossPayload = JwtUtil.getOssPayload(token, secretKey);
        String action = ossPayload.getAction();
        if (!"upload".equals(action)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(WebResult.failWithMsg("it's not upload token"));
        }

        int channelId1 = ossPayload.getChannelId();
        if (channelId != channelId1) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(WebResult.failWithMsg("channel not match in token"));
        }

        int loginUser = ossPayload.getUserId();
        ObjectChannel objectChannel = storeLocalService.getChannelByChannelId(loginUser, channelId);
        if (objectChannel == null) {
            String errMsg = String.format("channel validate failed, channel %s not exist", channelId);
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(WebResult.failWithMsg(errMsg));
        }

        int userId1 = ossPayload.getUserId();
        UserContext context = new UserContext(userId1);

        /* channel validate */
        String contentId = UUID.randomUUID().toString().replace("-", "");
        long size = file.getSize();
        File savedFile = fileStoreService.saveFile(file.getInputStream(), contentId, size);
        Result result = channelValidateService.validateFile(savedFile, objectChannel);
        if (result.getCode() != 0) {
            FileUtils.deleteQuietly(savedFile);
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(WebResult.result(result));
        }

        /* store file */
        String sha256sum1 = sha256sum;
        if (sha256sum1 == null) {
            sha256sum1 = DigestUtil.sha256sum(savedFile.getAbsolutePath());
        }

        String filename = file.getOriginalFilename();
        if (filename == null) {
            filename = "";
        }

        ObjectProp objectProp = objectNameService.getObjectProp(objectChannel, filename);
        ObjectResult objectResult = putObjectService.putObject(objectProp, contentId, savedFile, filename, sha256sum1);
        String objectId = objectResult.getObjectId();
        String objectUrl = objectNameService.getObjectUrl(objectResult.getObjectName());
        UploadFileRet uploadFileRet;
        if (objectChannel.getSeturl()) {
            uploadFileRet = new UploadFileRet(objectId, objectUrl);
        } else {
            uploadFileRet = new UploadFileRet(objectId);
        }

        return ResponseEntity.status(HttpStatus.OK).body(WebResult.success(uploadFileRet));
    }

    @DeleteMapping(value = "/")
    public ResponseEntity<String> deleteObject(String objectId) {
        //putObjectService.deleteObject(objectId);
        return ResponseEntity.ok().build();
    }
}
