import { z } from 'zod';

export const webhookProviders = ['slack', 'discord', 'teams'] as const;
export type WebhookProvider = (typeof webhookProviders)[number];

export interface WebhookConfig {
  id: string;
  provider: WebhookProvider;
  url: string;
  enabled: boolean;
  alertTypes: string[];
  severityFilter: 'all' | 'critical' | 'high' | 'high_and_critical';
  createdAt: Date;
  lastTestedAt?: Date;
  testStatus?: 'success' | 'failed' | 'pending';
}

export interface WebhookMessage {
  provider: WebhookProvider;
  title: string;
  description: string;
  severity: 'critical' | 'high' | 'medium' | 'low';
  alertType: string;
  metrics?: Record<string, number | string>;
  timestamp: Date;
  actionUrl?: string;
}

class WebhookIntegrationService {
  /**
   * Send alert to Slack webhook
   */
  async sendToSlack(config: WebhookConfig, message: WebhookMessage): Promise<boolean> {
    try {
      const color = this.getSeverityColor(message.severity);
      const payload = {
        attachments: [
          {
            color,
            title: message.title,
            text: message.description,
            fields: [
              {
                title: 'Severity',
                value: message.severity.toUpperCase(),
                short: true,
              },
              {
                title: 'Alert Type',
                value: message.alertType,
                short: true,
              },
              {
                title: 'Timestamp',
                value: message.timestamp.toISOString(),
                short: false,
              },
              ...(message.metrics
                ? Object.entries(message.metrics).map(([key, value]) => ({
                    title: key,
                    value: String(value),
                    short: true,
                  }))
                : []),
            ],
            ...(message.actionUrl && {
              actions: [
                {
                  type: 'button',
                  text: 'View Alert',
                  url: message.actionUrl,
                },
              ],
            }),
          },
        ],
      };

      const response = await fetch(config.url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      return response.ok;
    } catch (error) {
      console.error('Slack webhook error:', error);
      return false;
    }
  }

  /**
   * Send alert to Discord webhook
   */
  async sendToDiscord(config: WebhookConfig, message: WebhookMessage): Promise<boolean> {
    try {
      const color = this.getSeverityColorHex(message.severity);
      const payload = {
        embeds: [
          {
            title: message.title,
            description: message.description,
            color: parseInt(color.replace('#', ''), 16),
            fields: [
              {
                name: 'Severity',
                value: message.severity.toUpperCase(),
                inline: true,
              },
              {
                name: 'Alert Type',
                value: message.alertType,
                inline: true,
              },
              {
                name: 'Timestamp',
                value: message.timestamp.toISOString(),
                inline: false,
              },
              ...(message.metrics
                ? Object.entries(message.metrics).map(([key, value]) => ({
                    name: key,
                    value: String(value),
                    inline: true,
                  }))
                : []),
            ],
            ...(message.actionUrl && {
              url: message.actionUrl,
            }),
            footer: {
              text: 'CoinKrazy Alert System',
            },
            timestamp: message.timestamp.toISOString(),
          },
        ],
      };

      const response = await fetch(config.url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      return response.ok;
    } catch (error) {
      console.error('Discord webhook error:', error);
      return false;
    }
  }

  /**
   * Send alert to Microsoft Teams webhook
   */
  async sendToTeams(config: WebhookConfig, message: WebhookMessage): Promise<boolean> {
    try {
      const themeColor = this.getSeverityThemeColor(message.severity);
      const payload = {
        '@type': 'MessageCard',
        '@context': 'https://schema.org/extensions',
        summary: message.title,
        themeColor,
        sections: [
          {
            activityTitle: message.title,
            activitySubtitle: message.alertType,
            text: message.description,
            facts: [
              {
                name: 'Severity',
                value: message.severity.toUpperCase(),
              },
              {
                name: 'Timestamp',
                value: message.timestamp.toISOString(),
              },
              ...(message.metrics
                ? Object.entries(message.metrics).map(([key, value]) => ({
                    name: key,
                    value: String(value),
                  }))
                : []),
            ],
            ...(message.actionUrl && {
              potentialAction: [
                {
                  '@type': 'OpenUri',
                  name: 'View Alert',
                  targets: [
                    {
                      os: 'default',
                      uri: message.actionUrl,
                    },
                  ],
                },
              ],
            }),
          },
        ],
      };

      const response = await fetch(config.url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      return response.ok;
    } catch (error) {
      console.error('Teams webhook error:', error);
      return false;
    }
  }

  /**
   * Send alert to configured webhook
   */
  async sendAlert(config: WebhookConfig, message: WebhookMessage): Promise<boolean> {
    // Check severity filter
    if (config.severityFilter !== 'all') {
      const severityLevels = {
        critical: 4,
        high: 3,
        medium: 2,
        low: 1,
      };

      const messageSeverity = severityLevels[message.severity];
      const filterSeverity =
        config.severityFilter === 'critical'
          ? 4
          : config.severityFilter === 'high'
            ? 3
            : 3;

      if (messageSeverity < filterSeverity) {
        return false;
      }
    }

    // Check alert type filter
    if (config.alertTypes.length > 0 && !config.alertTypes.includes(message.alertType)) {
      return false;
    }

    // Send to appropriate provider
    switch (config.provider) {
      case 'slack':
        return this.sendToSlack(config, message);
      case 'discord':
        return this.sendToDiscord(config, message);
      case 'teams':
        return this.sendToTeams(config, message);
      default:
        return false;
    }
  }

  /**
   * Test webhook configuration
   */
  async testWebhook(config: WebhookConfig): Promise<boolean> {
    const testMessage: WebhookMessage = {
      provider: config.provider,
      title: 'Test Alert from CoinKrazy',
      description: 'This is a test notification to verify webhook integration is working correctly.',
      severity: 'high',
      alertType: 'test',
      metrics: {
        'Test Metric': 'Success',
      },
      timestamp: new Date(),
      actionUrl: 'https://coinkrazy.com/admin/alerts',
    };

    return this.sendAlert(config, testMessage);
  }

  /**
   * Get severity color for Slack
   */
  private getSeverityColor(severity: string): string {
    const colors: Record<string, string> = {
      critical: 'danger',
      high: 'warning',
      medium: '#0099ff',
      low: 'good',
    };
    return colors[severity] || 'good';
  }

  /**
   * Get severity color hex for Discord
   */
  private getSeverityColorHex(severity: string): string {
    const colors: Record<string, string> = {
      critical: '#FF0000',
      high: '#FF9900',
      medium: '#0099FF',
      low: '#00CC00',
    };
    return colors[severity] || '#00CC00';
  }

  /**
   * Get severity theme color for Teams
   */
  private getSeverityThemeColor(severity: string): string {
    const colors: Record<string, string> = {
      critical: 'FF0000',
      high: 'FF9900',
      medium: '0099FF',
      low: '00CC00',
    };
    return colors[severity] || '00CC00';
  }

  /**
   * Validate webhook URL format
   */
  validateWebhookUrl(provider: WebhookProvider, url: string): boolean {
    try {
      const urlObj = new URL(url);

      switch (provider) {
        case 'slack':
          return urlObj.hostname === 'hooks.slack.com' && url.includes('/services/');
        case 'discord':
          return urlObj.hostname === 'discord.com' && url.includes('/api/webhooks/');
        case 'teams':
          return urlObj.hostname.includes('webhook.office.com');
        default:
          return false;
      }
    } catch {
      return false;
    }
  }

  /**
   * Get webhook provider instructions
   */
  getProviderInstructions(provider: WebhookProvider): string {
    const instructions: Record<WebhookProvider, string> = {
      slack: `1. Go to your Slack workspace settings
2. Navigate to Apps > Custom Integrations > Incoming Webhooks
3. Click "Add New Webhook to Workspace"
4. Select the channel where alerts should be posted
5. Copy the webhook URL and paste it here`,
      discord: `1. Open your Discord server
2. Go to Server Settings > Integrations > Webhooks
3. Click "New Webhook"
4. Name it "CoinKrazy Alerts"
5. Copy the webhook URL and paste it here`,
      teams: `1. Open Microsoft Teams
2. Go to your team channel
3. Click the three dots (...) > Connectors
4. Search for "Incoming Webhook"
5. Configure and copy the webhook URL`,
    };
    return instructions[provider];
  }
}

export const webhookService = new WebhookIntegrationService();
