/**
 * Dashboard Resolver - studentDashboard Query.
 *
 * 仲裁依据:
 *   - student-bff.schema.graphql Query.studentDashboard
 *   - president-final-rulings §2.8 (Dashboard Query Resolver P2 即定型, 内部按阶段扩展)
 *   - president-final-rulings §2.6 (降级模式方案 B: data 内 degraded=true)
 *   - coord-final-decisions §2 B6 (Redis 5-30s 短缓存)
 *
 * 聚合:
 *   - iam.GetUserInfo (用户基础信息)
 *   - core-edu.ListHomeworkByStudent (待办作业)
 *   - core-edu.ListExamsByClass (即将到来的考试)
 *   - core-edu.ListGradesByStudent (最近一次成绩)
 *   - data-ana.GetStudentDashboard (P4 学情汇总, P3 返回 null)
 *   - msg.ListNotifications (未读通知数, P5)
 *
 * 缓存: student:dashboard:{userId} TTL 15s
 */
import type { StudentBffContext } from "../../shared/graphql/yoga.js";
import type { DownstreamResponse } from "@edu/shared-ts/bff";
import {
  ok,
  fail,
  degraded,
  DegradedReason,
} from "../../shared/action-state.js";
import { CacheTTL } from "../../shared/cache/cache.module.js";
import { UnauthorizedError } from "../../shared/errors/application-error.js";

export const dashboardResolvers = {
  Query: {
    /**
     * studentDashboard: 学生首页聚合.
     * @permission STUDENT_DASHBOARD_READ
     * @dataScope OWN
     */
    async studentDashboard(
      _parent: unknown,
      _args: unknown,
      ctx: StudentBffContext,
    ): Promise<unknown> {
      if (!ctx.userId) {
        throw new UnauthorizedError();
      }

      // 缓存命中检查
      const cached = await ctx.cache.get<unknown>("dashboard", ctx.userId);
      if (cached) {
        return ok(cached, {
          traceId: ctx.traceId,
          cachedAt: new Date().toISOString(),
        });
      }

      // 并行调用下游 (Promise.allSettled 容错)
      const results = await ctx.downstream.callAll([
        {
          service: "iam",
          method: "GetUserInfo",
          request: { userId: ctx.userId },
          options: {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        },
        {
          service: "core-edu",
          method: "ListHomeworkByStudent",
          request: { studentId: ctx.userId, status: "pending" },
          options: {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        },
        {
          service: "core-edu",
          method: "ListExamsByClass",
          request: { studentId: ctx.userId },
          options: {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        },
        {
          service: "core-edu",
          method: "ListGradesByStudent",
          request: { studentId: ctx.userId, page: 1, pageSize: 1 },
          options: {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        },
        {
          service: "data-ana",
          method: "GetStudentDashboard",
          request: { studentId: ctx.userId },
          options: {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        },
      ] as const);

      const [
        userInfoResp,
        homeworkResp,
        examsResp,
        gradesResp,
        dashboardAnaResp,
      ] = results as [
        DownstreamResponse<unknown>,
        DownstreamResponse<unknown>,
        DownstreamResponse<unknown>,
        DownstreamResponse<unknown>,
        DownstreamResponse<unknown>,
      ];

      // 必需字段失败检查
      if (!userInfoResp.success) {
        return fail(
          "BFF_STUDENT_BAD_GATEWAY",
          `Failed to fetch user info: ${userInfoResp.error.message}`,
          {
            i18nKey: "error.bffStudent.bad_gateway",
            traceId: ctx.traceId,
          },
        );
      }

      const userInfo = userInfoResp.data as {
        userId: string;
        name: string;
        avatar: string | null;
        classId: string;
        className: string;
        grade: string;
      };

      // 容错聚合: 各字段独立降级
      const degradedFields: string[] = [];
      const pendingHomework = homeworkResp.success
        ? ((homeworkResp.data as { homework: unknown[] }).homework ?? [])
        : (degradedFields.push("pendingHomework"), []);
      const upcomingExams = examsResp.success
        ? ((examsResp.data as { exams: unknown[] }).exams ?? [])
        : (degradedFields.push("upcomingExams"), []);
      const lastGrade = gradesResp.success
        ? (((gradesResp.data as { grades: unknown[] }).grades ?? [])[0] ?? null)
        : (degradedFields.push("lastGrade"), null);
      const analyticsSummary = dashboardAnaResp.success
        ? dashboardAnaResp.data
        : (degradedFields.push("analyticsSummary"), null);

      const data = {
        user: {
          id: userInfo.userId,
          name: userInfo.name,
          avatar: userInfo.avatar,
          grade: userInfo.grade,
          class: { id: userInfo.classId, name: userInfo.className },
        },
        pendingHomework,
        upcomingExams,
        lastGrade,
        analyticsSummary,
        unreadNotifications: 0, // P5 msg 服务启用后填充
      };

      // 写缓存
      await ctx.cache.set("dashboard", data, CacheTTL.DASHBOARD, ctx.userId);

      if (degradedFields.length > 0) {
        return degraded(
          data,
          DegradedReason.DOWNSTREAM_PARTIAL_FAILURE,
          degradedFields,
          { traceId: ctx.traceId },
        );
      }

      return ok(data, { traceId: ctx.traceId });
    },
  },
};
