// IamClient gRPC 实现（B2 裁决：首次实现即 gRPC）
// iam.proto 现状仅 GetUserInfo，GetViewports/GetEffectivePermissions 待 coord 补全
// 未就绪 RPC 降级 mock + warning 日志（president §2.6 降级模式 B）
import { Injectable } from "@nestjs/common";
import type * as grpc from "@grpc/grpc-js";
import { BaseDownstreamClient } from "../base.client.js";
import {
  createGrpcMetadata,
  getGrpcClient,
  checkGrpcHealth,
} from "../grpc/grpc.factory.js";
import type { CallContext } from "../types.js";
import type { IamClient } from "./iam-client.interface.js";
import type {
  UserInfo,
  ViewportItem,
  EffectivePermissions,
} from "./iam.types.js";
import { IamMockClient } from "./iam-mock.client.js";

@Injectable()
export class IamGrpcClient extends BaseDownstreamClient implements IamClient {
  readonly serviceName = "iam" as const;
  private readonly mock: IamMockClient;

  constructor() {
    super();
    this.initLogger();
    // mock 用于未就绪 RPC 的降级（proto 未定义的 RPC 走 mock + warning）
    this.mock = new IamMockClient();
  }

  async getUserInfo(ctx: CallContext): Promise<UserInfo> {
    return this.callGrpc("GetUserInfo", async () => {
      const client = getGrpcClient("iam") as unknown as {
        getUserInfo(
          req: { userId: string },
          meta: grpc.Metadata,
          cb: (err: grpc.ServiceError | null, res: UserInfo) => void,
        ): void;
      };
      const meta = createGrpcMetadata(ctx.userId, ctx.traceId);
      return new Promise<UserInfo>((resolve, reject) => {
        client.getUserInfo({ userId: ctx.userId }, meta, (err, res) => {
          if (err) reject(err);
          else resolve(res);
        });
      });
    });
  }

  async getViewports(ctx: CallContext): Promise<ViewportItem[]> {
    // iam.proto 暂无 GetViewports RPC，降级 mock + warning（待 coord 补全）
    this.log.warn(
      { rpc: "GetViewports", reason: "RPC not in iam.proto yet" },
      "Downstream RPC not ready, falling back to mock",
    );
    return this.mock.getViewports(ctx);
  }

  async getEffectivePermissions(
    ctx: CallContext,
  ): Promise<EffectivePermissions> {
    // iam.proto 暂无 GetEffectivePermissions RPC，降级 mock + warning
    this.log.warn(
      { rpc: "GetEffectivePermissions", reason: "RPC not in iam.proto yet" },
      "Downstream RPC not ready, falling back to mock",
    );
    return this.mock.getEffectivePermissions(ctx);
  }

  async checkHealth(): Promise<{
    serving: boolean;
    latencyMs: number;
    error?: string;
  }> {
    return checkGrpcHealth("iam");
  }
}
