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

/**
 * [BIZ_INT_12] 企业级 Webhook 推送服务 (Grounding Implementation)
 * @description 支持租户自定义事件推送、HMAC 签名与异步交付
 */
export class WebhookService {
  /**
   * 初始化数据库表
   */
  static async initTable() {
    const hasWebhookConfigsTable = await db.schema.hasTable('cf_webhook_configs');
    if (!hasWebhookConfigsTable) {
      console.log('📦 Creating cf_webhook_configs table...');
      await db.schema.createTable('cf_webhook_configs', (table) => {
        table.string('tenant_id', 64).primary();
        table.string('url', 255).notNullable();
        table.string('secret', 128).notNullable();
        table.json('enabled_events').notNullable();
        table.boolean('is_enabled').defaultTo(true);
        table.timestamps(true, true);
      });
      console.log('✅ Table cf_webhook_configs created');
    }

    const hasWebhookLogsTable = await db.schema.hasTable('cf_webhook_logs');
    if (!hasWebhookLogsTable) {
      console.log('📦 Creating cf_webhook_logs table...');
      await db.schema.createTable('cf_webhook_logs', (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 64).notNullable();
        table.string('event_type', 64).notNullable();
        table.json('payload').notNullable();
        table.string('status', 16).defaultTo('pending'); // pending, success, failed
        table.integer('retry_count').defaultTo(0);
        table.text('error_message');
        table.timestamps(true, true);

        table.index(['tenant_id', 'status']);
      });
      console.log('✅ Table cf_webhook_logs created');
    }
  }

  /**
   * 分发 Webhook 事件
   */
  static async dispatch(tenantId: string, event: string, payload: any) {
    try {
      const config = await db('cf_webhook_configs').where({ tenant_id: tenantId, is_enabled: true }).first();
      if (!config) return;

      // 检查事件是否开启
      const enabledEvents = typeof config.enabled_events === 'string' 
        ? JSON.parse(config.enabled_events) 
        : config.enabled_events;
        
      if (!enabledEvents.includes(event)) return;

      const logId = await db('cf_webhook_logs').insert({
        tenant_id: tenantId,
        event_type: event,
        payload: JSON.stringify(payload),
        status: 'pending'
      });

      logger.info(`[Webhook] Event ${event} queued for Tenant: ${tenantId}, LogID: ${logId}`);

      // 异步执行发送 (实际生产应由 BullMQ 消费)
      this.sendWebhook(tenantId, config.url, config.secret, event, payload, logId[0]).catch(err => {
        logger.error(`[Webhook] Async send failed: ${err.message}`);
      });
    } catch (err: any) {
      logger.error(`[Webhook] Dispatch error: ${err.message}`);
    }
  }

  /**
   * 实际发送 Webhook 请求
   */
  private static async sendWebhook(tenantId: string, url: string, secret: string, event: string, payload: any, logId: number) {
    const timestamp = Date.now();
    const body = JSON.stringify({
      event,
      timestamp,
      tenantId,
      data: payload
    });

    const signature = SignatureUtils.generateSignature(body, secret);

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

      await db('cf_webhook_logs').where({ id: logId }).update({
        status: 'success',
        updated_at: db.fn.now()
      });
      
      logger.info(`[Webhook] Sent ${event} to ${url} successfully`);
    } catch (err: any) {
      const errorMsg = err.response ? `Status ${err.response.status}: ${JSON.stringify(err.response.data)}` : err.message;
      
      await db('cf_webhook_logs').where({ id: logId }).update({
        status: 'failed',
        error_message: errorMsg,
        updated_at: db.fn.now()
      });

      logger.warn(`[Webhook] Failed to send ${event} to ${url}: ${errorMsg}`);
    }
  }

  /**
   * 获取 Webhook 配置
   */
  static async getConfig(tenantId: string) {
    return db('cf_webhook_configs').where({ tenant_id: tenantId }).first();
  }

  /**
   * 保存/更新 Webhook 配置
   */
  static async saveConfig(tenantId: string, data: { url: string; secret: string; enabled_events: string[] }) {
    const configData = {
      tenant_id: tenantId,
      url: data.url,
      secret: data.secret,
      enabled_events: JSON.stringify(data.enabled_events),
      updated_at: db.fn.now()
    };

    const existing = await db('cf_webhook_configs').where({ tenant_id: tenantId }).first();
    if (existing) {
      await db('cf_webhook_configs').where({ tenant_id: tenantId }).update(configData);
    } else {
      await db('cf_webhook_configs').insert({ ...configData, created_at: db.fn.now() });
    }
  }
}
