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

import cn.reghao.oss.api.constant.ChannelAction;
import cn.reghao.oss.api.dto.*;
import cn.reghao.oss.api.util.JwtUtil;
import cn.reghao.oss.console.app.model.po.StoreNode;
import cn.reghao.oss.console.app.model.po.UploadChannel;
import cn.reghao.oss.console.app.model.po.UserNode;
import cn.reghao.oss.console.app.service.StoreNodeService;
import cn.reghao.oss.console.app.service.UploadChannelService;
import cn.reghao.oss.api.iface.ConsoleService;
import cn.reghao.oss.console.app.service.UserNodeService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author reghao
 * @date 2024-07-02 10:58:51
 */
@DubboService
@Service
public class ConsoleServiceImpl implements ConsoleService {
    private final UploadChannelService uploadChannelService;
    private final StoreNodeService storeNodeService;
    private final UserNodeService userNodeService;

    public ConsoleServiceImpl(UploadChannelService uploadChannelService, StoreNodeService storeNodeService,
                              UserNodeService userNodeService) {
        this.uploadChannelService = uploadChannelService;
        this.storeNodeService = storeNodeService;
        this.userNodeService = userNodeService;
    }

    @Override
    public void registerNode(StoreNodeDto storeNodeDto) {
        storeNodeService.addOrUpdate(storeNodeDto);
    }

    @Override
    public NodeProperties getNodeProperties(int owner, String nodeAddress) {
        StoreNode storeNode = storeNodeService.getByNodeAddr(nodeAddress);
        if (storeNode != null) {
            int nodeId = storeNode.getId();
            UserNode userNode = userNodeService.getUserNode(nodeId, owner);
            if (userNode != null) {
                return new NodeProperties(userNode.getDomain(), userNode.getSecretKey(), userNode.getReferer());
            }
        }

        return null;
    }

    @Override
    public ServerInfo getUploadStore(int loginUser, int channelId) {
        UploadChannel uploadChannel = uploadChannelService.getByChannelIdAndCreateBy(channelId, loginUser);
        if (uploadChannel == null) {
            String errMsg = String.format("channel_id %s not exist", channelId);
            return null;
        }

        UserNode userNode = userNodeService.getUserNode(uploadChannel.getNodeId(), loginUser);
        if (userNode == null) {
            String errMsg = String.format("channel_id %s not associate with any store_node", channelId);
            return null;
        }

        String domain = userNode.getDomain();
        String ossUrl = String.format("//%s", domain);
        long maxSize = uploadChannel.getMaxSize();

        String secretKey = userNode.getSecretKey();
        String action = ChannelAction.upload.getName();
        long expireAt = System.currentTimeMillis() + 3600*1000;
        OssPayload ossPayload = new OssPayload(action, channelId, loginUser);
        String uploadToken = JwtUtil.createToken(ossPayload, expireAt, secretKey);
        return new ServerInfo(ossUrl, channelId, maxSize, uploadToken);
    }

    @Override
    public ObjectChannel getChannelById(int owner, int channelId) {
        return uploadChannelService.getObjectChannelByChannelId(channelId, owner);
    }

    @Override
    public int getChannelIdByUrl(int loginUser, String url) {
        List<UserNode> list = userNodeService.getByUserId(loginUser);
        List<UploadChannel> uploadChannels = new ArrayList<>();
        for (UserNode userNode : list) {
            int nodeId = userNode.getNodeId();
            uploadChannels.addAll(uploadChannelService.getByNodeIdAndUserId(nodeId, loginUser));
        }

        int idx = url.indexOf("/");
        String objectName = url.substring(idx);
        for (UploadChannel uploadChannel : uploadChannels) {
            if (objectName.startsWith(uploadChannel.getPrefix())) {
                return uploadChannel.getChannelId();
            }
        }

        return 0;
    }

    @Override
    public int getChannelScope(int channelId) {
        int createBy = 1;
        ObjectChannel objectChannel = uploadChannelService.getObjectChannelByChannelId(channelId, createBy);
        return objectChannel != null ? objectChannel.getScope() : -1;
    }
}
