/**
 * M1 课标（Standards）模块 - 数据访问层
 *
 * 严格遵守三层架构：本文件只被 modules/standards/actions.ts 和 app/ 路由调用，
 * 不直接被其他业务模块引用。其他模块如需查询课标，应通过本文件导出的函数。
 */
import "server-only";
import { db } from "@/shared/db";
import { standards, lessonPlanStandards } from "@/shared/db/schema";
import { and, eq, asc, like } from "drizzle-orm";
import type {
  Standard,
  StandardTreeNode,
  LessonPlanStandardLink,
  GetStandardsParams,
} from "./types";
import type { StandardLevel } from "../lesson-preparation/lib/type-guards";

/**
 * 查询课标列表（可按层级/学科/年级过滤，可选返回树形结构）
 */
export async function getStandards(
  params: GetStandardsParams = {},
): Promise<Standard[]> {
  const conditions = [];
  if (params.level) conditions.push(eq(standards.level, params.level));
  if (params.parentId) conditions.push(eq(standards.parentId, params.parentId));
  if (params.subjectId) conditions.push(eq(standards.subjectId, params.subjectId));
  if (params.gradeId) conditions.push(eq(standards.gradeId, params.gradeId));
  if (params.stage) conditions.push(eq(standards.stage, params.stage));
  if (!params.includeInactive) conditions.push(eq(standards.isActive, true));

  const rows = await db
    .select()
    .from(standards)
    .where(conditions.length > 0 ? and(...conditions) : undefined)
    .orderBy(asc(standards.sortOrder), asc(standards.code));

  return rows.map(mapRowToStandard);
}

/**
 * 查询课标树形结构
 */
export async function getStandardsTree(
  params: Omit<GetStandardsParams, "asTree" | "parentId"> = {},
): Promise<StandardTreeNode[]> {
  const allStandards = await getStandards(params);
  return buildStandardsTree(allStandards);
}

/**
 * 按 ID 获取单个课标
 */
export async function getStandardById(id: string): Promise<Standard | null> {
  const rows = await db.select().from(standards).where(eq(standards.id, id)).limit(1);
  return rows.length === 0 ? null : mapRowToStandard(rows[0]!);
}

/**
 * 按 code 获取单个课标
 */
export async function getStandardByCode(code: string): Promise<Standard | null> {
  const rows = await db.select().from(standards).where(eq(standards.code, code)).limit(1);
  return rows.length === 0 ? null : mapRowToStandard(rows[0]!);
}

/**
 * 创建课标
 */
export async function createStandard(
  input: {
    code: string;
    title: string;
    description?: string;
    level: StandardLevel;
    parentId?: string;
    subjectId?: string;
    gradeId?: string;
    stage?: string;
    sortOrder?: number;
  },
  createdBy: string,
): Promise<Standard> {
  const [row] = await db.insert(standards).values({
    code: input.code,
    title: input.title,
    description: input.description,
    level: input.level,
    parentId: input.parentId,
    subjectId: input.subjectId,
    gradeId: input.gradeId,
    stage: input.stage,
    sortOrder: input.sortOrder ?? 0,
    isActive: true,
    createdBy,
  });
  const insertedId = row.insertId;
  const created = await getStandardById(String(insertedId));
  if (!created) throw new Error("STANDARD_CREATE_FAILED");
  return created;
}

/**
 * 更新课标
 */
export async function updateStandard(
  id: string,
  patch: {
    title?: string;
    description?: string;
    parentId?: string;
    sortOrder?: number;
    isActive?: boolean;
  },
): Promise<Standard | null> {
  await db
    .update(standards)
    .set({
      ...(patch.title !== undefined ? { title: patch.title } : {}),
      ...(patch.description !== undefined ? { description: patch.description } : {}),
      ...(patch.parentId !== undefined ? { parentId: patch.parentId } : {}),
      ...(patch.sortOrder !== undefined ? { sortOrder: patch.sortOrder } : {}),
      ...(patch.isActive !== undefined ? { isActive: patch.isActive } : {}),
    })
    .where(eq(standards.id, id));
  return getStandardById(id);
}

/**
 * 软删除课标（标记 isActive=false，保留关联数据完整性）
 */
export async function deactivateStandard(id: string): Promise<void> {
  await db.update(standards).set({ isActive: false }).where(eq(standards.id, id));
}

/**
 * 按关键词搜索课标
 */
export async function searchStandards(
  keyword: string,
  limit = 50,
): Promise<Standard[]> {
  const rows = await db
    .select()
    .from(standards)
    .where(like(standards.title, `%${keyword}%`))
    .limit(limit)
    .orderBy(asc(standards.sortOrder));
  return rows.map(mapRowToStandard);
}

// ---- 课案 ↔ 课标 关联 ----

/**
 * 查询课案关联的所有课标
 */
export async function getStandardsByPlanId(
  planId: string,
): Promise<LessonPlanStandardLink[]> {
  const rows = await db
    .select({
      link: lessonPlanStandards,
      standard: standards,
    })
    .from(lessonPlanStandards)
    .innerJoin(standards, eq(lessonPlanStandards.standardId, standards.id))
    .where(eq(lessonPlanStandards.planId, planId))
    .orderBy(asc(lessonPlanStandards.createdAt));

  return rows.map((r) => ({
    id: r.link.id,
    planId: r.link.planId,
    standardId: r.link.standardId,
    relationType: r.link.relationType as "primary" | "related",
    createdBy: r.link.createdBy,
    createdAt: r.link.createdAt,
    standard: mapRowToStandard(r.standard),
  }));
}

/**
 * 关联课案与课标
 */
export async function linkPlanToStandard(
  planId: string,
  standardId: string,
  relationType: "primary" | "related",
  createdBy: string,
): Promise<LessonPlanStandardLink> {
  const [row] = await db.insert(lessonPlanStandards).values({
    planId,
    standardId,
    relationType,
    createdBy,
  });
  const insertedId = row.insertId;
  const links = await getStandardsByPlanId(planId);
  const created = links.find((l) => l.id === String(insertedId));
  if (!created) throw new Error("STANDARD_LINK_CREATE_FAILED");
  return created;
}

/**
 * 取消课案与课标的关联
 */
export async function unlinkPlanFromStandard(
  planId: string,
  standardId: string,
): Promise<void> {
  await db
    .delete(lessonPlanStandards)
    .where(
      and(
        eq(lessonPlanStandards.planId, planId),
        eq(lessonPlanStandards.standardId, standardId),
      ),
    );
}

// ---- 辅助函数 ----

function mapRowToStandard(row: typeof standards.$inferSelect): Standard {
  return {
    id: row.id,
    code: row.code,
    title: row.title,
    description: row.description ?? undefined,
    level: row.level as StandardLevel,
    parentId: row.parentId ?? undefined,
    subjectId: row.subjectId ?? undefined,
    gradeId: row.gradeId ?? undefined,
    stage: row.stage ?? undefined,
    sortOrder: row.sortOrder,
    isActive: row.isActive,
    createdBy: row.createdBy ?? undefined,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
  };
}

/**
 * 将扁平列表构建为树形结构
 */
function buildStandardsTree(items: Standard[]): StandardTreeNode[] {
  const map = new Map<string, StandardTreeNode>();
  const roots: StandardTreeNode[] = [];

  // 第一遍：建立 id → node 映射
  for (const item of items) {
    map.set(item.id, { ...item, children: [] });
  }

  // 第二遍：构建父子关系
  for (const item of items) {
    const node = map.get(item.id)!;
    if (item.parentId && map.has(item.parentId)) {
      map.get(item.parentId)!.children.push(node);
    } else {
      roots.push(node);
    }
  }

  return roots;
}
