import "server-only"

import { eq, inArray, sql, type SQL } from "drizzle-orm"

import { db } from "@/shared/db"
import { classes, gradeRecords } from "@/shared/db/schema"
import type { DataScope } from "@/shared/types/permissions"

/**
 * Safely convert an unknown value to a finite number.
 * Returns 0 when the value is not a finite number.
 *
 * Used to normalize numeric columns returned by Drizzle (which may be
 * string | number depending on the driver) into plain numbers.
 */
export const toNumber = (v: unknown): number => {
  const n = typeof v === "number" ? v : Number(v)
  return Number.isFinite(n) ? n : 0
}

/**
 * Normalize a raw score to a 0-100 scale based on its full score.
 * Returns 0 when fullScore is non-positive. Result is rounded to 2 decimals.
 */
export const normalize = (score: number, fullScore: number): number => {
  if (fullScore <= 0) return 0
  return Math.round((score / fullScore) * 10000) / 100
}

/**
 * Build a Drizzle SQL filter that restricts `gradeRecords` rows based on
 * the current user's DataScope. Returns `null` when no row-level filter
 * is required (e.g. admin / student viewing their own records — the caller
 * is expected to add the studentId condition separately for `class_members`).
 */
export const buildScopeClassFilter = (scope: DataScope): SQL | null => {
  if (scope.type === "all") return null
  if (scope.type === "class_taught") {
    return scope.classIds.length > 0
      ? inArray(gradeRecords.classId, scope.classIds)
      : sql`1=0`
  }
  if (scope.type === "grade_managed") {
    // P2-4 修复：grade_managed scope 应返回所管年级的班级成绩记录
    // 通过子查询过滤 classId IN (SELECT id FROM classes WHERE grade_id IN (...))
    return scope.gradeIds.length > 0
      ? inArray(
          gradeRecords.classId,
          db.select({ id: classes.id }).from(classes).where(inArray(classes.gradeId, scope.gradeIds))
        )
      : sql`1=0`
  }
  if (scope.type === "class_members") return null
  if (scope.type === "children") {
    return scope.childrenIds.length > 0
      ? inArray(gradeRecords.studentId, scope.childrenIds)
      : sql`1=0`
  }
  if (scope.type === "owned") return eq(gradeRecords.studentId, scope.userId)
  return sql`1=0`
}
