package nl.ovpay.queue;

import java.util.Map;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.impl.ForgivingExceptionHandler;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RabbitConnector {

    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitConnector.class);

    // TRIPS
    // SubscriptionId = 3e246de5-d3ad-468f-834b-1aaebf52244c
    // Use API 9853 to manually add xBOT to queue
    private static final String QUEUE_NAME = "BEID_3.TRIPS";
    private static final String USER_NAME = "BEID_3_TRIPS_HlTT";
    private static final String PASSWORD = "xJR4C8hIqhHQw0sn";

    // ALERTS
    // SubscriptionId = 17c8100b-88a2-4cef-b40d-8dca4f93d311
    // Use API 9853 to manually add xBOT to queue
    // private static final String QUEUE_NAME = "BEID_3.ALERTS";
    // private static final String USER_NAME = "BEID_3_ALERTS_nZs3";
    // private static final String PASSWORD = "VyubhPnczKgTB2zJ";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setVirtualHost("/");
        factory.setAutomaticRecoveryEnabled(true);
        factory.setPort(443);
        factory.setHost("not.sbx.idbt.translink.nl");
        factory.setUsername(USER_NAME);
        factory.setPassword(PASSWORD);
        factory.useSslProtocol("TLSv1.2");
        factory.setExceptionHandler(new ForgivingExceptionHandler());
        Map<String, Object> configs = factory.getClientProperties();
        LOGGER.info("Client properties: \n" + new JSONObject(configs).toString(2));

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        DeliverCallback deliverCallback = initDeliverCallback(channel);

        AMQP.Queue.DeclareOk queue = channel.queueDeclarePassive(QUEUE_NAME);
        LOGGER.info(
                "Declared queue: " + queue.getQueue() + ", consumer count: " + queue.getConsumerCount() + ", message count: " +
                queue.getMessageCount());

        // Second parameter controls autoAck - false = no autoAck = messages are only deleted from queue after consumer acknowledges them
        channel.basicConsume(queue.getQueue(), false, deliverCallback, consumerTag -> {});
        LOGGER.info("Waiting for messages from the queue. To exit press CTRL+C");
    }

    private static DeliverCallback initDeliverCallback(Channel channel) {
        return  (consumerTag, delivery) -> {
            final String message = new String(delivery.getBody(), "UTF-8");
            LOGGER.info("Received from message from the queue: \n " + new JSONObject(message).toString(2));

            LOGGER.info("Acknowledging message with delivery tag: " + delivery.getEnvelope().getDeliveryTag());
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            LOGGER.info("Successfully acknowledged message with delivery tag: " + delivery.getEnvelope().getDeliveryTag());

            if (QUEUE_NAME.equals("BEID_3.TRIPS")) {
                getTripDetails(message);
            } else if (QUEUE_NAME.equals("BEID_3.ALERTS")) {
                getAlertDetails(message);
            }
        };
    }

    private static void getAlertDetails(String message) {
        try {
            String alertId = Helpers.getAlertId(message);
            String xBot = Helpers.getXbot(message);
            String gboBearerToken = Helpers.getGboBearerToken();

            LOGGER.info("Getting alert details for xBOT {} and alertId {} via GBO API 8851...", xBot, alertId);
            Helpers.getAlertDetails(alertId, xBot, gboBearerToken);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void getTripDetails(String message) {
        try {
            String tripId = Helpers.getTripId(message);
            String xBot = Helpers.getXbot(message);
            String gboBearerToken = Helpers.getGboBearerToken();

            LOGGER.info("Getting trip details for xBOT {} and tripId {} via GBO API 8659...", xBot, tripId);
            Helpers.getTripDetails(tripId, xBot, gboBearerToken);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
