import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Connection } from '@temporalio/client';

export interface ProbeResult {
  ok: boolean;
  latencyMs?: number;
  error?: string;
}

/**
 * Temporal 业务可用性探针。
 *
 * 独立于 engines/approval/TemporalService：health 模块属于 core 层，
 * 不能依赖 engines。每次探测建立轻量 Connection 调用 getSystemInfo
 * (~10-50ms 健康网络)，2s 超时，立即关闭。
 *
 * 不缓存连接：health 调用频率低（LB/监控约 10s/次），缓存收益小、
 * 风险是连接 stuck 后无法自愈，得不偿失。
 */
@Injectable()
export class TemporalProbeService {
  private readonly logger = new Logger(TemporalProbeService.name);
  private readonly timeoutMs = 2000;

  constructor(private readonly configService: ConfigService) {}

  async probe(): Promise<ProbeResult> {
    const address = this.configService.get<string>('temporal.address', 'localhost:7233');
    const startTime = Date.now();

    let timedOut = false;
    let timer: NodeJS.Timeout | undefined;

    // Connection.connect 可能在 timeout 触发后才 resolve；下面的链式 close
    // 兜底回收所有"输给比赛但最终成功"的连接，避免 socket/gRPC channel 泄漏。
    const connectPromise = Connection.connect({ address });
    connectPromise.then(
      (conn) => {
        if (timedOut) {
          conn.close().catch(() => { /* ignore late-close errors */ });
        }
      },
      () => { /* connect failure already surfaced via race */ },
    );

    try {
      const timeoutPromise = new Promise<never>((_, reject) => {
        timer = setTimeout(() => {
          timedOut = true;
          reject(new Error(`Temporal probe timeout (${this.timeoutMs}ms)`));
        }, this.timeoutMs);
      });

      const conn = await Promise.race([connectPromise, timeoutPromise]);
      await conn.workflowService.getSystemInfo({});
      await conn.close().catch(() => { /* ignore */ });
      return { ok: true, latencyMs: Date.now() - startTime };
    } catch (error: any) {
      this.logger.warn(`Temporal probe failed: ${error.message}`);
      return { ok: false, error: error.message };
    } finally {
      if (timer) clearTimeout(timer);
    }
  }
}
