import type { AuthContext } from "@/shared/types/permissions"
import type { ClassSubject } from "./types"
import { DEFAULT_CLASS_SUBJECTS } from "./types"

const CLASS_SUBJECT_STRINGS: readonly string[] = DEFAULT_CLASS_SUBJECTS

export const isClassSubject = (v: string): v is ClassSubject => CLASS_SUBJECT_STRINGS.includes(v)

export const isWeekday = (n: number): n is 1 | 2 | 3 | 4 | 5 | 6 | 7 =>
  n >= 1 && n <= 7 && Number.isInteger(n)

export const toWeekday = (n: number): 1 | 2 | 3 | 4 | 5 | 6 | 7 => {
  if (!isWeekday(n)) throw new Error("Invalid weekday")
  return n
}

/**
 * P1-1: 替代 `ctx.roles.includes("admin")` 硬编码。
 * 通过 dataScope.type === "all" 判断是否拥有 admin 级别的数据访问范围。
 */
export const hasAdminScope = (ctx: AuthContext): boolean => ctx.dataScope.type === "all"

/**
 * P1-1: 替代 `ctx.roles.includes("teacher")` 硬编码。
 * 通过 dataScope.type === "class_taught" 判断是否为教师（有授课班级）。
 */
export const hasTeacherScope = (ctx: AuthContext): boolean => ctx.dataScope.type === "class_taught"

/**
 * P1-1: 替代 `ctx.roles.includes("student")` 硬编码。
 * 通过 dataScope.type === "class_members" 判断是否为学生。
 */
export const hasStudentScope = (ctx: AuthContext): boolean => ctx.dataScope.type === "class_members"

/**
 * 解析表单中的 subjectTeachers JSON 字符串为标准赋值数组。
 * 提取自原 actions.ts，供 admin/grade class 更新逻辑复用。
 */
export const parseSubjectTeachers = (raw: string | null) => {
  if (typeof raw !== "string" || raw.trim().length === 0) return null
  const parsed = JSON.parse(raw) as unknown
  if (!Array.isArray(parsed)) throw new Error("Invalid subject teachers")

  return parsed.flatMap((item) => {
    if (!item || typeof item !== "object") return []
    const subject = (item as { subject?: unknown }).subject
    const teacherId = (item as { teacherId?: unknown }).teacherId

    if (typeof subject !== "string" || !isClassSubject(subject)) return []

    if (teacherId === null || typeof teacherId === "undefined") {
      return [{ subject, teacherId: null }]
    }

    if (typeof teacherId !== "string") return []
    const trimmed = teacherId.trim()
    return [{ subject, teacherId: trimmed.length > 0 ? trimmed : null }]
  })
}
