"use server"

import { revalidatePath } from "next/cache"
import { requirePermission } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"
import { handleActionError } from "@/shared/lib/action-utils"
import type { DataScope } from "@/shared/types/permissions"

import {
  CreateCoursePlanSchema,
  UpdateCoursePlanSchema,
  CreateCoursePlanItemSchema,
  UpdateCoursePlanItemSchema,
  GetCoursePlansParamsSchema,
  GradeIdSchema,
  ReorderItemsSchema,
  BulkToggleSchema,
  CopyPlanSchema,
} from "./schema"
import {
  getCoursePlans,
  getCoursePlanById,
  getGradeCoursePlanProgress,
  createCoursePlan,
  updateCoursePlan,
  deleteCoursePlan,
  createCoursePlanItem,
  updateCoursePlanItem,
  deleteCoursePlanItem,
  reorderCoursePlanItems,
  bulkUpdateItemCompleted,
  copyCoursePlanToClasses,
} from "./data-access"
import type {
  CoursePlanWithItems,
  GetCoursePlansParams,
  CoursePlanListItem,
  CoursePlanQueryScope,
  GradeCoursePlanProgressResult,
  ReorderCoursePlanItemInput,
} from "./types"

/**
 * 从 AuthContext 解析课程计划查询范围。
 * - admin/教务主任 → 全局视图
 * - teacher → 仅自己负责的计划（class_taught scope）
 * - parent/student → 仅孩子所在班级的计划
 */
function resolveScope(
  ctx: { userId: string; dataScope: DataScope; roles: string[] }
): CoursePlanQueryScope {
  const isAdmin = ctx.roles.some(
    (r) => r === "admin" || r === "grade_manager" || r === "academic_director"
  )

  if (isAdmin || ctx.dataScope.type === "all") {
    return { userId: ctx.userId, isAdmin: true }
  }

  // 教师：class_taught scope 携带 classIds，同时按 teacherId 过滤
  if (ctx.dataScope.type === "class_taught") {
    return {
      userId: ctx.userId,
      isAdmin: false,
      teacherId: ctx.userId,
      classIds: ctx.dataScope.classIds,
    }
  }

  // 学生：class_members scope 携带 classIds
  if (ctx.dataScope.type === "class_members") {
    return {
      userId: ctx.userId,
      isAdmin: false,
      classIds: ctx.dataScope.classIds,
    }
  }

  // 家长：children scope 需通过孩子 ID 解析班级（调用方已预解析）
  if (ctx.dataScope.type === "children") {
    return {
      userId: ctx.userId,
      isAdmin: false,
      classIds: [], // 家长视角需调用方补充 classIds
    }
  }

  // grade_managed / owned：仅返回自己创建的
  return { userId: ctx.userId, isAdmin: false }
}

const revalidatePlanPaths = (id?: string): void => {
  revalidatePath("/admin/course-plans")
  revalidatePath("/teacher/course-plans")
  revalidatePath("/parent/course-plans")
  revalidatePath("/student/course-plans")
  if (id) {
    revalidatePath(`/admin/course-plans/${id}`)
    revalidatePath(`/teacher/course-plans/${id}`)
    revalidatePath(`/parent/course-plans/${id}`)
    revalidatePath(`/student/course-plans/${id}`)
  }
}

export async function createCoursePlanAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    const parsed = CreateCoursePlanSchema.safeParse({
      classId: formData.get("classId"),
      subjectId: formData.get("subjectId"),
      teacherId: formData.get("teacherId"),
      academicYearId: formData.get("academicYearId") || undefined,
      semester: formData.get("semester") || undefined,
      totalHours: formData.get("totalHours") || undefined,
      weeklyHours: formData.get("weeklyHours") || undefined,
      startDate: formData.get("startDate") || undefined,
      endDate: formData.get("endDate") || undefined,
      syllabus: formData.get("syllabus") || undefined,
      objectives: formData.get("objectives") || undefined,
      status: formData.get("status") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid form data",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const id = await createCoursePlan(parsed.data, ctx.userId)
    revalidatePlanPaths(id)
    return { success: true, message: "Course plan created", data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function updateCoursePlanAction(
  id: string,
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    // 权限二次校验：非 admin 只能修改自己负责的计划
    const scope = resolveScope(ctx)
    const existing = await getCoursePlanById(id, scope)
    if (!existing) return { success: false, message: "Course plan not found" }

    const parsed = UpdateCoursePlanSchema.safeParse({
      classId: formData.get("classId") || undefined,
      subjectId: formData.get("subjectId") || undefined,
      teacherId: formData.get("teacherId") || undefined,
      academicYearId: formData.get("academicYearId") || undefined,
      semester: formData.get("semester") || undefined,
      totalHours: formData.get("totalHours") || undefined,
      completedHours: formData.get("completedHours") || undefined,
      weeklyHours: formData.get("weeklyHours") || undefined,
      startDate: formData.get("startDate") || undefined,
      endDate: formData.get("endDate") || undefined,
      syllabus: formData.get("syllabus") || undefined,
      objectives: formData.get("objectives") || undefined,
      status: formData.get("status") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid form data",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    await updateCoursePlan(id, parsed.data)
    revalidatePlanPaths(id)
    return { success: true, message: "Course plan updated", data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function deleteCoursePlanAction(
  id: string
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    // 权限二次校验：非 admin 只能删除自己负责的计划
    const scope = resolveScope(ctx)
    const existing = await getCoursePlanById(id, scope)
    if (!existing) return { success: false, message: "Course plan not found" }

    await deleteCoursePlan(id)
    revalidatePlanPaths()
    return { success: true, message: "Course plan deleted" }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function getCoursePlansAction(
  params?: GetCoursePlansParams
): Promise<ActionState<CoursePlanListItem[]>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_READ)

    // P1-6：Zod 验证入参（避免 union 类型问题，提前返回）
    if (params) {
      const parsed = GetCoursePlansParamsSchema.safeParse(params)
      if (!parsed.success) {
        return {
          success: false,
          message: "Invalid params",
          errors: parsed.error.flatten().fieldErrors,
        }
      }
      const scope = resolveScope(ctx)
      const data = await getCoursePlans(parsed.data, scope)
      return { success: true, data }
    }

    const scope = resolveScope(ctx)
    const data = await getCoursePlans(undefined, scope)
    return { success: true, data }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function getCoursePlanAction(
  id: string
): Promise<ActionState<CoursePlanWithItems>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_READ)
    const scope = resolveScope(ctx)
    const data = await getCoursePlanById(id, scope)
    if (!data) return { success: false, message: "Course plan not found" }
    return { success: true, data }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function createCoursePlanItemAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    const parsed = CreateCoursePlanItemSchema.safeParse({
      planId: formData.get("planId"),
      week: formData.get("week") || undefined,
      topic: formData.get("topic"),
      content: formData.get("content") || undefined,
      hours: formData.get("hours") || undefined,
      textbookChapter: formData.get("textbookChapter") || undefined,
      notes: formData.get("notes") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid form data",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    // 权限二次校验：非 admin 只能操作自己负责的计划
    const scope = resolveScope(ctx)
    const existing = await getCoursePlanById(parsed.data.planId, scope)
    if (!existing) return { success: false, message: "Course plan not found" }

    const itemId = await createCoursePlanItem(parsed.data)
    revalidatePlanPaths(parsed.data.planId)
    return { success: true, message: "Week plan added", data: itemId }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function updateCoursePlanItemAction(
  id: string,
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    const parsed = UpdateCoursePlanItemSchema.safeParse({
      week: formData.get("week") || undefined,
      topic: formData.get("topic") || undefined,
      content: formData.get("content") || undefined,
      hours: formData.get("hours") || undefined,
      textbookChapter: formData.get("textbookChapter") || undefined,
      notes: formData.get("notes") || undefined,
      isCompleted:
        formData.get("isCompleted") === "true"
          ? true
          : formData.get("isCompleted") === "false"
            ? false
            : undefined,
      completedAt: formData.get("completedAt") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid form data",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    await updateCoursePlanItem(id, parsed.data)
    revalidatePlanPaths()
    return { success: true, message: "Week plan updated", data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function deleteCoursePlanItemAction(
  id: string
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.COURSE_PLAN_MANAGE)
    await deleteCoursePlanItem(id)
    revalidatePlanPaths()
    return { success: true, message: "Week plan deleted" }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function toggleCoursePlanItemCompletedAction(
  id: string,
  completed: boolean
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.COURSE_PLAN_MANAGE)
    await updateCoursePlanItem(id, {
      isCompleted: completed,
      completedAt: completed ? new Date().toISOString().slice(0, 10) : null,
    })
    revalidatePlanPaths()
    return {
      success: true,
      message: completed ? "Marked as completed" : "Marked as incomplete",
    }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 拖拽排序周计划条目（P1-7）。
 */
export async function reorderCoursePlanItemsAction(
  input: { planId: string; items: ReorderCoursePlanItemInput[] }
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    const parsed = ReorderItemsSchema.safeParse(input)
    if (!parsed.success) {
      return { success: false, message: "Invalid params", errors: parsed.error.flatten().fieldErrors }
    }

    // 权限二次校验：非 admin 只能操作自己负责的计划
    const scope = resolveScope(ctx)
    const existing = await getCoursePlanById(parsed.data.planId, scope)
    if (!existing) return { success: false, message: "Course plan not found" }

    await reorderCoursePlanItems(parsed.data.planId, parsed.data.items)
    revalidatePlanPaths(parsed.data.planId)
    return { success: true, message: "Order saved", data: parsed.data.planId }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 批量标记周计划条目完成状态（P2-4）。
 */
export async function bulkToggleItemsAction(
  itemIds: string[],
  completed: boolean
): Promise<ActionState<number>> {
  try {
    await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    const parsed = BulkToggleSchema.safeParse({ itemIds, completed })
    if (!parsed.success) {
      return { success: false, message: "Invalid params", errors: parsed.error.flatten().fieldErrors }
    }

    const count = await bulkUpdateItemCompleted(parsed.data.itemIds, parsed.data.completed)
    revalidatePlanPaths()
    return { success: true, message: "Bulk updated", data: count }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 复制课程计划到其他班级（P2-4）。
 */
export async function copyCoursePlanAction(
  sourcePlanId: string,
  targetClassIds: string[]
): Promise<ActionState<string[]>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_MANAGE)

    const parsed = CopyPlanSchema.safeParse({ sourcePlanId, targetClassIds })
    if (!parsed.success) {
      return { success: false, message: "Invalid params", errors: parsed.error.flatten().fieldErrors }
    }

    // 权限二次校验：非 admin 只能复制自己负责的计划
    const scope = resolveScope(ctx)
    const existing = await getCoursePlanById(parsed.data.sourcePlanId, scope)
    if (!existing) return { success: false, message: "Course plan not found" }

    const ids = await copyCoursePlanToClasses(parsed.data.sourcePlanId, parsed.data.targetClassIds)
    revalidatePlanPaths()
    return { success: true, message: "Copied", data: ids }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 获取课程计划模板候选列表（P2-5 模板库）。
 *
 * 复用现有计划作为模板：返回当前用户可见范围内的计划（含 items 数量），
 * 供 "从模板创建" 选择器使用。不新增 DB 表，避免 schema 迁移。
 *
 * @param subjectId 可选，按学科过滤
 */
export async function getTemplateCandidatesAction(
  subjectId?: string
): Promise<ActionState<CoursePlanListItem[]>> {
  try {
    const ctx = await requirePermission(Permissions.COURSE_PLAN_READ)
    const scope = resolveScope(ctx)
    const data = await getCoursePlans(
      subjectId ? { subjectId } : undefined,
      scope
    )
    return { success: true, data }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 年级仪表盘 - 维度4：获取年级下所有班级的教学计划进度。
 */
export async function getGradeCoursePlanProgressAction(
  gradeId: string
): Promise<ActionState<GradeCoursePlanProgressResult>> {
  try {
    await requirePermission(Permissions.COURSE_PLAN_READ)

    const parsed = GradeIdSchema.safeParse({ gradeId })
    if (!parsed.success) {
      return { success: false, message: "Invalid grade id" }
    }

    const data = await getGradeCoursePlanProgress({ gradeId: parsed.data.gradeId })
    return { success: true, data }
  } catch (e) {
    return handleActionError(e)
  }
}

// ── 监控埋点接口（P2-8）────────────────────────────────────
// trackCoursePlanEvent 已移至 lib/track-event.ts，因其为同步函数，
// 不允许出现在 "use server" 文件中（Next.js 16 规则）。
