import type { Request, Response } from "express";
import { UnauthorizedError } from "../shared/errors/application-error.js";
import { logger } from "../shared/observability/logger.js";
import type { Loaders } from "../dataloader/loaders.js";

/**
 * ParentSession 值对象（对齐 02-architecture-design.md §2.2）。
 *
 * 每次请求重建，不跨请求保留状态（符合 004 §12.1 无状态约束）。
 * 由前端在 GraphQL query 参数传入 requestedChildId（方案 A）。
 */
export interface ParentSession {
  /** 从 x-user-id 头解析（Gateway JWT 注入） */
  parentId: string;
  /** 从 x-user-roles 头解析（Gateway JWT 注入，逗号分隔） */
  roles: string[];
  /** 家长固定 CHILDREN（004 §5.4） */
  dataScope: "CHILDREN";
  /** 从 GraphQL query 参数解析（前端传入，可选） */
  requestedChildId?: string;
  /** 从 x-request-id 头解析（Gateway 注入） */
  traceId: string;
}

export interface GraphqlContext {
  session: ParentSession;
  req: Request;
  res: Response;
  /** Per-request DataLoader 实例集合（防 N+1） */
  loaders: Loaders;
}

/**
 * 从 Express Request 构建 ParentSession。
 *
 * 校验：x-user-id 必须存在（U4 仲裁：BFF 仅校验 x-user-id），缺失抛 401。
 * x-user-roles / x-request-id 缺失时降级为空数组 / "unknown"。
 */
export function buildSession(req: Request): ParentSession {
  const parentIdHeader = req.headers["x-user-id"];
  const parentId = typeof parentIdHeader === "string" ? parentIdHeader : "";

  if (!parentId) {
    throw new UnauthorizedError("Missing x-user-id header", {
      header: "x-user-id",
    });
  }

  const rolesHeader = req.headers["x-user-roles"];
  const roles =
    typeof rolesHeader === "string"
      ? rolesHeader
          .split(",")
          .map((r) => r.trim())
          .filter(Boolean)
      : [];

  const requestIdHeader = req.headers["x-request-id"];
  const traceId =
    typeof requestIdHeader === "string" ? requestIdHeader : "unknown";

  const session: ParentSession = {
    parentId,
    roles,
    dataScope: "CHILDREN",
    traceId,
  };

  logger.debug({ session }, "Parent session built");
  return session;
}
