package org.framework.lazy.cloud.network.heartbeat.server.standalone.application.impl;


import io.netty.channel.Channel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.ChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.constant.TcpMessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyClientVisitorContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.server.netty.tcp.socket.NettyTcpServerPermeateClientVisitorSocket;
import org.framework.lazy.cloud.network.heartbeat.server.properties.ServerNodeProperties;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.LazyNettyClientStateApplication;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.assembler.NettyClientStateDTOAssembler;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.command.lazy.netty.client.state.*;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.dto.LazyNettyClientStateDTO;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.application.dto.LazyNettyClientStateGroupByClientDTO;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.domain.model.lazy.netty.client.state.LazyNettyClientState;
import org.framework.lazy.cloud.network.heartbeat.server.standalone.domain.model.lazy.netty.client.state.LazyNettyClientStateRepository;
import org.wu.framework.core.utils.ObjectUtils;
import org.wu.framework.database.lazy.web.plus.stereotype.LazyApplication;
import org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyApplicationImpl;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
import org.wu.framework.web.response.Result;
import org.wu.framework.web.response.ResultFactory;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;

/**
 * describe 客户端状态
 *
 * @author Jia wei Wu
 * @date 2023/12/27 03:46 下午
 * @see DefaultDDDLazyApplicationImpl
 **/
@Slf4j
@LazyApplication
public class LazyNettyClientStateApplicationImpl implements LazyNettyClientStateApplication {

    @Resource
    LazyNettyClientStateRepository lazyNettyClientStateRepository;
    @Resource
    ServerNodeProperties serverNodeProperties;

    /**
     * describe 新增客户端状态
     *
     * @param lazyNettyClientStateStoryCommand 新增客户端状态
     * @return {@link Result<  LazyNettyClientState  >} 客户端状态新增后领域对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<LazyNettyClientState> story(LazyNettyClientStateStoryCommand lazyNettyClientStateStoryCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateStoryCommand);

        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.story(lazyNettyClientState);
    }

    /**
     * describe 批量新增客户端状态
     *
     * @param lazyNettyClientStateStoryCommandList 批量新增客户端状态
     * @return {@link Result<List< LazyNettyClientState >>} 客户端状态新增后领域对象集合
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<List<LazyNettyClientState>> batchStory(List<LazyNettyClientStateStoryCommand> lazyNettyClientStateStoryCommandList) {
        List<LazyNettyClientState> lazyNettyClientStateList = lazyNettyClientStateStoryCommandList
                .stream()
                .map(lazyNettyClientStateStoryCommand -> {
                    LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateStoryCommand);
                    String serverId = serverNodeProperties.getNodeId();
                    lazyNettyClientState.setServerId(serverId);
                    return lazyNettyClientState;
                })
                .collect(Collectors.toList());
        return lazyNettyClientStateRepository.batchStory(lazyNettyClientStateList);
    }

    /**
     * describe 更新客户端状态
     *
     * @param lazyNettyClientStateUpdateCommand 更新客户端状态
     * @return {@link Result< LazyNettyClientState >} 客户端状态领域对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<LazyNettyClientState> updateOne(LazyNettyClientStateUpdateCommand lazyNettyClientStateUpdateCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateUpdateCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.story(lazyNettyClientState);
    }

    /**
     * describe 查询单个客户端状态
     *
     * @param lazyNettyClientStateQueryOneCommand 查询单个客户端状态
     * @return {@link Result< LazyNettyClientStateDTO >} 客户端状态DTO对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<LazyNettyClientStateDTO> findOne(LazyNettyClientStateQueryOneCommand lazyNettyClientStateQueryOneCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateQueryOneCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.findOne(lazyNettyClientState).convert(NettyClientStateDTOAssembler.INSTANCE::fromNettyClientState);
    }

    /**
     * describe 查询多个客户端状态
     *
     * @param lazyNettyClientStateQueryListCommand 查询多个客户端状态
     * @return {@link Result<List< LazyNettyClientStateDTO >>} 客户端状态DTO对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<List<LazyNettyClientStateDTO>> findList(LazyNettyClientStateQueryListCommand lazyNettyClientStateQueryListCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateQueryListCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.findList(lazyNettyClientState).convert(nettyClientStates -> nettyClientStates.stream().map(NettyClientStateDTOAssembler.INSTANCE::fromNettyClientState).collect(Collectors.toList()));
    }

    /**
     * describe 分页查询多个客户端状态
     *
     * @param lazyNettyClientStateQueryListCommand 分页查询多个客户端状态
     * @return {@link Result<LazyPage< LazyNettyClientStateDTO >>} 分页客户端状态DTO对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<LazyPage<LazyNettyClientStateDTO>> findPage(int size, int current, LazyNettyClientStateQueryListCommand lazyNettyClientStateQueryListCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateQueryListCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.findPage(size, current, lazyNettyClientState).convert(page -> page.convert(NettyClientStateDTOAssembler.INSTANCE::fromNettyClientState));
    }

    /**
     * describe 查询多个客户端状态
     *
     * @param lazyNettyClientStateQueryListCommand 查询多个客户端状态
     * @return {@link Result <List<LazyNettyClientStateDTO>>} 客户端状态DTO对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/
    @Override
    public Result<List<LazyNettyClientStateGroupByClientDTO>> findListGroupByClient(LazyNettyClientStateQueryListCommand lazyNettyClientStateQueryListCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateQueryListCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.findListGroupByClient(lazyNettyClientState).convert(nettyClientStates -> nettyClientStates.stream().map(NettyClientStateDTOAssembler.INSTANCE::fromNettyClientState).collect(Collectors.toList()));

    }

    /**
     * describe 分页查询多个客户端状态
     *
     * @param size
     * @param current
     * @param lazyNettyClientStateQueryListCommand 分页查询多个客户端状态
     * @return {@link Result <LazyPage<LazyNettyClientStateDTO>>} 分页客户端状态DTO对象
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/
    @Override
    public Result<LazyPage<LazyNettyClientStateGroupByClientDTO>> findPageGroupByClient(int size, int current, LazyNettyClientStateQueryListCommand lazyNettyClientStateQueryListCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateQueryListCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        return lazyNettyClientStateRepository.findPageGroupByClient(size, current, lazyNettyClientState).convert(page -> page.convert(NettyClientStateDTOAssembler.INSTANCE::fromNettyClientState));
    }

    /**
     * describe 删除客户端状态
     *
     * @param lazyNettyClientStateRemoveCommand 删除客户端状态
     * @return {@link Result< LazyNettyClientState >} 客户端状态
     * @author Jia wei Wu
     * @date 2023/12/27 03:46 下午
     **/

    @Override
    public Result<LazyNettyClientState> remove(LazyNettyClientStateRemoveCommand lazyNettyClientStateRemoveCommand) {
        LazyNettyClientState lazyNettyClientState = NettyClientStateDTOAssembler.INSTANCE.toNettyClientState(lazyNettyClientStateRemoveCommand);
        String serverId = serverNodeProperties.getNodeId();
        lazyNettyClientState.setServerId(serverId);
        // 获取当前客户端通道 而后关闭
        String clientId = lazyNettyClientStateRemoveCommand.getClientId();
        // 心跳关闭
        ChannelContext.clear(clientId);
        // 关闭访客
        List<NettyTcpServerPermeateClientVisitorSocket> nettyTcpServerPermeateClientVisitorSocketList = NettyClientVisitorContext.getVisitorSockets(clientId);
        if (!ObjectUtils.isEmpty(nettyTcpServerPermeateClientVisitorSocketList)) {
            for (NettyTcpServerPermeateClientVisitorSocket nettyTcpServerPermeateClientVisitorSocket : nettyTcpServerPermeateClientVisitorSocketList) {
                nettyTcpServerPermeateClientVisitorSocket.close();
            }
        }
        NettyClientVisitorContext.removeVisitorSockets(clientId);
        return lazyNettyClientStateRepository.remove(lazyNettyClientState);
    }

    /**
     * 通过客户端心跳通道发送客户端请求
     *
     * @param lazyNettyClientMessageCommand 发送请求到客户端
     * @return {@link Result<Void>}
     */
    @Override
    public Result<Void> sendMessage2HeartbeatClient(LazyNettyClientMessageCommand lazyNettyClientMessageCommand) {
        // 获取客户端ID
        String clientId = lazyNettyClientMessageCommand.getClientId();
        String message = lazyNettyClientMessageCommand.getMessage();
        Channel clientChannel = ChannelContext.getLoadBalance(clientId);
        if (clientChannel == null) {
            return ResultFactory.errorOf("客户端：" + clientId + "不存在");
        }
        // 发送消息到客户端
        NettyProxyMsg nettyProxyMsg = new NettyProxyMsg();
        nettyProxyMsg.setClientId("服务端");
        nettyProxyMsg.setData(message.getBytes(StandardCharsets.UTF_8));
        nettyProxyMsg.setType(TcpMessageType.TCP_DISTRIBUTE_SINGLE_CLIENT_MESSAGE);
        clientChannel.writeAndFlush(nettyProxyMsg);
        return ResultFactory.successOf();
    }
}