import db from '../config/database';
import { logger } from '../utils/logger';
import RedisService from './RedisService';
import { BullMQService } from './BullMQService';

// 事件接口
export interface Event {
  id: string;
  type: string;
  data: any;
  metadata: EventMetadata;
  createdAt: Date;
}

export interface EventMetadata {
  source: string;
  correlationId: string;
  timestamp: number;
  version: string;
}

// 事件处理器类型
export type EventHandler = (event: Event) => Promise<void>;

// 订阅接口
export interface Subscription {
  id: string;
  topic: string;
  handler: EventHandler;
  filter?: EventFilter;
  createdAt: Date;
}

// 事件过滤接口
export interface EventFilter {
  [key: string]: any;
}

// 路由规则接口
export interface RouteRule {
  id: string;
  topic: string;
  condition: EventFilter;
  destinations: string[];
  createdAt: Date;
}

// 健康状态接口
export interface HealthStatus {
  status: 'healthy' | 'unhealthy';
  message?: string;
  metrics: {
    eventCount: number;
    subscriptionCount: number;
    queueSize: number;
  };
}

/**
 * [CORE_EVT_01] 事件总线服务
 * @description 分布式事件驱动架构，支持事件发布、订阅、路由
 */
export class EventBusService {
  private static readonly EVENT_TABLE = 'cf_events';
  private static readonly SUBSCRIPTION_TABLE = 'cf_event_subscriptions';
  private static readonly ROUTE_RULE_TABLE = 'cf_event_route_rules';
  private static readonly DEAD_LETTER_TABLE = 'cf_event_dead_letters';
  
  private static subscriptions: Map<string, Subscription> = new Map();
  private static routeRules: RouteRule[] = [];

  /**
   * 初始化数据库表
   */
  static async initTable() {
    // 创建事件表
    const hasEventTable = await db.schema.hasTable(this.EVENT_TABLE);
    if (!hasEventTable) {
      console.log(`📦 Creating ${this.EVENT_TABLE} table...`);
      await db.schema.createTable(this.EVENT_TABLE, (table) => {
        table.string('id', 64).primary();
        table.string('type', 128).index();
        table.json('data').notNullable();
        table.json('metadata').notNullable();
        table.timestamps(true, true);
      });
    }

    // 创建订阅表
    const hasSubscriptionTable = await db.schema.hasTable(this.SUBSCRIPTION_TABLE);
    if (!hasSubscriptionTable) {
      console.log(`📦 Creating ${this.SUBSCRIPTION_TABLE} table...`);
      await db.schema.createTable(this.SUBSCRIPTION_TABLE, (table) => {
        table.string('id', 64).primary();
        table.string('topic', 128).index();
        table.string('endpoint', 512).nullable();
        table.json('filter').nullable();
        table.timestamps(true, true);
      });
    }

    // 创建路由规则表
    const hasRouteRuleTable = await db.schema.hasTable(this.ROUTE_RULE_TABLE);
    if (!hasRouteRuleTable) {
      console.log(`📦 Creating ${this.ROUTE_RULE_TABLE} table...`);
      await db.schema.createTable(this.ROUTE_RULE_TABLE, (table) => {
        table.string('id', 64).primary();
        table.string('topic', 128).index();
        table.json('condition').notNullable();
        table.json('destinations').notNullable();
        table.timestamps(true, true);
      });
    }

    // 创建死信表
    const hasDeadLetterTable = await db.schema.hasTable(this.DEAD_LETTER_TABLE);
    if (!hasDeadLetterTable) {
      console.log(`📦 Creating ${this.DEAD_LETTER_TABLE} table...`);
      await db.schema.createTable(this.DEAD_LETTER_TABLE, (table) => {
        table.string('id', 64).primary();
        table.string('event_id', 64).index();
        table.string('topic', 128).index();
        table.json('event_data').notNullable();
        table.string('error', 1024).notNullable();
        table.integer('retry_count').defaultTo(0);
        table.timestamps(true, true);
      });
    }

    // 加载路由规则
    await this.loadRouteRules();
  }

  /**
   * 加载路由规则
   */
  private static async loadRouteRules() {
    try {
      const rules = await db(this.ROUTE_RULE_TABLE).select('*');
      this.routeRules = rules.map(rule => ({
        id: rule.id,
        topic: rule.topic,
        condition: rule.condition,
        destinations: rule.destinations,
        createdAt: rule.created_at
      }));
      logger.info(`[EventBus] Loaded ${this.routeRules.length} route rules`);
    } catch (error) {
      logger.error(`[EventBus] Failed to load route rules: ${error}`);
    }
  }

  /**
   * 发布事件
   */
  static async publish(event: Partial<Event>): Promise<Event> {
    const eventId = `EVT-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
    const now = new Date();
    
    const fullEvent: Event = {
      id: eventId,
      type: event.type!,
      data: event.data!,
      metadata: {
        source: event.metadata?.source || 'unknown',
        correlationId: event.metadata?.correlationId || eventId,
        timestamp: event.metadata?.timestamp || now.getTime(),
        version: event.metadata?.version || '1.0'
      },
      createdAt: now
    };

    logger.info(`[EventBus] Publishing event: ${fullEvent.type} (${fullEvent.id})`);

    try {
      // 存储事件到数据库
      await db(this.EVENT_TABLE).insert({
        id: fullEvent.id,
        type: fullEvent.type,
        data: fullEvent.data,
        metadata: fullEvent.metadata,
        created_at: fullEvent.createdAt,
        updated_at: fullEvent.createdAt
      });

      // 路由事件
      const destinations = this.routeEvent(fullEvent);
      logger.info(`[EventBus] Event ${fullEvent.id} routed to ${destinations.length} destinations`);

      // 发送到消息队列
      await BullMQService.addJob('event.published', {
        event: fullEvent,
        destinations
      });

      // 通知本地订阅者
      await this.notifyLocalSubscribers(fullEvent);

      return fullEvent;
    } catch (error) {
      logger.error(`[EventBus] Failed to publish event: ${error}`);
      throw error;
    }
  }

  /**
   * 订阅事件
   */
  static async subscribe(topic: string, handler: EventHandler, filter?: EventFilter): Promise<Subscription> {
    const subscriptionId = `SUB-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
    const subscription: Subscription = {
      id: subscriptionId,
      topic,
      handler,
      filter,
      createdAt: new Date()
    };

    this.subscriptions.set(subscriptionId, subscription);
    logger.info(`[EventBus] New subscription: ${topic} (${subscriptionId})`);

    return subscription;
  }

  /**
   * 取消订阅
   */
  static async unsubscribe(subscription: Subscription): Promise<void> {
    this.subscriptions.delete(subscription.id);
    logger.info(`[EventBus] Unsubscribed: ${subscription.topic} (${subscription.id})`);
  }

  /**
   * 路由事件
   */
  private static routeEvent(event: Event): string[] {
    const destinations: string[] = [];

    this.routeRules.forEach(rule => {
      if (rule.topic === event.type && this.matchesCondition(event, rule.condition)) {
        destinations.push(...rule.destinations);
      }
    });

    return destinations;
  }

  /**
   * 检查事件是否匹配条件
   */
  private static matchesCondition(event: Event, condition: EventFilter): boolean {
    for (const [key, value] of Object.entries(condition)) {
      const eventValue = this.getNestedValue(event, key);
      if (eventValue !== value) {
        return false;
      }
    }
    return true;
  }

  /**
   * 获取嵌套值
   */
  private static getNestedValue(obj: any, path: string): any {
    return path.split('.').reduce((acc, key) => acc?.[key], obj);
  }

  /**
   * 通知本地订阅者
   */
  private static async notifyLocalSubscribers(event: Event): Promise<void> {
    Array.from(this.subscriptions.values()).forEach(async (subscription) => {
      if (subscription.topic === event.type && (!subscription.filter || this.matchesCondition(event, subscription.filter))) {
        try {
          await subscription.handler(event);
        } catch (error) {
          logger.error(`[EventBus] Failed to notify subscriber ${subscription.id}: ${error}`);
          await this.handleDeadLetter(event, error as Error);
        }
      }
    });
  }

  /**
   * 处理死信
   */
  private static async handleDeadLetter(event: Event, error: Error): Promise<void> {
    const deadLetterId = `DLQ-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
    
    await db(this.DEAD_LETTER_TABLE).insert({
      id: deadLetterId,
      event_id: event.id,
      topic: event.type,
      event_data: event,
      error: error.message,
      retry_count: 0,
      created_at: new Date(),
      updated_at: new Date()
    });

    logger.warn(`[EventBus] Event ${event.id} moved to dead letter queue: ${error.message}`);
  }

  /**
   * 注册路由规则
   */
  static async registerRouteRule(rule: Omit<RouteRule, 'id' | 'createdAt'>): Promise<RouteRule> {
    const ruleId = `RULE-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
    const newRule: RouteRule = {
      id: ruleId,
      ...rule,
      createdAt: new Date()
    };

    await db(this.ROUTE_RULE_TABLE).insert({
      id: newRule.id,
      topic: newRule.topic,
      condition: newRule.condition,
      destinations: newRule.destinations,
      created_at: newRule.createdAt,
      updated_at: newRule.createdAt
    });

    this.routeRules.push(newRule);
    logger.info(`[EventBus] Registered route rule: ${newRule.topic} (${newRule.id})`);

    return newRule;
  }

  /**
   * 获取事件历史
   */
  static async getEventHistory(filter: { type?: string; startDate?: Date; endDate?: Date; source?: string; correlationId?: string }): Promise<Event[]> {
    let query = db(this.EVENT_TABLE).select('*');

    if (filter.type) {
      query = query.where('type', filter.type);
    }

    if (filter.startDate) {
      query = query.where('created_at', '>=', filter.startDate);
    }

    if (filter.endDate) {
      query = query.where('created_at', '<=', filter.endDate);
    }

    if (filter.source) {
      query = query.where('metadata', '@>', { source: filter.source });
    }

    if (filter.correlationId) {
      query = query.where('metadata', '@>', { correlationId: filter.correlationId });
    }

    const events = await query.orderBy('created_at', 'desc');
    return events.map(event => ({
      id: event.id,
      type: event.type,
      data: event.data,
      metadata: event.metadata,
      createdAt: event.created_at
    }));
  }

  /**
   * 健康检查
   */
  static async healthCheck(): Promise<HealthStatus> {
    try {
      // 检查数据库连接
      await db.raw('SELECT 1');

      // 获取统计信息
      const eventCount = await db(this.EVENT_TABLE).count('id as count').first();
      const subscriptionCount = await db(this.SUBSCRIPTION_TABLE).count('id as count').first();
      const queueSize = await BullMQService.getQueueSize('event.published');

      return {
        status: 'healthy',
        metrics: {
          eventCount: parseInt((eventCount as any).count || '0'),
          subscriptionCount: parseInt((subscriptionCount as any).count || '0'),
          queueSize: queueSize || 0
        }
      };
    } catch (error) {
      return {
        status: 'unhealthy',
        message: error instanceof Error ? error.message : 'Unknown error',
        metrics: {
          eventCount: 0,
          subscriptionCount: 0,
          queueSize: 0
        }
      };
    }
  }

  /**
   * 重试死信事件
   */
  static async retryDeadLetter(deadLetterId: string): Promise<boolean> {
    try {
      const deadLetter = await db(this.DEAD_LETTER_TABLE).where('id', deadLetterId).first();
      if (!deadLetter) {
        return false;
      }

      const event = deadLetter.event_data;
      await this.publish(event);

      // 更新重试计数
      await db(this.DEAD_LETTER_TABLE).where('id', deadLetterId).update({
        retry_count: deadLetter.retry_count + 1,
        updated_at: new Date()
      });

      logger.info(`[EventBus] Retried dead letter event: ${event.id}`);
      return true;
    } catch (error) {
      logger.error(`[EventBus] Failed to retry dead letter: ${error}`);
      return false;
    }
  }

  /**
   * 清理过期事件
   */
  static async cleanExpiredEvents(days: number = 30): Promise<number> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - days);

    const deleted = await db(this.EVENT_TABLE)
      .where('created_at', '<', cutoffDate)
      .del();

    logger.info(`[EventBus] Cleaned ${deleted} expired events`);
    return deleted;
  }
}
