import { REQUIRED_ENV } from '../server';

type WebhookConfig = {
	url: string;
	enabled: boolean;
	webhook_by_events: boolean;
	webhook_base64: boolean;
	events: string[];
};

type WebhookResponse = {
	webhook: {
		instanceName: string;
		webhook: {
			url: string;
			events: string[];
			enabled: boolean;
		};
	};
};

export class WebhookManager {
	private static readonly REQUIRED_EVENTS = [
		'APPLICATION_STARTUP',
		'MESSAGES_UPSERT',
		'GROUPS_UPSERT',
		'MESSAGES_UPDATE',
		'MESSAGES_DELETE',
		'PRESENCE_UPDATE',
		'CONTACTS_UPDATE',
		'CHATS_UPDATE'
	];

	private static validateConfig() {
		// Solo requerimos aquí las vars necesarias para registrar/verificar el webhook.
		// Excluimos CHATBOT_PHONE_NUMBER para que los tests unitarios de validación no fallen.
		const missing = REQUIRED_ENV
			.filter(v => v !== 'CHATBOT_PHONE_NUMBER')
			.filter(v => !process.env[v]);
		if (missing.length) {
			throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
		}

		if (!process.env.WEBHOOK_URL?.trim()) {
			throw new Error('WEBHOOK_URL environment variable is required and cannot be empty');
		}

		try {
			const url = new URL(process.env.WEBHOOK_URL);
			
			// Enhanced internal Docker URL validation
			if (process.env.WEBHOOK_URL.startsWith('http://srv-captain--')) {
				if (!url.port) {
					console.warn('Internal Docker URL missing port number - this may cause connection issues');
				}
			}
			
			// Allow internal docker URLs in production
			if (process.env.NODE_ENV === 'production') {
				const isOk = (url.protocol === 'http:' || url.protocol === 'https:') || process.env.WEBHOOK_URL.startsWith('http://srv-captain--');
				if (!isOk) {
					console.warn('Production WEBHOOK_URL should use http/https or internal docker URL');
				}
			} else if (!(url.protocol === 'http:' || url.protocol === 'https:')) {
				throw new Error('WEBHOOK_URL must use http or https protocol');
			}
		} catch (e) {
			throw new Error(`Invalid WEBHOOK_URL: ${e.message}`);
		}
	}

	private static getConfig(): { webhook: WebhookConfig } {
		const fromEnv = String(process.env.WEBHOOK_EVENTS || '')
			.split(',')
			.map(s => s.trim())
			.filter(Boolean);
		const allow = [
			'APPLICATION_STARTUP',
			'MESSAGES_UPSERT',
			'GROUPS_UPSERT',
			'MESSAGES_UPDATE',
			'MESSAGES_DELETE',
			'PRESENCE_UPDATE',
			'CONTACTS_UPDATE',
			'CHATS_UPDATE'
		];
		const events = (fromEnv.length ? fromEnv : ['APPLICATION_STARTUP','MESSAGES_UPSERT','GROUPS_UPSERT'])
			.filter(e => allow.includes(e));
		return {
			webhook: {
				url: process.env.WEBHOOK_URL!,
				enabled: true,
				webhook_by_events: true,
				webhook_base64: true,
				events
			}
		};
	}

	private static getApiUrl(): string {
		return `${process.env.EVOLUTION_API_URL}/webhook/set/${process.env.EVOLUTION_API_INSTANCE}`;
	}

	private static getHeaders(): HeadersInit {
		return {
			apikey: process.env.EVOLUTION_API_KEY!,
			'Content-Type': 'application/json',
		};
	}

	static async registerWebhook(): Promise<WebhookResponse> {
		this.validateConfig();

		// First test if our own endpoint is reachable
		const endpointTest = await this.testWebhookEndpoint();
		if (!endpointTest) {
			throw new Error('Webhook endpoint test failed - check your server logs');
		}

		const config = this.getConfig();
		const apiUrl = this.getApiUrl();

		const logSafeUrl = (url: string) => url ? `${url.substring(0, 20)}...` : 'invalid-url';

		console.log('ℹ️ Attempting to register webhook:', {
			apiUrl,
			config: {
				...config,
				webhook: {
					...config.webhook,
					url: logSafeUrl(config.webhook.url),
					events: config.webhook.events
				}
			}
		});

		const response = await fetch(apiUrl, {
			method: 'POST',
			headers: this.getHeaders(),
			body: JSON.stringify(config),
		});

		if (!response.ok) {
			let errorDetails = response.statusText;
			try {
				const errorBody = await response.text();
				errorDetails += ` - ${errorBody}`;
			} catch { }
			throw new Error(`Failed to register webhook: ${errorDetails}`);
		}

		const data = await response.json();

		if (!data?.enabled) {
			throw new Error('Webhook registration failed - not enabled in response');
		}

		console.log('✅ Webhook successfully registered:', {
			url: data.url,
			events: data.events,
			id: data.id
		});

		return data;
	}

	static async verifyWebhook(): Promise<boolean> {
		try {
			const url = `${process.env.EVOLUTION_API_URL}/webhook/find/${process.env.EVOLUTION_API_INSTANCE}`;
			console.log('ℹ️ Verifying webhook at:', url);
			
			const response = await fetch(url, {
				method: 'GET',
				headers: this.getHeaders(),
			});

			if (!response.ok) {
				const body = await response.text();
				console.error('❌ Webhook verification failed:', {
					status: response.status,
					statusText: response.statusText,
					body
				});
				return false;
			}

			const data = await response.json();
			console.log('ℹ️ Webhook verification response:', data);
			
			const isEnabled = data?.enabled === true;
			if (!isEnabled) {
				console.error('❌ Webhook not enabled in verification response');
			}
			return isEnabled;
		} catch (error) {
			console.error('❌ Webhook verification error:', error instanceof Error ? error.stack : error);
			return false;
		}
	}

	static async testWebhookEndpoint(): Promise<boolean> {
		try {
			if (!process.env.WEBHOOK_URL) {
				throw new Error('WEBHOOK_URL is not set');
			}

			// Skip self-test in production if using internal URL
			if (process.env.NODE_ENV === 'production' && 
				process.env.WEBHOOK_URL.startsWith('http://srv-captain--')) {
				console.log('ℹ️ Skipping self-test for internal production URL');
				return true;
			}

			console.log('ℹ️ Testing webhook endpoint:', process.env.WEBHOOK_URL);
			
			const testPayload = {
				test: true,
				timestamp: new Date().toISOString()
			};

			const response = await fetch(process.env.WEBHOOK_URL, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
				},
				body: JSON.stringify(testPayload),
				timeout: 5000 // Add timeout to prevent hanging
			});

			if (!response.ok) {
				const body = await response.text();
				console.error('❌ Webhook test failed:', {
					status: response.status,
					statusText: response.statusText,
					body
				});
				return false;
			}

			console.log('✅ Webhook endpoint test successful');
			return true;
		} catch (error) {
			console.error('❌ Webhook test error:', error instanceof Error ? error.stack : error);
			return false;
		}
	}
}
