/**
 * Homework Resolver - myHomework Query + submitHomework Mutation.
 *
 * 仲裁依据:
 *   - student-bff.schema.graphql Query.myHomework + Mutation.submitHomework
 *   - coord-final-decisions §2 B4 (强制自我越权防御, 学生只能查/操作自己数据)
 *   - coord-final-decisions §2 B6 (Redis 5-30s 短缓存)
 *   - president-final-rulings §2.9 (越权防御 P3 实现方式: 方案 D)
 */
import { z } from "zod";
import type { StudentBffContext } from "../../shared/graphql/yoga.js";
import { ok, fail } from "../../shared/action-state.js";
import { CacheTTL } from "../../shared/cache/cache.module.js";
import {
  UnauthorizedError,
  ValidationError,
} from "../../shared/errors/application-error.js";
import { assertOwnData } from "../guards/authorization.guard.js";

/**
 * 提交作业输入 Zod schema (G7 Zod 验证).
 */
const SubmitHomeworkInputSchema = z.object({
  homeworkId: z.string().min(1),
  studentId: z.string().min(1).optional(),
  answers: z
    .array(
      z.object({
        questionId: z.string().min(1),
        content: z.string().min(1).max(10000),
        attachments: z.array(z.string().url()).max(5).optional(),
      }),
    )
    .min(1)
    .max(100),
});

export const homeworkResolvers = {
  Query: {
    /**
     * myHomework: 我的作业列表.
     * @permission STUDENT_HOMEWORK_READ
     * @dataScope OWN
     */
    async myHomework(
      _parent: unknown,
      args: { status?: string; classId?: string },
      ctx: StudentBffContext,
    ): Promise<unknown> {
      if (!ctx.userId) {
        throw new UnauthorizedError();
      }

      // 缓存命中
      const cacheKey = ctx.userId + (args.classId ? `:${args.classId}` : "");
      const cached = await ctx.cache.get<unknown>("homework", cacheKey);
      if (cached) {
        return ok(cached, {
          traceId: ctx.traceId,
          cachedAt: new Date().toISOString(),
        });
      }

      try {
        const result = await ctx.downstream.call(
          "core-edu",
          "ListHomeworkByStudent",
          {
            studentId: ctx.userId,
            status: args.status,
            classId: args.classId,
          },
          {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        );

        const data = result as { homework: unknown[] };
        await ctx.cache.set("homework", data, CacheTTL.HOMEWORK, cacheKey);
        return ok(data, { traceId: ctx.traceId });
      } catch (err) {
        return fail(
          "BFF_STUDENT_BAD_GATEWAY",
          `Failed to fetch homework: ${(err as Error).message}`,
          { i18nKey: "error.bffStudent.bad_gateway", traceId: ctx.traceId },
        );
      }
    },
  },

  Mutation: {
    /**
     * submitHomework: 提交作业.
     * @permission STUDENT_HOMEWORK_SUBMIT
     * @dataScope OWN (B4 强制 studentId = userId)
     */
    async submitHomework(
      _parent: unknown,
      args: { input: unknown },
      ctx: StudentBffContext,
    ): Promise<unknown> {
      if (!ctx.userId) {
        throw new UnauthorizedError();
      }

      // G7 Zod 校验
      const parseResult = SubmitHomeworkInputSchema.safeParse(args.input);
      if (!parseResult.success) {
        throw new ValidationError(
          "Invalid submitHomework input",
          parseResult.error.flatten(),
        );
      }
      const input = parseResult.data;

      // B4 自我越权防御: body 中 studentId 必须 = JWT userId
      assertOwnData(ctx.userId, input.studentId);

      try {
        const result = await ctx.downstream.call(
          "core-edu",
          "SubmitHomework",
          {
            homeworkId: input.homeworkId,
            studentId: ctx.userId,
            answers: input.answers,
          },
          {
            traceId: ctx.traceId,
            metadata: { "x-user-id": ctx.userId },
          },
        );

        // 失效相关缓存
        await ctx.cache.invalidate("homework", ctx.userId);
        await ctx.cache.invalidate("dashboard", ctx.userId);

        const data = result as {
          submissionId: string;
          homeworkId: string;
          submittedAt: string;
          status: string;
        };
        return ok(data, { traceId: ctx.traceId });
      } catch (err) {
        return fail(
          "BFF_STUDENT_BAD_GATEWAY",
          `Failed to submit homework: ${(err as Error).message}`,
          { i18nKey: "error.bffStudent.bad_gateway", traceId: ctx.traceId },
        );
      }
    },
  },
};
