import axios from 'axios';
import crypto from 'crypto';
import { logger } from '../../utils/logger';
import db from '../../config/database';

export interface WebhookEvent {
  tenantId: string;
  eventType: 'TASK_CREATED' | 'TASK_APPROVED' | 'TASK_PUBLISHED' | 'TASK_FAILED' | 'RECONCILIATION_COMPLETED';
  payload: any;
  traceId: string;
  timestamp: number;
}

export interface WebhookConfig {
  tenantId: string;
  url: string;
  secret: string;
  enabledEvents: string[];
  isEnabled: boolean;
}

/**
 * [CORE_TOB_05] Webhook 事件总线 (Event Bus)
 * @description 将系统任务状态变化可靠地推送到企业级客户系统
 */
export class WebhookService {
  private static readonly CONFIG_TABLE = 'cf_webhook_configs';
  private static readonly LOG_TABLE = 'cf_webhook_logs';

  /**
   * 发送 Webhook 通知 (入口)
   */
  static async trigger(event: WebhookEvent): Promise<void> {
    logger.info(`[Webhook] Processing event ${event.eventType} for Tenant: ${event.tenantId}`);

    // 1. 获取租户配置
    const config = await this.getTenantConfig(event.tenantId);
    if (!config || !config.isEnabled) return;

    if (!config.enabledEvents.includes(event.eventType)) {
      logger.info(`[Webhook] Event ${event.eventType} skipped (not subscribed)`);
      return;
    }

    // 2. 记录初始日志
    const [logId] = await db(this.LOG_TABLE).insert({
      tenant_id: event.tenantId,
      event_type: event.eventType,
      payload: JSON.stringify(event.payload),
      status: 'pending',
      created_at: new Date(),
      updated_at: new Date()
    });

    // 3. 执行推送 (异步)
    this.sendToEndpoint(logId, config, event).catch(err => 
      logger.error(`[Webhook] Async push failed: ${err.message}`)
    );
  }

  /**
   * 实际发送逻辑
   */
  private static async sendToEndpoint(logId: number, config: WebhookConfig, event: WebhookEvent) {
    const timestamp = Date.now();
    const signature = this.generateSignature(event, config.secret, timestamp);

    try {
      await axios.post(config.url, event, {
        headers: {
          'Content-Type': 'application/json',
          'X-Crawlful-Signature': signature,
          'X-Crawlful-Timestamp': timestamp.toString()
        },
        timeout: 10000
      });

      await db(this.LOG_TABLE).where({ id: logId }).update({
        status: 'success',
        updated_at: new Date()
      });

      logger.info(`[Webhook] Successfully delivered event to ${config.url}`);
    } catch (err: any) {
      const errorMessage = err.response?.data ? JSON.stringify(err.response.data) : err.message;
      
      await db(this.LOG_TABLE).where({ id: logId }).update({
        status: 'failed',
        error_message: errorMessage,
        updated_at: new Date()
      });

      logger.error(`[Webhook] Delivery failed for log ${logId}: ${errorMessage}`);
    }
  }

  /**
   * 生成安全签名 (HMAC-SHA256)
   */
  private static generateSignature(payload: any, secret: string, timestamp: number): string {
    const data = `${timestamp}.${JSON.stringify(payload)}`;
    return crypto.createHmac('sha256', secret).update(data).digest('hex');
  }

  /**
   * 获取租户 Webhook 配置
   */
  private static async getTenantConfig(tenantId: string): Promise<WebhookConfig | null> {
    const record = await db(this.CONFIG_TABLE).where({ tenant_id: tenantId }).first();
    if (!record) return null;

    return {
      tenantId: record.tenant_id,
      url: record.url,
      secret: record.secret,
      enabledEvents: typeof record.enabled_events === 'string' ? JSON.parse(record.enabled_events) : record.enabled_events,
      isEnabled: Boolean(record.is_enabled)
    };
  }

  /**
   * 更新 Webhook 配置
   */
  static async updateConfig(tenantId: string, data: Partial<WebhookConfig>) {
    const exists = await db(this.CONFIG_TABLE).where({ tenant_id: tenantId }).first();
    
    const updateData: any = { ...data };
    if (data.enabledEvents) updateData.enabled_events = JSON.stringify(data.enabledEvents);
    updateData.updated_at = new Date();

    if (exists) {
      await db(this.CONFIG_TABLE).where({ tenant_id: tenantId }).update(updateData);
    } else {
      await db(this.CONFIG_TABLE).insert({
        tenant_id: tenantId,
        url: data.url || '',
        secret: data.secret || crypto.randomBytes(16).toString('hex'),
        enabled_events: JSON.stringify(data.enabledEvents || []),
        is_enabled: data.isEnabled ?? true,
        created_at: new Date(),
        updated_at: new Date()
      });
    }
  }
}
