"use client"

/**
 * ExamServiceProvider — ExamServicePort 的 React Context 注入点（P2-4 骨架）
 *
 * 设计要点：
 * - Context 默认值为 null，组件通过 useExamService() 取值
 * - 未注入时抛出明确错误，避免静默使用未定义服务
 * - Context 不直接绑定具体实现，不同角色页面可注入不同 Provider 实现
 *
 * 当前阶段：
 * - 仅落地 Context 与 Hook 骨架
 * - 具体实现（TeacherExamService/AdminExamService/MockExamService）将在 P2-6+ 重构时补充
 * - 现有组件暂不强制改造，保持向后兼容
 */

import { createContext, useContext, type ReactNode } from "react"
import type { ExamServicePort } from "./exam-service-port"

const ExamServiceContext = createContext<ExamServicePort | null>(null)

interface ExamServiceProviderProps {
  /** 注入的服务实现 */
  service: ExamServicePort
  children: ReactNode
}

/**
 * 注入 ExamService 实现的 Provider。
 *
 * @example
 * ```tsx
 * // 在角色专属 layout.tsx 中
 * import { ExamServiceProvider } from "@/modules/exams/services/exam-service-context"
 * import { TeacherExamService } from "@/modules/exams/services/teacher-exam-service"
 *
 * export default function TeacherExamsLayout({ children }) {
 *   return <ExamServiceProvider service={new TeacherExamService()}>{children}</ExamServiceProvider>
 * }
 * ```
 */
export function ExamServiceProvider({ service, children }: ExamServiceProviderProps): ReactNode {
  return <ExamServiceContext.Provider value={service}>{children}</ExamServiceContext.Provider>
}

/**
 * 获取注入的 ExamService 实例。
 *
 * 必须在 ExamServiceProvider 子树内调用，否则抛出明确错误。
 * 这表明调用方未在合适的角色 layout 中被包裹，需检查路由结构。
 */
export function useExamService(): ExamServicePort {
  const service = useContext(ExamServiceContext)
  if (service === null) {
    throw new Error(
      "[ExamServicePort] No implementation injected. " +
        "Wrap the consumer tree in <ExamServiceProvider service={...}>. " +
        "If you see this in a Server Component, ExamServicePort only supports client-side injection (P2-4 scope)."
    )
  }
  return service
}

/**
 * 测试用：尝试获取服务，未注入时返回 null（不抛错）。
 * 仅在测试场景下使用，生产代码应使用 useExamService()。
 *
 * 注意：命名以 `use` 开头以满足 React Hooks 规则。
 */
export function useTryExamService(): ExamServicePort | null {
  return useContext(ExamServiceContext)
}
