/**
 * M12 代课教师机制 - 数据访问层
 */
import "server-only";
import { db } from "@/shared/db";
import { lessonPlanSubstitutes, lessonPlans } from "@/shared/db/schema";
import { and, eq, gte, lte, or, isNull, desc } from "drizzle-orm";
import type { SubstituteStatus } from "./lib/type-guards";
import { isSubstituteStatus } from "./lib/type-guards";

/** 代课教师记录 */
export interface LessonPlanSubstitute {
  id: string;
  planId: string;
  originalTeacherId: string;
  substituteTeacherId: string;
  startDate: Date;
  endDate?: Date;
  reason?: string;
  status: SubstituteStatus;
  createdBy: string;
  createdAt: Date;
  updatedAt: Date;
}

/**
 * 查询某课案的代课教师列表
 */
export async function getSubstitutesByPlanId(
  planId: string,
): Promise<LessonPlanSubstitute[]> {
  const rows = await db
    .select()
    .from(lessonPlanSubstitutes)
    .where(eq(lessonPlanSubstitutes.planId, planId))
    .orderBy(desc(lessonPlanSubstitutes.createdAt));

  return rows.map(mapRowToSubstitute);
}

/**
 * 查询某教师当前生效的代课任务（作为代课教师或原教师）
 */
export async function getActiveSubstitutesByTeacherId(
  teacherId: string,
): Promise<LessonPlanSubstitute[]> {
  const now = new Date();
  const rows = await db
    .select()
    .from(lessonPlanSubstitutes)
    .where(
      and(
        eq(lessonPlanSubstitutes.status, "active"),
        or(eq(lessonPlanSubstitutes.originalTeacherId, teacherId), eq(lessonPlanSubstitutes.substituteTeacherId, teacherId)),
        lte(lessonPlanSubstitutes.startDate, now),
        or(isNull(lessonPlanSubstitutes.endDate), gte(lessonPlanSubstitutes.endDate, now)),
      ),
    );
  return rows.map(mapRowToSubstitute);
}

/**
 * 创建代课教师映射
 */
export async function createSubstitute(
  input: {
    planId: string;
    originalTeacherId: string;
    substituteTeacherId: string;
    startDate: Date;
    endDate?: Date;
    reason?: string;
  },
  createdBy: string,
): Promise<LessonPlanSubstitute> {
  const [row] = await db.insert(lessonPlanSubstitutes).values({
    planId: input.planId,
    originalTeacherId: input.originalTeacherId,
    substituteTeacherId: input.substituteTeacherId,
    startDate: input.startDate,
    endDate: input.endDate,
    reason: input.reason,
    status: "active",
    createdBy,
  });
  const insertedId = row.insertId;
  const all = await getSubstitutesByPlanId(input.planId);
  const created = all.find((s) => s.id === String(insertedId));
  if (!created) throw new Error("SUBSTITUTE_CREATE_FAILED");
  return created;
}

/**
 * 更新代课教师状态（cancel/expire）
 */
export async function updateSubstituteStatus(
  substituteId: string,
  status: SubstituteStatus,
): Promise<void> {
  await db
    .update(lessonPlanSubstitutes)
    .set({ status, updatedAt: new Date() })
    .where(eq(lessonPlanSubstitutes.id, substituteId));
}

/**
 * 删除代课教师映射
 */
export async function deleteSubstitute(substituteId: string): Promise<void> {
  await db
    .delete(lessonPlanSubstitutes)
    .where(eq(lessonPlanSubstitutes.id, substituteId));
}

/**
 * 检查某教师对某课案是否具有代课权限
 * - 是原教师 → true
 * - 是当前生效的代课教师 → true
 */
export async function canTeacherAccessPlan(
  planId: string,
  teacherId: string,
): Promise<boolean> {
  // 原教师
  const plan = await db
    .select({ creatorId: lessonPlans.creatorId })
    .from(lessonPlans)
    .where(eq(lessonPlans.id, planId))
    .limit(1);
  if (plan.length === 0) return false;
  if (plan[0]!.creatorId === teacherId) return true;

  // 代课教师
  const substitutes = await getActiveSubstitutesByTeacherId(teacherId);
  return substitutes.some((s) => s.planId === planId);
}

function mapRowToSubstitute(
  row: typeof lessonPlanSubstitutes.$inferSelect,
): LessonPlanSubstitute {
  const status = isSubstituteStatus(row.status) ? row.status : "active";
  return {
    id: row.id,
    planId: row.planId,
    originalTeacherId: row.originalTeacherId,
    substituteTeacherId: row.substituteTeacherId,
    startDate: row.startDate,
    endDate: row.endDate ?? undefined,
    reason: row.reason ?? undefined,
    status,
    createdBy: row.createdBy,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
  };
}
