// BFF_TEACHER_ 错误码（B5 + G14 裁决，统一 BFF_ 前缀）
// 越权防御 3 类错误码（president §2.7 裁决）：
//   - BFF_TEACHER_UNAUTHORIZED (401): x-user-id 缺失或无效
//   - BFF_TEACHER_FORBIDDEN_RESOURCE (403): teacherId 与资源无归属关系（场景 A）
//   - BFF_TEACHER_IDENTITY_MISMATCH (403): JWT teacherId 与 body teacherId 不一致（场景 B）
// 其他聚合层错误码（contract §1.5）

export type ErrorType =
  | "validation"
  | "not_found"
  | "unauthorized"
  | "forbidden_resource"
  | "identity_mismatch"
  | "conflict"
  | "business"
  | "bad_gateway"
  | "aggregation_failed"
  | "internal";

export interface ErrorDetails {
  [key: string]: unknown;
}

export abstract class ApplicationError extends Error {
  abstract readonly type: ErrorType;
  abstract readonly statusCode: number;
  readonly code: string;
  readonly details?: ErrorDetails;
  traceId?: string;

  constructor(message: string, code: string, details?: ErrorDetails) {
    super(message);
    this.name = this.constructor.name;
    this.code = code;
    this.details = details;
  }

  toJSON(): Record<string, unknown> {
    return {
      success: false,
      error: {
        code: this.code,
        message: this.message,
        details: this.details,
        traceId: this.traceId,
      },
    };
  }
}

/** 输入参数校验失败（400） */
export class ValidationError extends ApplicationError {
  readonly type = "validation" as const;
  readonly statusCode = 400;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_VALIDATION_FAILED", details);
  }
}

/** 资源不存在（404） */
export class NotFoundError extends ApplicationError {
  readonly type = "not_found" as const;
  readonly statusCode = 404;
  constructor(resource: string, id: string) {
    super(`${resource} not found: ${id}`, "BFF_TEACHER_NOT_FOUND", {
      resource,
      id,
    });
  }
}

/** x-user-id 缺失或无效（401，president §2.7） */
export class UnauthorizedError extends ApplicationError {
  readonly type = "unauthorized" as const;
  readonly statusCode = 401;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_UNAUTHORIZED", details);
  }
}

/** teacherId 与资源无归属关系（403 场景 A，president §2.7） */
export class ForbiddenResourceError extends ApplicationError {
  readonly type = "forbidden_resource" as const;
  readonly statusCode = 403;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_FORBIDDEN_RESOURCE", details);
  }
}

/** JWT teacherId 与请求 body teacherId 不一致（403 场景 B，president §2.7） */
export class IdentityMismatchError extends ApplicationError {
  readonly type = "identity_mismatch" as const;
  readonly statusCode = 403;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_IDENTITY_MISMATCH", details);
  }
}

/** 并发冲突（409） */
export class ConflictError extends ApplicationError {
  readonly type = "conflict" as const;
  readonly statusCode = 409;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_CONFLICT", details);
  }
}

/** 业务规则违反（422） */
export class BusinessError extends ApplicationError {
  readonly type = "business" as const;
  readonly statusCode = 422;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_BUSINESS_ERROR", details);
  }
}

/** 下游 gRPC 不可达（502） */
export class BadGatewayError extends ApplicationError {
  readonly type = "bad_gateway" as const;
  readonly statusCode = 502;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_UPSTREAM_UNAVAILABLE", details);
  }
}

/** 聚合多下游时部分失败且无降级数据（500） */
export class AggregationFailedError extends ApplicationError {
  readonly type = "aggregation_failed" as const;
  readonly statusCode = 500;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_AGGREGATION_FAILED", details);
  }
}

/** 兜底内部错误（500） */
export class InternalError extends ApplicationError {
  readonly type = "internal" as const;
  readonly statusCode = 500;
  constructor(message: string, details?: ErrorDetails) {
    super(message, "BFF_TEACHER_INTERNAL_ERROR", details);
  }
}
