package cn.reghao.oss.console.app.rpc;

import cn.reghao.oss.console.app.model.dto.ObjectsScopeDto;
import cn.reghao.oss.console.app.model.po.StoreNode;
import cn.reghao.oss.console.app.model.po.UploadChannel;
import cn.reghao.oss.console.app.service.UploadChannelService;
import cn.reghao.oss.console.util.AuthKeyContext;
import cn.reghao.oss.storeapi.dto.ObjectInfo;
import cn.reghao.oss.storeapi.iface.ObjectService;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author reghao
 * @date 2024-02-29 14:27:03
 */
@Service
public class OssObjectService {
    private final UploadChannelService uploadChannelService;

    public OssObjectService(UploadChannelService uploadChannelService) {
        this.uploadChannelService = uploadChannelService;
    }

    public void setObjectsScope(ObjectsScopeDto objectsScopeDto) throws Exception {
        int channelId = objectsScopeDto.getChannelId();
        ObjectService objectService = getObjectService(channelId);
        int scope = objectsScopeDto.getScope();
        List<String> objectIds = objectsScopeDto.getObjectIds();
        objectService.setObjectsScope(scope, objectIds);
    }

    public void deleteByObjectIds(int channelId, List<String> objectIds) throws Exception {
        ObjectService objectService = getObjectService(channelId);
        objectService.deleteByObjectIds(objectIds);
    }

    public void deleteByObjectUrl(String objectUrl) throws Exception {
        int loginUser = AuthKeyContext.getUser();
        String domain = objectUrl.replace("//", "").split("/")[0];
        String objectName = objectUrl.replace("//" + domain + "/", "");
        List<UploadChannel> uploadChannels = uploadChannelService.getByDomainAndCreateBy(domain, loginUser);
        for (UploadChannel uploadChannel : uploadChannels) {
            String prefix = uploadChannel.getPrefix();
            // TODO get best match
            if (objectName.startsWith(prefix)) {
                int channelId = uploadChannel.getChannelId();
                ObjectService objectService = getObjectService(channelId);
                objectService.deleteByObjectName(objectName);
                return;
            }
        }

        String errMsg = String.format("%s not associate with any channels", objectUrl);
        throw new Exception(errMsg);
    }

    public String getSignedUrl(int channelId, String objectId) throws Exception {
        ObjectService objectService = getObjectService(channelId);
        int loginUser = AuthKeyContext.getUser();
        int expireSecond = 3600;
        return objectService.getSignedUrl(loginUser, objectId, expireSecond);
    }

    public ObjectInfo getObjectInfo(int channelId, String objectId) throws Exception {
        ObjectService objectService = getObjectService(channelId);
        int loginUser = AuthKeyContext.getUser();
        int expireSecond = 3600;
        return objectService.getObjectInfo(loginUser, objectId, expireSecond);
    }

    private ObjectService getObjectService(int channelId) throws Exception {
        StoreNode storeNode = uploadChannelService.getStoreNodeByChannelId(channelId);
        if (storeNode == null) {
            String errMsg = String.format("channel_id %s not associate with any store_node", channelId);
            throw new Exception(errMsg);
        }

        RemoteService<ObjectService> remoteService = new RemoteService<>();
        String host = storeNode.getNodeAddr();
        int port = storeNode.getRpcPort();
        return remoteService.getService(host, port, ObjectService.class);
    }
}
