/**
 * Alert Service
 *
 * Zentraler Service für System-Benachrichtigungen.
 * Unterstützt verschiedene Kanäle: E-Mail, Slack, Discord, etc.
 */

import type { Payload } from 'payload'

export type AlertChannel = 'email' | 'slack' | 'discord' | 'console'
export type AlertLevel = 'info' | 'warning' | 'error' | 'critical'

export interface AlertConfig {
  channels: AlertChannel[]
  recipients?: string[] // E-Mail-Adressen
  slackWebhook?: string
  discordWebhook?: string
  minLevel: AlertLevel
}

interface AlertInput {
  level: AlertLevel
  title: string
  message: string
  details?: Record<string, unknown>
  tenantId?: number
  tenantName?: string
}

// Alert-Konfiguration aus Environment
const alertConfig: AlertConfig = {
  channels: (process.env.ALERT_CHANNELS?.split(',') as AlertChannel[]) || ['console'],
  recipients: process.env.ALERT_EMAIL_RECIPIENTS?.split(','),
  slackWebhook: process.env.ALERT_SLACK_WEBHOOK,
  discordWebhook: process.env.ALERT_DISCORD_WEBHOOK,
  minLevel: (process.env.ALERT_MIN_LEVEL as AlertLevel) || 'warning',
}

// Level-Hierarchie für Filterung
const levelPriority: Record<AlertLevel, number> = {
  info: 0,
  warning: 1,
  error: 2,
  critical: 3,
}

/**
 * Prüft ob ein Alert basierend auf dem Level gesendet werden soll
 */
function shouldSendAlert(level: AlertLevel): boolean {
  return levelPriority[level] >= levelPriority[alertConfig.minLevel]
}

/**
 * Formatiert die Alert-Nachricht für verschiedene Kanäle
 */
function formatAlertMessage(alert: AlertInput, format: 'text' | 'html' | 'markdown'): string {
  const timestamp = new Date().toLocaleString('de-DE')
  const levelEmoji: Record<AlertLevel, string> = {
    info: 'ℹ️',
    warning: '⚠️',
    error: '❌',
    critical: '🚨',
  }

  if (format === 'html') {
    return `
      <div style="font-family: Arial, sans-serif; padding: 20px; border-left: 4px solid ${
        alert.level === 'critical'
          ? '#dc2626'
          : alert.level === 'error'
            ? '#f97316'
            : alert.level === 'warning'
              ? '#eab308'
              : '#3b82f6'
      };">
        <h2 style="margin: 0 0 10px;">${levelEmoji[alert.level]} ${alert.title}</h2>
        <p style="color: #666; margin: 0 0 15px;">${timestamp}</p>
        ${alert.tenantName ? `<p><strong>Tenant:</strong> ${alert.tenantName}</p>` : ''}
        <p>${alert.message}</p>
        ${
          alert.details
            ? `
          <details>
            <summary>Details</summary>
            <pre style="background: #f5f5f5; padding: 10px; overflow: auto;">${JSON.stringify(alert.details, null, 2)}</pre>
          </details>
        `
            : ''
        }
      </div>
    `
  }

  if (format === 'markdown') {
    let md = `${levelEmoji[alert.level]} **${alert.title}**\n\n`
    md += `*${timestamp}*\n\n`
    if (alert.tenantName) md += `**Tenant:** ${alert.tenantName}\n\n`
    md += `${alert.message}\n`
    if (alert.details) {
      md += `\n\`\`\`json\n${JSON.stringify(alert.details, null, 2)}\n\`\`\``
    }
    return md
  }

  // Plain text
  let text = `${levelEmoji[alert.level]} ${alert.title}\n`
  text += `${timestamp}\n\n`
  if (alert.tenantName) text += `Tenant: ${alert.tenantName}\n`
  text += `${alert.message}\n`
  if (alert.details) {
    text += `\nDetails: ${JSON.stringify(alert.details)}`
  }
  return text
}

/**
 * Sendet Alert via E-Mail
 */
async function sendEmailAlert(payload: Payload, alert: AlertInput): Promise<void> {
  if (!alertConfig.recipients?.length) {
    console.warn('[AlertService] No email recipients configured')
    return
  }

  const levelLabels: Record<AlertLevel, string> = {
    info: 'Info',
    warning: 'Warnung',
    error: 'Fehler',
    critical: 'KRITISCH',
  }

  try {
    await payload.sendEmail({
      to: alertConfig.recipients.join(','),
      subject: `[${levelLabels[alert.level]}] ${alert.title}`,
      html: formatAlertMessage(alert, 'html'),
      text: formatAlertMessage(alert, 'text'),
    })
    console.log(`[AlertService] Email alert sent to ${alertConfig.recipients.join(', ')}`)
  } catch (error) {
    console.error('[AlertService] Failed to send email alert:', error)
  }
}

/**
 * Sendet Alert via Slack Webhook
 */
async function sendSlackAlert(alert: AlertInput): Promise<void> {
  if (!alertConfig.slackWebhook) {
    console.warn('[AlertService] No Slack webhook configured')
    return
  }

  const colors: Record<AlertLevel, string> = {
    info: '#3b82f6',
    warning: '#eab308',
    error: '#f97316',
    critical: '#dc2626',
  }

  try {
    const response = await fetch(alertConfig.slackWebhook, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        attachments: [
          {
            color: colors[alert.level],
            title: alert.title,
            text: alert.message,
            fields: [
              ...(alert.tenantName
                ? [
                    {
                      title: 'Tenant',
                      value: alert.tenantName,
                      short: true,
                    },
                  ]
                : []),
              {
                title: 'Level',
                value: alert.level.toUpperCase(),
                short: true,
              },
            ],
            footer: 'Payload CMS Alert',
            ts: Math.floor(Date.now() / 1000),
          },
        ],
      }),
    })

    if (!response.ok) {
      throw new Error(`Slack responded with ${response.status}`)
    }
    console.log('[AlertService] Slack alert sent')
  } catch (error) {
    console.error('[AlertService] Failed to send Slack alert:', error)
  }
}

/**
 * Sendet Alert via Discord Webhook
 */
async function sendDiscordAlert(alert: AlertInput): Promise<void> {
  if (!alertConfig.discordWebhook) {
    console.warn('[AlertService] No Discord webhook configured')
    return
  }

  const colors: Record<AlertLevel, number> = {
    info: 0x3b82f6,
    warning: 0xeab308,
    error: 0xf97316,
    critical: 0xdc2626,
  }

  try {
    const response = await fetch(alertConfig.discordWebhook, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        embeds: [
          {
            title: alert.title,
            description: alert.message,
            color: colors[alert.level],
            fields: [
              ...(alert.tenantName
                ? [
                    {
                      name: 'Tenant',
                      value: alert.tenantName,
                      inline: true,
                    },
                  ]
                : []),
              {
                name: 'Level',
                value: alert.level.toUpperCase(),
                inline: true,
              },
            ],
            footer: {
              text: 'Payload CMS Alert',
            },
            timestamp: new Date().toISOString(),
          },
        ],
      }),
    })

    if (!response.ok) {
      throw new Error(`Discord responded with ${response.status}`)
    }
    console.log('[AlertService] Discord alert sent')
  } catch (error) {
    console.error('[AlertService] Failed to send Discord alert:', error)
  }
}

/**
 * Sendet Alert an alle konfigurierten Kanäle
 */
export async function sendAlert(payload: Payload, alert: AlertInput): Promise<void> {
  if (!shouldSendAlert(alert.level)) {
    return
  }

  const promises: Promise<void>[] = []

  for (const channel of alertConfig.channels) {
    switch (channel) {
      case 'email':
        promises.push(sendEmailAlert(payload, alert))
        break
      case 'slack':
        promises.push(sendSlackAlert(alert))
        break
      case 'discord':
        promises.push(sendDiscordAlert(alert))
        break
      case 'console':
        console.log(`[Alert:${alert.level.toUpperCase()}]`, formatAlertMessage(alert, 'text'))
        break
    }
  }

  await Promise.allSettled(promises)
}

/**
 * Email-Fehler Alert
 */
export async function alertEmailFailed(
  payload: Payload,
  tenantId: number,
  tenantName: string,
  to: string,
  subject: string,
  error: string,
  failedCount: number,
): Promise<void> {
  await sendAlert(payload, {
    level: failedCount >= 5 ? 'critical' : 'error',
    title: `E-Mail-Versand fehlgeschlagen${failedCount >= 5 ? ' (wiederholt)' : ''}`,
    message: `E-Mail an "${to}" mit Betreff "${subject}" konnte nicht gesendet werden.`,
    tenantId,
    tenantName,
    details: {
      to,
      subject,
      error: error.substring(0, 200), // Gekürzt um Secrets zu vermeiden
      failedCount,
      recommendation:
        failedCount >= 5
          ? 'SMTP-Konfiguration prüfen! Mehrere Fehler in Folge.'
          : 'Einzelner Fehler. Weiter beobachten.',
    },
  })
}

/**
 * Rate-Limit Alert
 */
export async function alertRateLimitReached(
  payload: Payload,
  endpoint: string,
  userId?: number,
  userEmail?: string,
): Promise<void> {
  await sendAlert(payload, {
    level: 'warning',
    title: 'Rate-Limit erreicht',
    message: `Rate-Limit für Endpoint "${endpoint}" wurde erreicht.`,
    details: {
      endpoint,
      userId,
      userEmail,
    },
  })
}
