/**
 * M5 形成性评价闭环 - 数据访问层
 *
 * publish 课案时嵌入互动组件（poll/quiz/exit_ticket），
 * 学生课中作答后结果回写到 lessonPlanFormativeResponses 表，
 * 教师可查看实时反馈，闭环到课案优化。
 */
import "server-only";
import { db } from "@/shared/db";
import {
  lessonPlanFormativeItems,
  lessonPlanFormativeResponses,
} from "@/shared/db/schema";
import { eq, desc, asc } from "drizzle-orm";
import type { FormativeInteractionType } from "./lib/type-guards";
import { isFormativeInteractionType } from "./lib/type-guards";

/** 互动组件项 */
export interface FormativeItem {
  id: string;
  planId: string;
  blockId: string;
  interactionType: FormativeInteractionType;
  payload: unknown;
  instantFeedback: boolean;
  orderIndex: number;
  createdAt: Date;
  updatedAt: Date;
}

/** 学生作答记录 */
export interface FormativeResponse {
  id: string;
  itemId: string;
  studentId: string;
  classId?: string;
  response: unknown;
  isCorrect?: boolean;
  durationSec?: number;
  createdAt: Date;
}

/**
 * 查询课案的所有互动组件
 */
export async function getFormativeItemsByPlanId(
  planId: string,
): Promise<FormativeItem[]> {
  const rows = await db
    .select()
    .from(lessonPlanFormativeItems)
    .where(eq(lessonPlanFormativeItems.planId, planId))
    .orderBy(asc(lessonPlanFormativeItems.orderIndex));

  return rows.map(mapRowToItem);
}

/**
 * 查询单个互动组件
 */
export async function getFormativeItemById(
  id: string,
): Promise<FormativeItem | null> {
  const rows = await db
    .select()
    .from(lessonPlanFormativeItems)
    .where(eq(lessonPlanFormativeItems.id, id))
    .limit(1);
  return rows.length === 0 ? null : mapRowToItem(rows[0]!);
}

/**
 * 创建互动组件
 */
export async function createFormativeItem(
  input: {
    planId: string;
    blockId: string;
    interactionType: FormativeInteractionType;
    payload: unknown;
    instantFeedback?: boolean;
    orderIndex?: number;
  },
): Promise<FormativeItem> {
  const [row] = await db.insert(lessonPlanFormativeItems).values({
    planId: input.planId,
    blockId: input.blockId,
    interactionType: input.interactionType,
    payload: input.payload,
    instantFeedback: input.instantFeedback ?? false,
    orderIndex: input.orderIndex ?? 0,
  });
  const insertedId = row.insertId;
  const created = await getFormativeItemById(String(insertedId));
  if (!created) throw new Error("FORMATIVE_ITEM_CREATE_FAILED");
  return created;
}

/**
 * 更新互动组件
 */
export async function updateFormativeItem(
  id: string,
  patch: {
    payload?: unknown;
    instantFeedback?: boolean;
    orderIndex?: number;
  },
): Promise<void> {
  await db
    .update(lessonPlanFormativeItems)
    .set({
      ...(patch.payload !== undefined ? { payload: patch.payload } : {}),
      ...(patch.instantFeedback !== undefined ? { instantFeedback: patch.instantFeedback } : {}),
      ...(patch.orderIndex !== undefined ? { orderIndex: patch.orderIndex } : {}),
    })
    .where(eq(lessonPlanFormativeItems.id, id));
}

/**
 * 删除互动组件
 */
export async function deleteFormativeItem(id: string): Promise<void> {
  await db
    .delete(lessonPlanFormativeItems)
    .where(eq(lessonPlanFormativeItems.id, id));
}

/**
 * 提交学生作答
 */
export async function submitFormativeResponse(
  input: {
    itemId: string;
    studentId: string;
    classId?: string;
    response: unknown;
    isCorrect?: boolean;
    durationSec?: number;
  },
): Promise<FormativeResponse> {
  const [row] = await db.insert(lessonPlanFormativeResponses).values({
    itemId: input.itemId,
    studentId: input.studentId,
    classId: input.classId,
    response: input.response,
    isCorrect: input.isCorrect,
    durationSec: input.durationSec,
  });
  const insertedId = row.insertId;
  const items = await getResponsesByItemId(input.itemId);
  const created = items.find((r) => r.id === String(insertedId));
  if (!created) throw new Error("FORMATIVE_RESPONSE_CREATE_FAILED");
  return created;
}

/**
 * 查询互动组件的所有作答
 */
export async function getResponsesByItemId(
  itemId: string,
): Promise<FormativeResponse[]> {
  const rows = await db
    .select()
    .from(lessonPlanFormativeResponses)
    .where(eq(lessonPlanFormativeResponses.itemId, itemId))
    .orderBy(desc(lessonPlanFormativeResponses.createdAt));

  return rows.map(mapRowToResponse);
}

/**
 * 查询某学生作答历史
 */
export async function getResponsesByStudentId(
  studentId: string,
  planId?: string,
): Promise<FormativeResponse[]> {
  // 简化查询：按 studentId 查询，可选按 planId 过滤
  if (planId) {
    const items = await db
      .select({ id: lessonPlanFormativeItems.id })
      .from(lessonPlanFormativeItems)
      .where(eq(lessonPlanFormativeItems.planId, planId));
    if (items.length === 0) return [];
    const itemIds = items.map((i) => i.id);
    const rows = await db
      .select()
      .from(lessonPlanFormativeResponses)
      .where(eq(lessonPlanFormativeResponses.studentId, studentId));
    return rows.filter((r) => itemIds.includes(r.itemId)).map(mapRowToResponse);
  }
  const rows = await db
    .select()
    .from(lessonPlanFormativeResponses)
    .where(eq(lessonPlanFormativeResponses.studentId, studentId));
  return rows.map(mapRowToResponse);
}

/**
 * 统计互动组件的作答情况（用于教师查看实时反馈）
 */
export async function getFormativeItemStats(
  itemId: string,
): Promise<{ total: number; correct: number; incorrect: number; avgDurationSec: number }> {
  const rows = await db
    .select()
    .from(lessonPlanFormativeResponses)
    .where(eq(lessonPlanFormativeResponses.itemId, itemId));

  const total = rows.length;
  let correct = 0;
  let incorrect = 0;
  let totalDuration = 0;
  let durationCount = 0;
  for (const r of rows) {
    if (r.isCorrect === true) correct++;
    else if (r.isCorrect === false) incorrect++;
    if (r.durationSec !== null && r.durationSec !== undefined) {
      totalDuration += r.durationSec;
      durationCount++;
    }
  }
  return {
    total,
    correct,
    incorrect,
    avgDurationSec: durationCount > 0 ? Math.round(totalDuration / durationCount) : 0,
  };
}

function mapRowToItem(
  row: typeof lessonPlanFormativeItems.$inferSelect,
): FormativeItem {
  const interactionType = isFormativeInteractionType(row.interactionType)
    ? row.interactionType
    : "poll";
  return {
    id: row.id,
    planId: row.planId,
    blockId: row.blockId,
    interactionType,
    payload: row.payload,
    instantFeedback: row.instantFeedback,
    orderIndex: row.orderIndex,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
  };
}

function mapRowToResponse(
  row: typeof lessonPlanFormativeResponses.$inferSelect,
): FormativeResponse {
  return {
    id: row.id,
    itemId: row.itemId,
    studentId: row.studentId,
    classId: row.classId ?? undefined,
    response: row.response,
    isCorrect: row.isCorrect ?? undefined,
    durationSec: row.durationSec ?? undefined,
    createdAt: row.createdAt,
  };
}
