package cn.reghao.tnb.file.app.zoss.service;

import cn.reghao.jutil.jdk.converter.ByteConverter;
import cn.reghao.jutil.jdk.converter.ByteType;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.web.result.ResultStatus;
import cn.reghao.tnb.file.app.service.StoreConfigService;
import cn.reghao.tnb.oss.api.dto.ObjectChannel;
import cn.reghao.tnb.oss.api.constant.ObjectScope;
import cn.reghao.tnb.oss.api.constant.ObjectType;
import cn.reghao.tnb.common.util.ConstantId;
import cn.reghao.tnb.file.app.zoss.db.mapper.UploadChannelMapper;
import cn.reghao.tnb.file.app.zoss.db.repository.ChannelRepository;
import cn.reghao.file.api.constant.UploadChannelType;
import cn.reghao.tnb.file.app.zoss.model.dto.UploadChannelDto;
import cn.reghao.tnb.file.app.zoss.model.po.UploadChannel;
import cn.reghao.tnb.file.app.zoss.model.po.UserNode;
import cn.reghao.tnb.file.app.zoss.rpc.StoreServiceWrapper;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author reghao
 * @date 2024-02-23 15:14:53
 */
@Service
public class UploadChannelService {
    private final ByteConverter byteConverter;
    private final UploadChannelMapper uploadChannelMapper;
    private final UserNodeService userNodeService;
    private final StoreServiceWrapper storeServiceWrapper;
    private final StoreConfigService storeConfigService;
    private final ChannelRepository channelRepository;

    public UploadChannelService(ByteConverter byteConverter, UploadChannelMapper uploadChannelMapper,
                                UserNodeService userNodeService, StoreServiceWrapper storeServiceWrapper,
                                StoreConfigService storeConfigService, ChannelRepository channelRepository) {
        this.byteConverter = byteConverter;
        this.uploadChannelMapper = uploadChannelMapper;
        this.userNodeService = userNodeService;
        this.storeServiceWrapper = storeServiceWrapper;
        this.storeConfigService = storeConfigService;
        this.channelRepository = channelRepository;
    }

    public synchronized Result addObjectChannel(UploadChannelDto uploadChannelDto) throws Exception {
        long createBy = storeConfigService.getLocalOssUser();
        int userNodeId = uploadChannelDto.getUserNodeId();
        UserNode userNode = userNodeService.getUserNode(userNodeId);
        if (userNode == null) {
            return Result.fail(String.format("store_node with id %s not exist", userNodeId));
        }

        String channelPrefix = uploadChannelDto.getChannelPrefix();
        UploadChannel uploadChannel = uploadChannelMapper.findByCreateByAndPrefix(createBy, channelPrefix);
        if (uploadChannel != null) {
            return Result.fail(String.format("channel_prefix %s exist", channelPrefix));
        }

        int channelCode = getNextChannelCode(createBy);
        uploadChannel = new UploadChannel(channelCode, uploadChannelDto, (int) createBy);
        channelRepository.createUploadChannel(uploadChannel);
        return Result.success();
    }

    /**
     * 初始化系统中使用的 UploadChannel
     *
     * @param
     * @return
     * @date 2025-10-21 09:55:23
     */
    public void initUploadChannel() throws Exception {
        int ossUser = storeConfigService.getLocalOssUser();
        List<UserNode> list = userNodeService.getUserNodes(ossUser);
        if (list.size() == 1 && uploadChannelMapper.findByCreateBy(ossUser).isEmpty()) {
            int userNodeId = list.get(0).getId();
            for (UploadChannelType uploadChannelType : UploadChannelType.values()) {
                UploadChannel uploadChannel = new UploadChannel(userNodeId, uploadChannelType, ossUser);
                channelRepository.createUploadChannel(uploadChannel);
            }
        }
    }

    private int getNextChannelCode(long createBy) {
        int total = uploadChannelMapper.countByCreateBy(createBy);
        return ConstantId.START_CHANNEL_CODE + total;
    }

    public void updateChannelStatus(int id) {
        UploadChannel uploadChannel = uploadChannelMapper.findById(id);
        if (uploadChannel != null) {
            boolean enabled = uploadChannel.getEnabled();
            uploadChannel.setEnabled(!enabled);
            uploadChannelMapper.save(uploadChannel);
        }
    }

    public Result deleteChannel(int id) throws Exception {
        UploadChannel uploadChannel = uploadChannelMapper.findById(id);
        if (uploadChannel == null) {
            String errMsg = String.format("通道不存在");
            return Result.result(ResultStatus.FAIL, errMsg);
        }

        int channelCode = uploadChannel.getId();
        String prefix = uploadChannel.getPrefix();
        int ossUser = storeConfigService.getLocalOssUser();
        Integer total = storeServiceWrapper.countChannelObjects(channelCode, prefix, ossUser);
        if (total != null && total == 0) {
            storeServiceWrapper.deleteByObjectName(channelCode, prefix, ossUser);
            uploadChannelMapper.deleteById(id);
            return Result.result(ResultStatus.SUCCESS);
        }

        String errMsg = String.format("%s 通道中尚有对象存在", prefix);
        return Result.result(ResultStatus.FAIL, errMsg);
    }

    public List<UploadChannel> getChannelsByUserNode(int userNodeId) {
        long createBy = storeConfigService.getLocalOssUser();
        List<UploadChannel> list = uploadChannelMapper.findByCreateByAndUserNodeId(createBy, userNodeId);
        list.forEach(uploadChannel -> {
            String maxSizeStr = byteConverter.convert(ByteType.Bytes, uploadChannel.getMaxSize());
            uploadChannel.setMaxSizeStr(maxSizeStr);
            String fileTypeStr = ObjectType.getDescByCode(uploadChannel.getFileType());
            uploadChannel.setFileTypeStr(fileTypeStr);
            String scopeStr = ObjectScope.getByCode(uploadChannel.getScope()).name();
            uploadChannel.setScopeStr(scopeStr);
        });

        return list;
    }

    public List<UploadChannel> getUploadChannelsByCreateBy(long createBy) {
        return uploadChannelMapper.findByCreateBy(createBy);
    }

    public UploadChannel getByChannelCodeAndCreateBy(int channelCode, long createBy) {
        return uploadChannelMapper.findByCreateByAndChannelCode(createBy, channelCode);
    }

    public ObjectChannel getObjectChannelByChannelCode(int channelCode, long createBy) {
        UploadChannel uploadChannel = uploadChannelMapper.findByCreateByAndChannelCode(createBy, channelCode);
        if (uploadChannel == null) {
            return null;
        }

        int id = uploadChannel.getId();
        String channelPrefix = uploadChannel.getPrefix();
        long maxSize = uploadChannel.getMaxSize();
        int fileType = uploadChannel.getFileType();
        boolean setUrl = uploadChannel.getSetUrl();
        boolean setCallback = uploadChannel.getSetCallback();
        int scope = uploadChannel.getScope();

        UserNode userNode = userNodeService.getUserNode(uploadChannel.getUserNodeId());
        String domain = userNode.getDomain();
        return new ObjectChannel(id, channelCode, channelPrefix, maxSize, fileType,
                setUrl, setCallback, scope, domain, (int) createBy);
    }
}
