import "server-only";

import { and, desc, eq, inArray, max } from "drizzle-orm";
import { createId } from "@paralleldrive/cuid2";

import { db } from "@/shared/db";
import { lessonPlanVersions, lessonPlans } from "@/shared/db/schema";
import { normalizeDocument } from "./data-access";
import type { LessonPlanDocument, LessonPlanVersion } from "./types";

// ---- 类型映射：Drizzle 行 → LessonPlanVersion（Date → ISO string）----
function mapRowToVersion(row: {
  id: string;
  planId: string;
  versionNo: number;
  label: string | null;
  content: unknown;
  isAuto: boolean;
  creatorId: string;
  createdAt: Date;
}): LessonPlanVersion {
  return {
    id: row.id,
    planId: row.planId,
    versionNo: row.versionNo,
    label: row.label,
    content: normalizeDocument(row.content),
    isAuto: row.isAuto,
    creatorId: row.creatorId,
    createdAt: row.createdAt.toISOString(),
  };
}

export async function getLessonPlanVersions(
  planId: string,
  userId: string,
): Promise<LessonPlanVersion[]> {
  // 校验归属
  const plan = await db
    .select({ id: lessonPlans.id })
    .from(lessonPlans)
    .where(
      and(eq(lessonPlans.id, planId), eq(lessonPlans.creatorId, userId)),
    )
    .limit(1);
  if (plan.length === 0) return [];

  const rows = await db
    .select()
    .from(lessonPlanVersions)
    .where(eq(lessonPlanVersions.planId, planId))
    .orderBy(desc(lessonPlanVersions.versionNo));
  return rows.map(mapRowToVersion);
}

export async function createLessonPlanVersion(input: {
  planId: string;
  content: LessonPlanDocument;
  userId: string;
  isAuto: boolean;
  label?: string;
}): Promise<{ versionNo: number } | null> {
  // P0 修复：max(versionNo)+1 必须在事务内完成，避免并发产生重复版本号
  return await db.transaction(async (tx) => {
    // 校验 planId 归属
    const plan = await tx
      .select({ id: lessonPlans.id })
      .from(lessonPlans)
      .where(
        and(eq(lessonPlans.id, input.planId), eq(lessonPlans.creatorId, input.userId)),
      )
      .limit(1);
    if (plan.length === 0) return null;

    const maxRow = await tx
      .select({ maxNo: max(lessonPlanVersions.versionNo) })
      .from(lessonPlanVersions)
      .where(eq(lessonPlanVersions.planId, input.planId));
    const nextNo = (maxRow[0]?.maxNo ?? 0) + 1;

    await tx.insert(lessonPlanVersions).values({
      id: createId(),
      planId: input.planId,
      versionNo: nextNo,
      label: input.label ?? null,
      content: input.content,
      isAuto: input.isAuto,
      creatorId: input.userId,
    });
    return { versionNo: nextNo };
  });
}

export async function getVersionContent(
  planId: string,
  versionNo: number,
  userId: string,
): Promise<LessonPlanDocument | null> {
  // 校验归属
  const plan = await db
    .select({ id: lessonPlans.id })
    .from(lessonPlans)
    .where(
      and(eq(lessonPlans.id, planId), eq(lessonPlans.creatorId, userId)),
    )
    .limit(1);
  if (plan.length === 0) return null;

  const rows = await db
    .select({ content: lessonPlanVersions.content })
    .from(lessonPlanVersions)
    .where(
      and(
        eq(lessonPlanVersions.planId, planId),
        eq(lessonPlanVersions.versionNo, versionNo),
      ),
    )
    .limit(1);
  if (rows.length === 0) return null;
  return normalizeDocument(rows[0].content);
}

export async function revertToVersion(
  planId: string,
  versionNo: number,
  userId: string,
  // V3 修复：由 actions 层传入 i18n 翻译的回退标签，避免 data-access 硬编码中文
  revertLabel: string,
): Promise<{ newVersionNo: number } | null> {
  const content = await getVersionContent(planId, versionNo, userId);
  if (!content) return null;

  // P0 修复：update 与 createLessonPlanVersion 必须在同一事务内，
  // 避免回退后 content 已覆盖但版本记录未生成的不一致状态
  return await db.transaction(async (tx) => {
    await tx
      .update(lessonPlans)
      .set({ content, lastSavedAt: new Date() })
      .where(
        and(eq(lessonPlans.id, planId), eq(lessonPlans.creatorId, userId)),
      );

    const maxRow = await tx
      .select({ maxNo: max(lessonPlanVersions.versionNo) })
      .from(lessonPlanVersions)
      .where(eq(lessonPlanVersions.planId, planId));
    const newNo = (maxRow[0]?.maxNo ?? 0) + 1;

    await tx.insert(lessonPlanVersions).values({
      id: createId(),
      planId,
      versionNo: newNo,
      label: revertLabel,
      content,
      isAuto: false,
      creatorId: userId,
    });
    return { newVersionNo: newNo };
  });
}

export async function pruneAutoVersions(
  planId: string,
  userId: string,
  keep = 50,
): Promise<number> {
  // 校验 planId 归属
  const plan = await db
    .select({ id: lessonPlans.id })
    .from(lessonPlans)
    .where(and(eq(lessonPlans.id, planId), eq(lessonPlans.creatorId, userId)))
    .limit(1);
  if (plan.length === 0) return 0;

  const rows = await db
    .select({
      id: lessonPlanVersions.id,
      isAuto: lessonPlanVersions.isAuto,
      versionNo: lessonPlanVersions.versionNo,
    })
    .from(lessonPlanVersions)
    .where(eq(lessonPlanVersions.planId, planId))
    .orderBy(desc(lessonPlanVersions.versionNo));

  if (rows.length <= keep) return 0;
  // 保留前 keep 条；超出部分只删 isAuto=true 的
  const toDelete = rows.slice(keep).filter((r) => r.isAuto);
  if (toDelete.length === 0) return 0;
  await db
    .delete(lessonPlanVersions)
    .where(
      and(
        eq(lessonPlanVersions.planId, planId),
        inArray(
          lessonPlanVersions.id,
          toDelete.map((r) => r.id),
        ),
      ),
    );
  return toDelete.length;
}
