import { Logger } from '@nestjs/common';
import { WebSocketGateway, WebSocketServer, SubscribeMessage, OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
import { Server, WebSocket } from 'ws';
import { IncomingMessage } from 'http';
import { EventsService } from './events.service';
import { ApiTier } from '../../common/guards/api-key.guard';

/**
 * WebSocket 事件网关
 *
 * 认证方式：连接时通过 query param 或 header 传递 API Key
 *   - ws://host:3020/v1/ws/events?apiKey=gx_inst_xxx
 *   - 或 header: X-API-Key: gx_inst_xxx
 *
 * 最低权限要求：institutional 级别（指南 §3.2）
 */
@WebSocketGateway({ path: '/v1/ws/events' })
export class EventsGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer() server: Server;
  private readonly logger = new Logger(EventsGateway.name);
  private readonly authenticatedClients = new WeakSet<WebSocket>();

  constructor(private readonly eventsService: EventsService) {}

  afterInit() {
    this.eventsService.startListening((event) => {
      this.server.clients.forEach((client) => {
        if (client.readyState === WebSocket.OPEN && this.authenticatedClients.has(client)) {
          client.send(JSON.stringify(event));
        }
      });
    });
  }

  handleConnection(client: WebSocket, req: IncomingMessage) {
    // 从 query param 或 header 获取 API Key
    const url = new URL(req.url || '', `http://${req.headers.host}`);
    const apiKey = url.searchParams.get('apiKey') || req.headers['x-api-key'] as string;

    if (!apiKey) {
      client.send(JSON.stringify({ type: 'error', message: 'Missing API key. Pass via ?apiKey= or X-API-Key header' }));
      client.close(4001, 'Unauthorized: missing API key');
      return;
    }

    const tier = this.resolveApiKeyTier(apiKey);
    if (!tier) {
      client.send(JSON.stringify({ type: 'error', message: 'Invalid API key' }));
      client.close(4001, 'Unauthorized: invalid API key');
      return;
    }

    // WebSocket 需要 institutional 或更高权限
    const tierHierarchy: ApiTier[] = ['public', 'institutional', 'regulatory', 'internal'];
    if (tierHierarchy.indexOf(tier) < tierHierarchy.indexOf('institutional')) {
      client.send(JSON.stringify({ type: 'error', message: 'WebSocket requires institutional tier or above' }));
      client.close(4003, 'Forbidden: insufficient API tier');
      return;
    }

    this.authenticatedClients.add(client);
    this.logger.log(`WebSocket client connected (tier: ${tier})`);
    client.send(JSON.stringify({ type: 'connected', chainId: 8888, tier }));
  }

  handleDisconnect(client: WebSocket) {
    this.authenticatedClients.delete(client);
  }

  @SubscribeMessage('subscribe')
  handleSubscribe(client: WebSocket, data: { eventType: string }) {
    if (!this.authenticatedClients.has(client)) {
      return { event: 'error', data: { message: 'Not authenticated' } };
    }
    // 支持订阅特定事件类型: newBlock, largeTx, compliance, couponMint
    return { event: 'subscribed', data: { eventType: data.eventType } };
  }

  private resolveApiKeyTier(apiKey: string): ApiTier | null {
    if (apiKey.startsWith('gx_internal_')) return 'internal';
    if (apiKey.startsWith('gx_reg_')) return 'regulatory';
    if (apiKey.startsWith('gx_inst_')) return 'institutional';
    if (apiKey.startsWith('gx_pub_')) return 'public';
    return null;
  }
}
