import type { IResolvers } from "@graphql-tools/utils";
import { GraphQLScalarType, Kind } from "graphql";
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 type { ChildGuard } from "../../aggregation/child-guard.js";
import { buildDashboardResolver } from "./dashboard.resolver.js";
import {
  buildChildAnalyticsFieldResolver,
  buildChildAnalyticsQueryResolver,
  buildChildExamsFieldResolver,
  buildChildExamsQueryResolver,
  buildChildGradesFieldResolver,
  buildChildHomeworkFieldResolver,
  buildChildHomeworkQueryResolver,
  buildChildLastGradeFieldResolver,
  buildChildQueryResolver,
  buildChildrenQueryResolver,
} from "./child.resolver.js";
import { buildChildGradesQueryResolver } from "./grade.resolver.js";
import { buildSelectChildMutationResolver } from "./select-child.resolver.js";
import {
  buildMeQueryResolver,
  buildViewportsQueryResolver,
} from "./me.resolver.js";
import {
  buildNotificationsQueryResolver,
  buildMarkNotificationReadMutationResolver,
} from "./notification.resolver.js";
import {
  buildNotificationPreferencesQueryResolver,
  buildUpdateNotificationPreferencesMutationResolver,
} from "./notification-preference.resolver.js";

/**
 * Resolver 依赖注入容器。
 *
 * 由 GraphqlModule 在 YOGA_INSTANCE factory 中组装，
 * 传入 4 个下游客户端 + ChildGuard。
 */
export interface ResolverDeps {
  iamClient: IamClient;
  coreEduClient: CoreEduClient;
  dataAnaClient: DataAnaClient;
  msgClient: MsgClient;
  childGuard: ChildGuard;
}

/**
 * DateTime 标量：ISO 8601 字符串 ↔ JS Date / string。
 */
const DateTimeScalar = new GraphQLScalarType({
  name: "DateTime",
  description: "ISO 8601 date-time string",

  serialize(value: unknown): string {
    if (value instanceof Date) {
      return value.toISOString();
    }
    if (typeof value === "string") {
      return value;
    }
    if (typeof value === "number") {
      return new Date(value).toISOString();
    }
    throw new Error(`DateTime scalar: cannot serialize ${typeof value}`);
  },

  parseValue(value: unknown): string {
    if (typeof value === "string") {
      const date = new Date(value);
      if (Number.isNaN(date.getTime())) {
        throw new Error(`DateTime scalar: invalid date string "${value}"`);
      }
      return value;
    }
    if (typeof value === "number") {
      return new Date(value).toISOString();
    }
    throw new Error(`DateTime scalar: cannot parse ${typeof value}`);
  },

  parseLiteral(ast): string {
    if (ast.kind === Kind.STRING) {
      const date = new Date(ast.value);
      if (Number.isNaN(date.getTime())) {
        throw new Error(`DateTime scalar: invalid date string "${ast.value}"`);
      }
      return ast.value;
    }
    if (ast.kind === Kind.INT) {
      return new Date(Number(ast.value)).toISOString();
    }
    throw new Error(`DateTime scalar: cannot parse literal ${ast.kind}`);
  },
});

/**
 * 构建 GraphQL resolvers（对齐 02-architecture-design.md §4.2 SDL）。
 *
 * 组装顺序：
 * 1. DateTime scalar
 * 2. Query resolvers（11 fields）
 * 3. Mutation resolvers（3 fields）
 * 4. Child type field resolvers（5 lazy-loaded fields）
 *
 * notifications / notificationPreferences / markNotificationRead / updateNotificationPreferences
 * 为 P5 桩实现，P5 msg 接入后替换。
 */
export function buildResolvers(deps: ResolverDeps): IResolvers {
  return {
    DateTime: DateTimeScalar,

    Query: {
      dashboard: buildDashboardResolver(deps),
      viewports: buildViewportsQueryResolver(deps),
      me: buildMeQueryResolver(deps),
      children: buildChildrenQueryResolver(deps),
      child: buildChildQueryResolver(deps),
      childGrades: buildChildGradesQueryResolver(deps),
      childHomework: buildChildHomeworkQueryResolver(deps),
      childExams: buildChildExamsQueryResolver(deps),
      childAnalytics: buildChildAnalyticsQueryResolver(deps),

      // P5 通知 resolvers
      notifications: buildNotificationsQueryResolver(deps),
      notificationPreferences: buildNotificationPreferencesQueryResolver(deps),
    },

    Mutation: {
      selectChild: buildSelectChildMutationResolver(deps),

      // P5 通知 mutations
      markNotificationRead: buildMarkNotificationReadMutationResolver(deps),
      updateNotificationPreferences:
        buildUpdateNotificationPreferencesMutationResolver(deps),
    },

    Child: {
      lastGrade: buildChildLastGradeFieldResolver(),
      grades: buildChildGradesFieldResolver(),
      homework: buildChildHomeworkFieldResolver(),
      exams: buildChildExamsFieldResolver(),
      analytics: buildChildAnalyticsFieldResolver(deps),
    },
  };
}
