package com.caliverse.admin.domain.RabbitMq;

import com.caliverse.admin.domain.RabbitMq.message.ServerMessage;
import com.caliverse.admin.global.common.code.CommonCode;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.exception.RestApiException;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.JsonFormat;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Instant;
import java.util.Objects;
import java.util.concurrent.TimeoutException;

@Slf4j
@Service
public class RabbitMqService {

    private final Connection m_rabbitMq;

    public RabbitMqService(Connection rabbitMqConnection) {
        this.m_rabbitMq = rabbitMqConnection;
    }

    // Send ServerMessage to GameServer

    public void SendMessage(com.google.protobuf.GeneratedMessageV3 message, String destServer) {
        try {
            Channel channel = m_rabbitMq.createChannel();
            var server_message_builder = ServerMessage.newBuilder();
            server_message_builder.setMessageTime(getCurrentTimestamp());
            server_message_builder.setMessageSender("AdminTool");

            for(var descriptor : ServerMessage.getDescriptor().getOneofs().get(0).getFields())
            {
                if(!Objects.equals(descriptor.getMessageType().getName(), message.getDescriptorForType().getName())) continue;
                server_message_builder.setField(descriptor, message);
                break;
            }

            String send = JsonFormat.printer().print(server_message_builder);
            channel.queueDeclare(destServer, true, false, true, null);
            channel.basicPublish("", destServer, null, send.getBytes());

        }
        catch (InvalidProtocolBufferException e) {
            log.error("InvalidProtocolBufferException message: {}, destServer: {}, e.Message : {}", message.toString(), destServer, e.getMessage());
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.EXCEPTION_INVALID_PROTOCOL_BUFFER_EXCEPTION_ERROR.getMessage());
        }
        catch (IOException e) {
            log.error("IOException message: {}, destServer: {}, e.Message : {}", message.toString(), destServer, e.getMessage());
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.EXCEPTION_IO_EXCEPTION_ERROR.getMessage());
        }
    }

    private Timestamp getCurrentTimestamp()
    {
        var current = Instant.now();

        return Timestamp.newBuilder().setSeconds(current.getEpochSecond())
                .setNanos(current.getNano()).build();
    }

    // Consumer 등록 : 현재는 운영툴 Backend 가 ServerMessage 를 받을 필요가 없다.
    /*public void startConsumer() throws IOException, TimeoutException
    {
        if(!m_rabbitMq.isOpen())
        {
            return;
        }

        try(Channel channel = m_rabbitMq.createChannel())
        {
            channel.queueDeclare(m_server_name, true, false, true, null);
            channel.basicConsume(m_server_name, true, deliveryCallback, consumerTag -> { });
        }
    }

    private final DeliverCallback deliveryCallback = (consumerTag, delivery) ->
    {
        String message = new String(delivery.getBody());
        logger.info("Received message: {}", message);
    };*/
}
