import { Module } from "@nestjs/common";
import { env } from "../config/env.js";
import { createGrpcClient } from "./grpc/grpc.factory.js";
import type { IamClient } from "./iam.client.js";
import { GrpcIamClient, MockIamClient } from "./iam.client.js";
import type { CoreEduClient } from "./core-edu.client.js";
import { GrpcCoreEduClient, MockCoreEduClient } from "./core-edu.client.js";
import type { DataAnaClient } from "./data-ana.client.js";
import { GrpcDataAnaClient, MockDataAnaClient } from "./data-ana.client.js";
import type { MsgClient } from "./msg.client.js";
import { GrpcMsgClient, MockMsgClient } from "./msg.client.js";
import type { PushHttpClient } from "./http/push-http.client.js";
import {
  MockPushHttpClient,
  HttpPushHttpClient,
} from "./http/push-http.client.js";

/**
 * 下游客户端模块（对齐 02-architecture-design.md §1.4 clients/）。
 *
 * 根据 DEV_MODE 切换 mock / gRPC 实现：
 * - DEV_MODE=true（默认）：Mock 客户端
 * - DEV_MODE=false：gRPC / HTTP 客户端
 *
 * 上游就绪后设置 DEV_MODE=false 即可切换到真实调用。
 */

// IAM 原始 gRPC client 类型（proto-loader 动态加载，无静态类型）
interface IamGrpcService {
  getUserInfo(
    req: unknown,
    cb: (err: Error | null, res: unknown) => void,
  ): void;
}

@Module({
  providers: [
    {
      provide: "IAM_CLIENT",
      useFactory: (): IamClient => {
        if (env.DEV_MODE) {
          return new MockIamClient();
        }
        const raw = createGrpcClient<IamGrpcService>({
          protoFile: "iam.proto",
          packageName: "next_edu_cloud.iam.v1",
          serviceName: "IamService",
          target: env.IamGrpcTarget,
        });
        return new GrpcIamClient(raw);
      },
    },
    {
      provide: "CORE_EDU_CLIENT",
      useFactory: (): CoreEduClient => {
        if (env.DEV_MODE) {
          return new MockCoreEduClient();
        }
        // core_edu.proto 定义了三个独立 service，需分别创建 client
        const gradeClient = createGrpcClient({
          protoFile: "core_edu.proto",
          packageName: "next_edu_cloud.core_edu.v1",
          serviceName: "GradeService",
          target: env.CoreEduGrpcTarget,
        });
        const homeworkClient = createGrpcClient({
          protoFile: "core_edu.proto",
          packageName: "next_edu_cloud.core_edu.v1",
          serviceName: "HomeworkService",
          target: env.CoreEduGrpcTarget,
        });
        const examClient = createGrpcClient({
          protoFile: "core_edu.proto",
          packageName: "next_edu_cloud.core_edu.v1",
          serviceName: "ExamService",
          target: env.CoreEduGrpcTarget,
        });
        return new GrpcCoreEduClient(gradeClient, homeworkClient, examClient);
      },
    },
    {
      provide: "DATA_ANA_CLIENT",
      useFactory: (): DataAnaClient => {
        if (env.DEV_MODE) {
          return new MockDataAnaClient();
        }
        const raw = createGrpcClient({
          protoFile: "analytics.proto",
          packageName: "next_edu_cloud.analytics.v1",
          serviceName: "AnalyticsService",
          target: env.DataAnaGrpcTarget,
        });
        return new GrpcDataAnaClient(raw);
      },
    },
    {
      provide: "MSG_CLIENT",
      useFactory: (): MsgClient => {
        if (env.DEV_MODE) {
          return new MockMsgClient();
        }
        const raw = createGrpcClient({
          protoFile: "msg.proto",
          packageName: "next_edu_cloud.msg.v1",
          serviceName: "NotificationService",
          target: env.MsgGrpcTarget,
        });
        return new GrpcMsgClient(raw);
      },
    },
    {
      provide: "PUSH_HTTP_CLIENT",
      useFactory: (): PushHttpClient => {
        if (env.DEV_MODE) {
          return new MockPushHttpClient();
        }
        return new HttpPushHttpClient();
      },
    },
  ],
  exports: [
    "IAM_CLIENT",
    "CORE_EDU_CLIENT",
    "DATA_ANA_CLIENT",
    "MSG_CLIENT",
    "PUSH_HTTP_CLIENT",
  ],
})
export class ClientsModule {}
