import Handlebars from 'handlebars';
import { NotificationChannel } from './types';
import { LoggingService } from '#services/file-system/logService';

const logger = new LoggingService();

// Cache TTL in milliseconds (5 minutes)
const CACHE_TTL_MS = 5 * 60 * 1000;

export interface TemplateRenderParams {
	template_key: string;
	channel: NotificationChannel;
	variables: Record<string, any>;
	locale?: string;
}

export interface TemplateContent {
	title: string;
	body: string;
	subject?: string; // For email
	html?: string; // For email
}

export interface NotificationTemplate {
	title_template: string;
	body_template: string;
}

export interface TemplateVariables {
	[key: string]: string | number | boolean | null;
}

interface CachedTemplate {
	compiled: HandlebarsTemplateDelegate;
	timestamp: number;
}

class TemplateEngineService {
	private static instance: TemplateEngineService;
	private cache: Map<string, CachedTemplate> = new Map();
	private templates: Map<string, TemplateContent> = new Map();

	static getInstance(): TemplateEngineService {
		TemplateEngineService.instance ??= new TemplateEngineService();
		return TemplateEngineService.instance;
	}

	constructor() {
		this.initializeDefaultTemplates();
	}

	private initializeDefaultTemplates() {
		// Order created templates
		this.templates.set('order_created_push_vi', {
			title: 'Đơn hàng mới đã được tạo',
			body: 'Cảm ơn {{customer_name}}! Đơn hàng #{{order_code}} của bạn đang được xử lý.',
		});

		this.templates.set('order_created_push_en', {
			title: 'New order created',
			body: 'Thank you {{customer_name}}! Your order #{{order_code}} is being processed.',
		});

		// Order delivered templates
		this.templates.set('order_delivered_push_vi', {
			title: '🎉 Đơn hàng #{{order_code}} đã giao!',
			body: 'Cảm ơn {{customer_name}}! Đơn hàng của bạn đã được giao thành công.',
		});

		this.templates.set('order_delivered_push_en', {
			title: '🎉 Order #{{order_code}} delivered!',
			body: 'Thank you {{customer_name}}! Your order has been delivered successfully.',
		});

		this.templates.set('order_delivered_email_vi', {
			title: 'Đơn hàng đã được giao',
			body: 'Đơn hàng #{{order_code}} của bạn đã được giao thành công.',
			subject: 'Đơn hàng #{{order_code}} đã được giao',
			html: '<h1>Chào {{customer_name}}!</h1><p>Đơn hàng #{{order_code}} của bạn đã được giao thành công.</p>',
		});

		this.templates.set('order_delivered_email_en', {
			title: 'Order delivered',
			body: 'Your order #{{order_code}} has been delivered successfully.',
			subject: 'Order #{{order_code}} delivered',
			html: '<h1>Hello {{customer_name}}!</h1><p>Your order #{{order_code}} has been delivered successfully.</p>',
		});

		// Payment failed templates
		this.templates.set('payment_failed_push_vi', {
			title: 'Thanh toán thất bại',
			body: 'Thanh toán đơn hàng #{{order_id}} không thành công. {{error_message}}',
		});

		this.templates.set('payment_failed_push_en', {
			title: 'Payment Failed',
			body: 'Payment for order #{{order_id}} failed. {{error_message}}',
		});

		// Chat message templates
		this.templates.set('chat_message_push_vi', {
			title: 'Tin nhắn mới',
			body: '{{message}}',
		});

		this.templates.set('chat_message_push_en', {
			title: 'New Message',
			body: '{{message}}',
		});

		// Security alert templates
		this.templates.set('security_alert_push_vi', {
			title: 'Cảnh báo bảo mật',
			body: '{{alert_type}}',
		});

		this.templates.set('security_alert_push_en', {
			title: 'Security Alert',
			body: '{{alert_type}}',
		});
	}

	async render(params: TemplateRenderParams): Promise<TemplateContent> {
		const { template_key, channel, variables, locale = 'vi' } = params;
		const _cacheKey = `${template_key}_${channel}_${locale}`;

		// Get template
		const template = this.getTemplate(template_key, channel, locale);
		if (!template) {
			logger
				.logInfoAsync('TemplateEngine', `Template not found: ${template_key}_${channel}_${locale}`, null)
				.catch(() => {});
			return { title: '', body: '' };
		}

		return this.renderTemplate(template, variables);
	}

	private getTemplate(template_key: string, channel: NotificationChannel, locale: string): TemplateContent | undefined {
		// Try locale-specific template first
		const localeTemplate = this.templates.get(`${template_key}_${channel}_${locale}`);
		if (localeTemplate) {
			return localeTemplate;
		}

		// Fallback to English if locale-specific not found
		const englishTemplate = this.templates.get(`${template_key}_${channel}_en`);
		if (englishTemplate) {
			return englishTemplate;
		}

		// Fallback to default template
		return this.templates.get(template_key);
	}

	private renderTemplate(template: TemplateContent, variables: Record<string, any>): TemplateContent {
		const result: TemplateContent = {
			title: this.compileAndRender(template.title, variables),
			body: this.compileAndRender(template.body, variables),
		};

		if (template.subject) {
			result.subject = this.compileAndRender(template.subject, variables);
		}

		if (template.html) {
			result.html = this.compileAndRender(template.html, variables);
		}

		return result;
	}

	private compileAndRender(template: string, variables: Record<string, any>): string {
		const templateKey = this.generateTemplateKey(template);
		const compiled = this.compileWithCache(templateKey, template);
		return compiled(variables);
	}

	private generateTemplateKey(template: string): string {
		// Simple hash for template key (in production, use proper hash function)
		return template.substring(0, 50);
	}

	private compileWithCache(templateKey: string, template: string): HandlebarsTemplateDelegate {
		const now = Date.now();
		const cached = this.cache.get(templateKey);

		// Return cached template if still valid
		if (cached && now - cached.timestamp < CACHE_TTL_MS) {
			return cached.compiled;
		}

		// Compile and cache new template
		const compiled = Handlebars.compile(template);
		this.cache.set(templateKey, { compiled, timestamp: now });

		return compiled;
	}

	invalidateCache(template_key: string, channel: NotificationChannel, locale: string = 'vi') {
		const cacheKey = `${template_key}_${channel}_${locale}`;
		this.cache.delete(cacheKey);
	}
}

export default TemplateEngineService;
