import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";
import type { IamClient } from "../clients/iam.client.js";
import type { CoreEduClient } from "../clients/core-edu.client.js";
import type { DataAnaClient } from "../clients/data-ana.client.js";
import type { MsgClient } from "../clients/msg.client.js";
import { GraphqlController } from "../entry/graphql.controller.js";
import { contextMiddleware } from "../entry/context.middleware.js";
import { DataLoaderModule } from "../dataloader/dataloader.module.js";
import { DataLoaderFactory } from "../dataloader/dataloader.factory.js";
import { AggregationModule } from "../aggregation/aggregation.module.js";
import { ChildGuard } from "../aggregation/child-guard.js";
import { ClientsModule } from "../clients/clients.module.js";
import { createYogaInstance, type YogaInstance } from "./yoga.js";
import { buildResolvers, type ResolverDeps } from "./resolvers/index.js";

/**
 * GraphQL Module（对齐 02-architecture-design.md §1.4）。
 *
 * 注册：
 * - GraphqlController（POST/GET /graphql）
 * - YOGA_INSTANCE provider（工厂模式，注入 DataLoaderFactory + 下游客户端 + ChildGuard）
 * - contextMiddleware（解析 x-user-id / x-user-roles / x-request-id）
 * - DataLoaderModule（per-request 实例）
 * - AggregationModule（ChildGuard）
 *
 * P4.5：YOGA_INSTANCE factory 组装 ResolverDeps 并调 buildResolvers 生成 resolver map。
 * P5：注入 MSG_CLIENT 用于通知 resolver。
 */
@Module({
  imports: [DataLoaderModule, AggregationModule, ClientsModule],
  controllers: [GraphqlController],
  providers: [
    {
      provide: "YOGA_INSTANCE",
      useFactory: (
        loaderFactory: DataLoaderFactory,
        iamClient: IamClient,
        coreEduClient: CoreEduClient,
        dataAnaClient: DataAnaClient,
        msgClient: MsgClient,
        childGuard: ChildGuard,
      ): YogaInstance => {
        const deps: ResolverDeps = {
          iamClient,
          coreEduClient,
          dataAnaClient,
          msgClient,
          childGuard,
        };
        const resolvers = buildResolvers(deps);
        return createYogaInstance(loaderFactory, resolvers);
      },
      inject: [
        DataLoaderFactory,
        "IAM_CLIENT",
        "CORE_EDU_CLIENT",
        "DATA_ANA_CLIENT",
        "MSG_CLIENT",
        ChildGuard,
      ],
    },
  ],
})
export class GraphqlModule implements NestModule {
  configure(consumer: MiddlewareConsumer): void {
    consumer.apply(contextMiddleware).forRoutes("graphql");
  }
}
