package cn.reghao.oss.web.app.service;

import cn.reghao.oss.api.dto.*;
import cn.reghao.oss.api.iface.ObjectService;
import cn.reghao.oss.api.iface.OssServerService;
import cn.reghao.oss.web.app.db.repository.StoreNodeRepository;
import cn.reghao.oss.web.app.db.repository.UploadChannelRepository;
import cn.reghao.oss.web.app.model.po.StoreNode;
import cn.reghao.oss.web.app.model.po.UploadChannel;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2024-02-23 09:22:53
 */
@Service
public class OssService {
    private final UploadChannelRepository uploadChannelRepository;
    private final StoreNodeRepository storeNodeRepository;

    public OssService(UploadChannelRepository uploadChannelRepository, StoreNodeRepository storeNodeRepository) {
        this.uploadChannelRepository = uploadChannelRepository;
        this.storeNodeRepository = storeNodeRepository;
    }

    public ServerInfo getServerInfo(int channelId) throws Exception {
        int userId = 1;
        UploadChannel uploadChannel = uploadChannelRepository.findByChannelIdAndCreateBy(channelId, userId);
        if (uploadChannel == null) {
            String errMsg = String.format("channel_id %s not exist", channelId);
            throw new Exception(errMsg);
        }

        String domain = uploadChannel.getBindDomain();
        String ossUrl = String.format("https://%s", domain);
        long maxSize = uploadChannel.getMaxSize();

        StoreNode storeNode = storeNodeRepository.findByDomain(domain);
        if (storeNode == null) {
            String errMsg = String.format("store_node %s not exist", domain);
            throw new Exception(errMsg);
        }

        String host = storeNode.getIpv4Addr();
        int port = storeNode.getRpcPort();
        RemoteService<OssServerService> remoteService = new RemoteService<>();
        OssServerService ossServerService = remoteService.getService(host, port, OssServerService.class);
        String token = ossServerService.getUploadToken(channelId);
        return new ServerInfo(ossUrl, channelId, maxSize, token);
    }

    public List<ObjectChannel> getObjectChannels(String nodeAddr) {
        StoreNode storeNode = storeNodeRepository.findByIpv4Addr(nodeAddr);
        if (storeNode == null) {
            return Collections.emptyList();
        }

        String domain = storeNode.getDomain();
        return uploadChannelRepository.findByBindDomain(domain).stream()
                .map(uploadChannel -> {
                    String name = uploadChannel.getDescription();
                    long maxSize = uploadChannel.getMaxSize();
                    String channelPrefix = uploadChannel.getPrefix();
                    String contentType = uploadChannel.getContentType();
                    return new ObjectChannel(name, channelPrefix, maxSize, contentType, domain);
                })
                .collect(Collectors.toList());
    }

    public ObjectChannel getObjectChannel(String nodeAddr, int channelId) {
        StoreNode storeNode = storeNodeRepository.findByIpv4Addr(nodeAddr);
        if (storeNode == null) {
            return null;
        }

        String domain = storeNode.getDomain();
        UploadChannel uploadChannel = uploadChannelRepository.findByBindDomainAndChannelId(domain, channelId);
        if (uploadChannel == null) {
            return null;
        }

        String name = uploadChannel.getDescription();
        String channelPrefix = uploadChannel.getPrefix();
        long maxSize = uploadChannel.getMaxSize();
        String contentType = uploadChannel.getContentType();
        return new ObjectChannel(name, channelPrefix, maxSize, contentType, domain);
    }

    public ObjectInfo getObjectInfo(String objectId) {
        RemoteService<ObjectService> remoteService = new RemoteService<>();
        String host = "";
        int port = -1;
        ObjectService objectService = remoteService.getService(host, port, ObjectService.class);
        return objectService.getObjectInfo(objectId);
    }

    public DownloadUrl getDownloadUrl(String objectId, int channelId, long userId) {
        RemoteService<ObjectService> remoteService = new RemoteService<>();
        String host = "";
        int port = -1;
        ObjectService objectService = remoteService.getService(host, port, ObjectService.class);
        return objectService.getDownloadUrl(objectId, channelId, userId);
    }

    public void putObjectPrefix(ObjectPrefix objectPrefix) {
    }

    public List<String> getObjectPrefix() {
        return Collections.emptyList();
    }

    public ObjectMeta getObject(String objectName) {
        return null;
    }

    public ObjectUrl getObjectUrl(String objectId) {
        return null;
    }
}
