package com.github.xabgesagtx.bots;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.api.methods.updates.SetWebhook;
import org.telegram.telegrambots.meta.api.objects.InputFile;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.generics.BotSession;
import org.telegram.telegrambots.meta.generics.LongPollingBot;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import org.telegram.telegrambots.updatesreceivers.DefaultWebhook;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;

/**
 * Auto configuration for telegram bots to automatically start bots that are configured as beans.
 */
@Configuration
@Slf4j
@ConditionalOnClass(TelegramBotsApi.class)
@RequiredArgsConstructor
@Import(TelegramProperties.class)
public class TelegramBotAutoConfiguration {

	private List<BotSession> sessions = new ArrayList<>();

	private final List<LongPollingBot> pollingBots;
	private final List<TelegramWebhookBotService> webHookBots;
	private final TelegramProperties properties;
	private SetWebhook.SetWebhookBuilder webhookBuilder;

	@PostConstruct
	public void start() throws TelegramApiException {
		log.info("Starting auto config for telegram bots");
		webhookBuilder = SetWebhook.builder();
		TelegramBotsApi api = telegramBotsApi();
		pollingBots.forEach(bot -> {
			try {
				log.info("Registering polling bot: {}", bot.getBotUsername());
				sessions.add(api.registerBot(bot));
			} catch (TelegramApiException e) {
				log.error("Failed to register bot {} due to error", bot.getBotUsername(), e);
			}
		});
		webHookBots.forEach(bot -> {
			try {
				log.info("Registering web hook bot: {}", bot.getBotUsername());
				SetWebhook webhook = bot.customizeWebHook(webhookBuilder).build();
				api.registerBot(bot, webhook);
			} catch (TelegramApiException e) {
				log.error("Failed to register bot {} due to error", bot.getBotUsername(), e);
			}
		});
	}

	/**
	 * Get API object depending on configured properties.
	 * If no properties are configured, the API object won't support webhooks.
	 *
	 * @return api object
	 * @throws TelegramApiRequestException in case the creation of the API object fails
	 */
	@Bean
	@ConditionalOnMissingBean
	public TelegramBotsApi telegramBotsApi() throws TelegramApiException {
		TelegramBotsApi result;
		if (properties.hasKeyStoreWithPath()) {
			log.info("Initializing API with webhook support and configured keystore and path to certificate");
			webhookBuilder.certificate(new InputFile(properties.getPathToCertificate()));
			webhookBuilder.url(properties.getExternalUrl());
			DefaultWebhook webhook = getWebhookConfig(properties);
			result = new TelegramBotsApi(DefaultBotSession.class, webhook);
		} else if (properties.hasKeyStore()) {
			log.info("Initializing API with webhook support and configured keystore");
			webhookBuilder.url(properties.getExternalUrl());
			DefaultWebhook webhook = getWebhookConfig(properties);
			result = new TelegramBotsApi(DefaultBotSession.class, webhook);
		} else if (properties.hasUrls()) {
			log.info("Initializing API with webhook support");
			webhookBuilder.url(properties.getExternalUrl());
			DefaultWebhook webhook = getWebhookConfig(properties);
			result = new TelegramBotsApi(DefaultBotSession.class, webhook);
		} else {
			log.info("Initializing API without webhook support");
			result = new TelegramBotsApi(DefaultBotSession.class);
		}
		return result;
	}

	private DefaultWebhook getWebhookConfig(TelegramProperties properties) throws TelegramApiException {
		DefaultWebhook webhook = new DefaultWebhook();
		if (properties.hasKeyStoreWithPath()) {
			webhook.setKeyStore(properties.getKeyStore(), properties.getKeyStorePassword());
		}
		webhook.setInternalUrl(properties.getInternalUrl());
		return webhook;
	}

	@PreDestroy
	public void stop() {
		sessions.forEach(session -> {
			if (session != null) {
				session.stop();
			}
		});
	}

}

@@ -553,16 +553,104 @@
 ebhook;%0A
+import org.telegram.telegrambots.meta.api.methods.updates.SetWebhook.SetWebhookBuilder;%0A
 import o
@@ -1726,62 +1726,8 @@
 ies;
-%0A%09private SetWebhook.SetWebhookBuilder webhookBuilder;
 %0A%0A%09@
@@ -1849,49 +1849,8 @@
 %22);%0A
-%09%09webhookBuilder = SetWebhook.builder();%0A
 %09%09Te
@@ -2280,34 +2280,121 @@
 ;%0A%09%09%09%09SetWebhook
- w
+.SetWebhookBuilder webhookBuilder = createWebhookBuilder();%0A%09%09%09%09SetWebhook botCustomizedW
 ebhook = bot.cus
@@ -2457,17 +2457,30 @@
 ot(bot, 
-w
+botCustomizedW
 ebhook);
@@ -2615,16 +2615,479 @@
 %7D);%0A%09%7D%0A%0A
+%09private SetWebhookBuilder createWebhookBuilder() %7B%0A%09%09SetWebhook.SetWebhookBuilder builder = SetWebhook.builder();%0A%09%09if (properties.hasKeyStoreWithPath()) %7B%0A%09%09%09InputFile certificatePath = new InputFile(properties.getPathToCertificate());%0A%09%09%09builder.certificate(certificatePath);%0A%09%09%09builder.url(properties.getExternalUrl());%0A%09%09%7D else if (properties.hasKeyStore() %7C%7C properties.hasUrls()) %7B%0A%09%09%09builder.url(properties.getExternalUrl());%0A%09%09%7D%0A%09%09return builder;%0A    %7D%0A%0A
 %09/**%0A%09 *
@@ -3611,141 +3611,8 @@
 %22);%0A
-%09%09%09webhookBuilder.certificate(new InputFile(properties.getPathToCertificate()));%0A%09%09%09webhookBuilder.url(properties.getExternalUrl());%0A
 %09%09%09D
@@ -3855,60 +3855,8 @@
 %22);%0A
-%09%09%09webhookBuilder.url(properties.getExternalUrl());%0A
 %09%09%09D
@@ -4071,60 +4071,8 @@
 %22);%0A
-%09%09%09webhookBuilder.url(properties.getExternalUrl());%0A
 %09%09%09D

create webhook builder per bot