package com.bcxin.wps.service;

import cn.wps.solution.weboffice.provider.v3.exception.FileNotExist;
import cn.wps.solution.weboffice.provider.v3.exception.FileUploadNotComplete;
import cn.wps.solution.weboffice.provider.v3.model.DigestType;
import cn.wps.solution.weboffice.provider.v3.model.FileInfo;
import cn.wps.solution.weboffice.provider.v3.model.FileUploadMultiPhase;
import cn.wps.solution.weboffice.provider.v3.service.MultiPhaseFileStorageService;
import com.bcxin.wps.entity.File;
import com.bcxin.wps.entity.FileId;
import com.bcxin.wps.repository.FileRepository;
import com.bcxin.wps.entity.User;
import com.bcxin.wps.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class MultiPhaseFileStorageServiceImpl implements MultiPhaseFileStorageService {
    @Value("${weboffice.provider.host:http://localhost:8080}")
    private String host;

    @Autowired
    private PreviewServiceImpl previewService;
    @Autowired
    private FileRepository fileRepository;
    @Autowired
    private UserRepository userRepository;

    @Override
    public List<DigestType> uploadPrepare(String s) {
        return Collections.singletonList(DigestType.SHA1);
    }

    @Override
    public FileUploadMultiPhase.FileUploadAddress.Response uploadAddress(FileUploadMultiPhase.FileUploadAddress.Request request) {
        // TODO liangzuobin supports create new file, which no file id in request

        // ATTENTION
        // ConsoleController.upload() handle the upload request
        // and store the new content of file, and create a new version of file
        // without invoke uploadComplete method
        // it is not good in the real world
        return FileUploadMultiPhase.FileUploadAddress.Response.builder()
                .method(FileUploadMultiPhase.FileUploadAddress.Response.Method.PUT)
                .url(String.format("%s/console/upload/%s", host, request.getFileId()))
                .build();
    }

    @Override
    public FileInfo uploadComplete(FileUploadMultiPhase.FileUploadComplete.Request request) {
        // emm
        Optional<FileUploadMultiPhase.FileUploadComplete.UploadResponse> rp =
                Optional.ofNullable(request)
                        .map(FileUploadMultiPhase.FileUploadComplete.Request::getResponse)
                        .filter(r -> r.getStatus() == HttpStatus.OK.value());

        if (!rp.isPresent()) {
            throw new FileUploadNotComplete();
        }

        User user = previewService.fetchUserByToken();

        Timestamp lastModifyTime = Timestamp.valueOf(LocalDateTime.now());
        return Optional.ofNullable(previewService.fetchFile(request.getFileId()))
                .map(f -> f.copyForNew(String.valueOf(user.getId()), request.getRequest().getName(), f.getVersion() + 1))
                .map(f -> fileRepository.save(f))
                .map(File::toFileInfo)
                .orElseThrow(FileNotExist::new);
    }
}
