/**
 * Sentry 错误追踪初始化（P6 硬化）
 *
 * - 参考 student-portal/src/lib/observability/sentry.ts 实现
 * - 仅当 NEXT_PUBLIC_SENTRY_DSN 配置时初始化（动态 import @sentry/nextjs）
 * - beforeSend PII 过滤：email / phone / token / password / 身份证 / 教师姓名
 * - 设置 release / tag / environment
 * - 导出 initSentry() + captureException / captureMessage 包装器
 *
 * 关联：02-architecture-design.md §12 可观测性
 */

import { getObservabilityConfig } from "@/lib/observability/env";

/**
 * Sentry 模块类型（仅声明使用的 API 子集）。
 * 避免对未安装包的静态类型依赖。
 */
interface SentryModule {
  init(options: {
    dsn: string;
    environment: string;
    release?: string;
    tracesSampleRate: number;
    beforeSend?: (event: unknown) => unknown;
  }): void;
  captureException(err: unknown, context?: { extra?: Record<string, unknown> }): void;
  captureMessage(message: string): void;
  addBreadcrumb(breadcrumb: {
    category?: string;
    message?: string;
    level?: string;
  }): void;
  setTag(key: string, value: string): void;
}

/** 需要脱敏的 PII 字段名（匹配 key，不区分大小写） */
const PII_KEYS = [
  "teachername",
  "name",
  "email",
  "phone",
  "mobile",
  "idcard",
  "id_card",
  "token",
  "accesstoken",
  "access_token",
  "refreshtoken",
  "refresh_token",
  "password",
  "secret",
  "authorization",
];

/** Sentry 模块缓存（initSentry 成功后赋值） */
let sentryModule: SentryModule | null = null;

/** 初始化状态标记 */
let initialized = false;

/**
 * 递归移除 PII 字段（返回脱敏后的副本）。
 *
 * 从 unknown 转换为结构化对象处理，符合 project_rules §3.4 禁止 any 规则。
 */
function stripPII(input: unknown): unknown {
  if (Array.isArray(input)) {
    return input.map(stripPII);
  }
  if (input !== null && typeof input === "object") {
    const obj = input as Record<string, unknown>;
    const out: Record<string, unknown> = {};
    for (const key of Object.keys(obj)) {
      if (PII_KEYS.includes(key.toLowerCase())) {
        out[key] = "[REDACTED]";
      } else {
        out[key] = stripPII(obj[key]);
      }
    }
    return out;
  }
  return input;
}

/**
 * 初始化 Sentry（仅在浏览器/服务端入口调用一次）。
 *
 * 使用动态 import 加载 @sentry/nextjs，避免未安装包导致构建失败。
 * 包将在统一安装阶段补充到 package.json。
 *
 * @returns 是否成功初始化（false 表示未配置 DSN 或加载失败）
 */
export async function initSentry(): Promise<boolean> {
  if (initialized) return sentryModule !== null;

  const config = getObservabilityConfig();
  if (config.sentryDsn === null) {
    // 未配置 DSN，标记为已检查，避免重复读取配置
    initialized = true;
    return false;
  }

  try {
    const Sentry = (await import("@sentry/nextjs")) as unknown as SentryModule;

    Sentry.init({
      dsn: config.sentryDsn,
      environment: config.environment,
      release: config.sentryRelease ?? undefined,
      tracesSampleRate: config.tracesSampleRate,
      beforeSend(event: unknown) {
        // 过滤 PII 后回传事件
        return stripPII(event);
      },
    });

    // 设置全局 tag（service 标识，便于 Sentry 面板按应用过滤）
    Sentry.setTag("service", config.serviceName);
    Sentry.setTag("portal", "teacher");

    sentryModule = Sentry;
    initialized = true;

    // 挂载捕获器供 ErrorBoundary 使用（参考 student-portal 模式）
    if (typeof window !== "undefined") {
      (
        window as unknown as {
          __eduCaptureException?: (e: Error, extra?: unknown) => void;
        }
      ).__eduCaptureException = (err: Error, extra?: unknown) => {
        if (sentryModule) {
          sentryModule.captureException(
            err,
            extra !== undefined ? { extra: { detail: extra } } : undefined,
          );
        }
      };
    }

    return true;
  } catch (err) {
    // @sentry/nextjs 未安装或加载失败，降级到 console
    if (typeof console !== "undefined") {
      console.warn("[teacher-portal] Sentry 加载失败，降级到 console", err);
    }
    initialized = true;
    return false;
  }
}

/**
 * 捕获异常（未初始化时降级为 console.error）。
 *
 * 同步 API：若 Sentry 模块已加载则上报，否则输出到控制台。
 */
export function captureException(err: unknown): void {
  if (sentryModule) {
    sentryModule.captureException(err);
  } else if (typeof console !== "undefined") {
    console.error("[teacher-portal]", err);
  }
}

/**
 * 捕获消息（未初始化时降级为 console.warn）。
 */
export function captureMessage(message: string): void {
  if (sentryModule) {
    sentryModule.captureMessage(message);
  } else if (typeof console !== "undefined") {
    console.warn("[teacher-portal]", message);
  }
}

/**
 * 添加面包屑（用于错误上下文追踪）。
 * 未初始化时为空操作。
 */
export function addBreadcrumb(breadcrumb: {
  category?: string;
  message?: string;
  level?: string;
}): void {
  if (sentryModule) {
    sentryModule.addBreadcrumb(breadcrumb);
  }
}

/** Sentry 是否已初始化（可用于运行时判断） */
export function isSentryInitialized(): boolean {
  return sentryModule !== null;
}
