/**
 * Telegram Message Templates
 *
 * Centralized template system for formatting Telegram notifications
 * All messages are formatted in HTML with consistent styling
 */

import { format } from 'date-fns';
import { logger } from '../../../../shared/utils/logger';
import {
  TelegramMessageType,
  TelegramPriority,
} from '../../../../config/telegram';

/**
 * Base Template Interface
 */
interface BaseTemplate {
  format(data: any): string;
  getType(): TelegramMessageType;
  getPriority(): TelegramPriority;
}

/**
 * System Notification Template
 */
export class SystemNotificationTemplate implements BaseTemplate {
  format(data: {
    title: string;
    message: string;
    details?: Record<string, any>;
  }): string {
    const { title, message, details } = data;

    let content = `
<b>🔔 System Notification</b>

<b>Title:</b> ${this.escapeHtml(title)}
<b>Message:</b> ${this.escapeHtml(message)}
`;

    if (details && Object.keys(details).length > 0) {
      content += `\n<b>Details:</b>\n`;
      Object.entries(details).forEach(([key, value]) => {
        content += `• <b>${this.escapeHtml(key)}:</b> ${this.escapeHtml(String(value))}\n`;
      });
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.SYSTEM;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.NORMAL;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * User Registration Template
 */
export class UserRegistrationTemplate implements BaseTemplate {
  format(data: {
    userId: string;
    username?: string;
    email?: string;
    registrationDate: Date;
    ipAddress?: string;
    userAgent?: string;
  }): string {
    const { userId, username, email, registrationDate, ipAddress, userAgent } = data;

    let content = `
<b>👤 New User Registration</b>

<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>
`;

    if (username) {
      content += `<b>Username:</b> ${this.escapeHtml(username)}\n`;
    }

    if (email) {
      content += `<b>Email:</b> <code>${this.escapeHtml(email)}</code>\n`;
    }

    content += `
<b>Registration Date:</b> ${format(registrationDate, 'yyyy-MM-dd HH:mm:ss')}
`;

    if (ipAddress) {
      content += `<b>IP Address:</b> <code>${this.escapeHtml(ipAddress)}</code>\n`;
    }

    if (userAgent) {
      const shortUserAgent = this.truncate(userAgent, 100);
      content += `<b>User Agent:</b> <code>${this.escapeHtml(shortUserAgent)}</code>\n`;
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.USER_REGISTRATION;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.LOW;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private truncate(text: string, maxLength: number): string {
    return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * User Activity Template
 */
export class UserActivityTemplate implements BaseTemplate {
  format(data: {
    userId: string;
    username?: string;
    activity: string;
    details?: Record<string, any>;
    timestamp: Date;
  }): string {
    const { userId, username, activity, details, timestamp } = data;

    let content = `
<b>📊 User Activity</b>

<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>
`;

    if (username) {
      content += `<b>Username:</b> ${this.escapeHtml(username)}\n`;
    }

    content += `
<b>Activity:</b> ${this.escapeHtml(activity)}
<b>Time:</b> ${format(timestamp, 'yyyy-MM-dd HH:mm:ss')}
`;

    if (details && Object.keys(details).length > 0) {
      content += `\n<b>Details:</b>\n`;
      Object.entries(details).forEach(([key, value]) => {
        content += `• <b>${this.escapeHtml(key)}:</b> ${this.escapeHtml(String(value))}\n`;
      });
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.USER_ACTIVITY;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.LOW;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Exercise Completion Template
 */
export class ExerciseCompletionTemplate implements BaseTemplate {
  format(data: {
    userId: string;
    username?: string;
    exerciseId?: string;
    topic: string;
    difficulty: string;
    completedAt: Date;
    timeSpent?: number;
    correct?: boolean;
    attempts?: number;
  }): string {
    const { userId, username, exerciseId, topic, difficulty, completedAt, timeSpent, correct, attempts } = data;

    let content = `
<b>✅ Exercise Completed</b>

<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>
`;

    if (username) {
      content += `<b>Username:</b> ${this.escapeHtml(username)}\n`;
    }

    if (exerciseId) {
      content += `<b>Exercise ID:</b> <code>${this.escapeHtml(exerciseId)}</code>\n`;
    }

    content += `
<b>Topic:</b> ${this.escapeHtml(topic)}
<b>Difficulty:</b> ${this.escapeHtml(difficulty)}
<b>Completed At:</b> ${format(completedAt, 'yyyy-MM-dd HH:mm:ss')}
`;

    if (timeSpent !== undefined) {
      content += `<b>Time Spent:</b> ${this.formatTime(timeSpent)}\n`;
    }

    if (correct !== undefined) {
      content += `<b>Result:</b> ${correct ? '✅ Correct' : '❌ Incorrect'}\n`;
    }

    if (attempts !== undefined) {
      content += `<b>Attempts:</b> ${attempts}\n`;
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.EXERCISE_COMPLETION;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.LOW;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private formatTime(seconds: number): string {
    if (seconds < 60) {
      return `${seconds}s`;
    }
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = seconds % 60;
    return `${minutes}m ${remainingSeconds}s`;
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Module Completion Template
 */
export class ModuleCompletionTemplate implements BaseTemplate {
  format(data: {
    userId: string;
    username?: string;
    moduleType: string;
    moduleName: string;
    completedAt: Date;
    totalTime?: number;
    exerciseCount?: number;
    averageScore?: number;
    badgeEarned?: string;
  }): string {
    const { userId, username, moduleType, moduleName, completedAt, totalTime, exerciseCount, averageScore, badgeEarned } = data;

    let content = `
<b>🎉 Module Completed!</b>

<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>
`;

    if (username) {
      content += `<b>Username:</b> ${this.escapeHtml(username)}\n`;
    }

    content += `
<b>Module:</b> ${this.escapeHtml(moduleName)} (${this.escapeHtml(moduleType)})
<b>Completed At:</b> ${format(completedAt, 'yyyy-MM-dd HH:mm:ss')}
`;

    if (totalTime !== undefined) {
      content += `<b>Total Time:</b> ${this.formatTime(totalTime)}\n`;
    }

    if (exerciseCount !== undefined) {
      content += `<b>Exercises:</b> ${exerciseCount}\n`;
    }

    if (averageScore !== undefined) {
      content += `<b>Average Score:</b> ${averageScore.toFixed(1)}%\n`;
    }

    if (badgeEarned) {
      content += `\n🏆 <b>Badge Earned:</b> ${this.escapeHtml(badgeEarned)}\n`;
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.MODULE_COMPLETION;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.NORMAL;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private formatTime(seconds: number): string {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    if (hours > 0) {
      return `${hours}h ${minutes}m`;
    }
    return `${minutes}m`;
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Achievement Template
 */
export class AchievementTemplate implements BaseTemplate {
  format(data: {
    userId: string;
    username?: string;
    achievementType: string;
    achievementName: string;
    description: string;
    earnedAt: Date;
    rarity?: 'common' | 'rare' | 'epic' | 'legendary';
    progress?: {
      current: number;
      required: number;
    };
  }): string {
    const { userId, username, achievementType, achievementName, description, earnedAt, rarity, progress } = data;

    const rarityEmojis = {
      common: '⚪',
      rare: '🔵',
      epic: '🟣',
      legendary: '🟡',
    };

    const rarityEmoji = rarity ? rarityEmojis[rarity] : '⚪';

    let content = `
<b>🏆 ${rarityEmoji} Achievement Unlocked!</b>

<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>
`;

    if (username) {
      content += `<b>Username:</b> ${this.escapeHtml(username)}\n`;
    }

    content += `
<b>Type:</b> ${this.escapeHtml(achievementType)}
<b>Achievement:</b> <b>${this.escapeHtml(achievementName)}</b>
<b>Description:</b> ${this.escapeHtml(description)}
<b>Unlocked At:</b> ${format(earnedAt, 'yyyy-MM-dd HH:mm:ss')}
`;

    if (progress) {
      const percentage = Math.round((progress.current / progress.required) * 100);
      content += `\n<b>Progress:</b> ${progress.current}/${progress.required} (${percentage}%)\n`;
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.ACHIEVEMENT;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.NORMAL;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Error Notification Template
 */
export class ErrorNotificationTemplate implements BaseTemplate {
  format(data: {
    errorType: string;
    errorMessage: string;
    stackTrace?: string;
    userId?: string;
    route?: string;
    method?: string;
    statusCode?: number;
    metadata?: Record<string, any>;
  }): string {
    const { errorType, errorMessage, stackTrace, userId, route, method, statusCode, metadata } = data;

    let content = `
<b>🚨 Error Notification</b>

<b>Type:</b> <code>${this.escapeHtml(errorType)}</code>
<b>Message:</b> ${this.escapeHtml(errorMessage)}
`;

    if (statusCode) {
      content += `<b>Status:</b> <code>${statusCode}</code>\n`;
    }

    if (route || method) {
      content += `<b>Location:</b> ${method ? this.escapeHtml(method) + ' ' : ''}${route ? '<code>' + this.escapeHtml(route) + '</code>' : 'N/A'}\n`;
    }

    if (userId) {
      content += `<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>\n`;
    }

    if (metadata && Object.keys(metadata).length > 0) {
      content += `\n<b>Metadata:</b>\n`;
      Object.entries(metadata).forEach(([key, value]) => {
        content += `• <b>${this.escapeHtml(key)}:</b> ${this.escapeHtml(String(value))}\n`;
      });
    }

    if (stackTrace) {
      const truncatedStack = this.truncate(stackTrace, 500);
      content += `\n<b>Stack Trace:</b>\n<pre>${this.escapeHtml(truncatedStack)}</pre>\n`;
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.ERROR;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.HIGH;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private truncate(text: string, maxLength: number): string {
    return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Security Alert Template
 */
export class SecurityAlertTemplate implements BaseTemplate {
  format(data: {
    alertType: string;
    severity: 'low' | 'medium' | 'high' | 'critical';
    message: string;
    userId?: string;
    ipAddress?: string;
    userAgent?: string;
    location?: string;
    details?: Record<string, any>;
    timestamp: Date;
  }): string {
    const { alertType, severity, message, userId, ipAddress, userAgent, location, details, timestamp } = data;

    const severityEmojis = {
      low: '🟢',
      medium: '🟡',
      high: '🟠',
      critical: '🔴',
    };

    const severityEmoji = severityEmojis[severity];

    let content = `
<b>🔒 ${severityEmoji} Security Alert</b>

<b>Severity:</b> ${severityEmoji.toUpperCase()} ${this.escapeHtml(severity.toUpperCase())}
<b>Type:</b> ${this.escapeHtml(alertType)}
<b>Message:</b> ${this.escapeHtml(message)}
<b>Time:</b> ${format(timestamp, 'yyyy-MM-dd HH:mm:ss')}
`;

    if (userId) {
      content += `<b>User ID:</b> <code>${this.escapeHtml(userId)}</code>\n`;
    }

    if (ipAddress) {
      content += `<b>IP Address:</b> <code>${this.escapeHtml(ipAddress)}</code>\n`;
    }

    if (location) {
      content += `<b>Location:</b> ${this.escapeHtml(location)}\n`;
    }

    if (userAgent) {
      const shortUserAgent = this.truncate(userAgent, 80);
      content += `<b>User Agent:</b> <code>${this.escapeHtml(shortUserAgent)}</code>\n`;
    }

    if (details && Object.keys(details).length > 0) {
      content += `\n<b>Details:</b>\n`;
      Object.entries(details).forEach(([key, value]) => {
        content += `• <b>${this.escapeHtml(key)}:</b> ${this.escapeHtml(String(value))}\n`;
      });
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.SECURITY;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.URGENT;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private truncate(text: string, maxLength: number): string {
    return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Performance Monitoring Template
 */
export class PerformanceTemplate implements BaseTemplate {
  format(data: {
    metric: string;
    value: number;
    unit: string;
    threshold?: number;
    severity?: 'warning' | 'critical';
    route?: string;
    method?: string;
    timestamp: Date;
    details?: Record<string, any>;
  }): string {
    const { metric, value, unit, threshold, severity, route, method, timestamp, details } = data;

    const severityEmojis = {
      warning: '⚠️',
      critical: '🚨',
    };

    const severityEmoji = severity ? severityEmojis[severity] : '📊';

    let content = `
<b>${severityEmoji} Performance Alert</b>

<b>Metric:</b> ${this.escapeHtml(metric)}
<b>Value:</b> ${value} ${this.escapeHtml(unit)}
`;

    if (threshold !== undefined) {
      const percentage = Math.round((value / threshold) * 100);
      content += `<b>Threshold:</b> ${threshold} ${this.escapeHtml(unit)} (${percentage}%)\n`;
    }

    if (route) {
      content += `<b>Route:</b> <code>${method ? this.escapeHtml(method) + ' ' : ''}${this.escapeHtml(route)}</code>\n`;
    }

    content += `<b>Time:</b> ${format(timestamp, 'yyyy-MM-dd HH:mm:ss')}\n`;

    if (details && Object.keys(details).length > 0) {
      content += `\n<b>Details:</b>\n`;
      Object.entries(details).forEach(([key, value]) => {
        content += `• <b>${this.escapeHtml(key)}:</b> ${this.escapeHtml(String(value))}\n`;
      });
    }

    content += `\n<i>${this.getTimestamp()}</i>`;

    return content.trim();
  }

  getType(): TelegramMessageType {
    return TelegramMessageType.PERFORMANCE;
  }

  getPriority(): TelegramPriority {
    return TelegramPriority.HIGH;
  }

  private escapeHtml(text: string): string {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
  }

  private getTimestamp(): string {
    return format(new Date(), 'yyyy-MM-dd HH:mm:ss');
  }
}

/**
 * Template Factory
 */
export class TelegramTemplateFactory {
  /**
   * Get template by message type
   */
  public static getTemplate(type: TelegramMessageType): BaseTemplate {
    switch (type) {
      case TelegramMessageType.SYSTEM:
        return new SystemNotificationTemplate();
      case TelegramMessageType.USER_REGISTRATION:
        return new UserRegistrationTemplate();
      case TelegramMessageType.USER_ACTIVITY:
        return new UserActivityTemplate();
      case TelegramMessageType.EXERCISE_COMPLETION:
        return new ExerciseCompletionTemplate();
      case TelegramMessageType.MODULE_COMPLETION:
        return new ModuleCompletionTemplate();
      case TelegramMessageType.ACHIEVEMENT:
        return new AchievementTemplate();
      case TelegramMessageType.ERROR:
        return new ErrorNotificationTemplate();
      case TelegramMessageType.SECURITY:
        return new SecurityAlertTemplate();
      case TelegramMessageType.PERFORMANCE:
        return new PerformanceTemplate();
      default:
        logger.warn({ type }, 'Unknown Telegram message type, using system template');
        return new SystemNotificationTemplate();
    }
  }

  /**
   * Format message using template
   */
  public static formatMessage(
    type: TelegramMessageType,
    data: any
  ): { content: string; messageType: TelegramMessageType; priority: TelegramPriority } {
    try {
      const template = this.getTemplate(type);
      const content = template.format(data);
      return {
        content,
        messageType: template.getType(),
        priority: template.getPriority(),
      };
    } catch (error) {
      logger.error({ error, type, data }, 'Failed to format Telegram message template');
      // Fallback to simple system template
      const fallbackTemplate = new SystemNotificationTemplate();
      const content = fallbackTemplate.format({
        title: `Notification (${type})`,
        message: JSON.stringify(data, null, 2),
      });
      return {
        content,
        messageType: fallbackTemplate.getType(),
        priority: fallbackTemplate.getPriority(),
      };
    }
  }
}

export default TelegramTemplateFactory;
