"use server"

import { revalidatePath } from "next/cache"
import { getTranslations } from "next-intl/server"
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 { trackEvent } from "@/shared/lib/track-event"
import { verifyParentChildRelation } from "@/modules/parent/data-access"
import { getStudentActiveClass } from "@/modules/classes/data-access"
import { syncExcusedFromLeaveRequest } from "@/modules/attendance/data-access"

import { CreateLeaveRequestSchema, ReviewLeaveRequestSchema } from "./schema"
import {
  createLeaveRequest,
  getLeaveRequest,
  getLeaveRequests,
  hasOverlappingLeave,
  reviewLeaveRequest,
  cancelLeaveRequest,
  markAttendanceSynced,
} from "./data-access"
import type { LeaveType } from "./types"

/**
 * 校验提交人对学生的归属：
 * - 家长视角：必须通过 verifyParentChildRelation 校验
 * - 学生本人：requesterId === studentId（由调用方保证，本函数不处理）
 * 返回值：true 表示是家长代提交且关系已校验；false 表示非家长路径（学生本人）。
 */
async function assertRequesterRelation(
  studentId: string,
  requesterId: string,
): Promise<{ isParent: boolean; ok: boolean }> {
  if (studentId === requesterId) {
    return { isParent: false, ok: true }
  }
  const relation = await verifyParentChildRelation(studentId, requesterId)
  return { isParent: true, ok: relation !== null }
}

/** 创建请假申请（家长代子女 / 学生本人）。 */
export async function createLeaveRequestAction(
  prevState: ActionState<string> | null,
  formData: FormData,
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("leave")
    const ctx = await requirePermission(Permissions.LEAVE_REQUEST_CREATE)

    const parsed = CreateLeaveRequestSchema.safeParse({
      studentId: formData.get("studentId"),
      classId: formData.get("classId"),
      leaveType: formData.get("leaveType"),
      startDate: formData.get("startDate"),
      endDate: formData.get("endDate"),
      reason: formData.get("reason"),
    })

    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    // 校验提交人与学生的归属关系
    const relation = await assertRequesterRelation(parsed.data.studentId, ctx.userId)
    if (!relation.ok) {
      return { success: false, message: t("errors.noRelation") }
    }

    // 校验 classId 确为学生当前所在班级（防止伪造班级 ID）
    const activeClass = await getStudentActiveClass(parsed.data.studentId)
    if (!activeClass || activeClass.classId !== parsed.data.classId) {
      return { success: false, message: t("errors.classMismatch") }
    }

    // 校验日期范围内无未结束的请假
    const hasOverlap = await hasOverlappingLeave(
      parsed.data.studentId,
      parsed.data.startDate,
      parsed.data.endDate,
    )
    if (hasOverlap) {
      return { success: false, message: t("errors.overlappingLeave") }
    }

    const id = await createLeaveRequest(parsed.data, ctx.userId)
    revalidatePath("/parent/leave")
    revalidatePath("/student/leave")
    revalidatePath("/teacher/leave")
    await trackEvent({
      event: "leave_request.created",
      userId: ctx.userId,
      targetId: id,
      targetType: "leave_request",
      properties: {
        studentId: parsed.data.studentId,
        classId: parsed.data.classId,
        leaveType: parsed.data.leaveType,
        startDate: parsed.data.startDate,
        endDate: parsed.data.endDate,
      },
    })
    return { success: true, message: t("messages.created"), data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

/** 审批请假申请（班主任 / 管理员）。 */
export async function reviewLeaveRequestAction(
  id: string,
  prevState: ActionState<string> | null,
  formData: FormData,
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("leave")
    const ctx = await requirePermission(Permissions.LEAVE_REQUEST_REVIEW)

    const parsed = ReviewLeaveRequestSchema.safeParse({
      status: formData.get("status"),
      reviewComment: formData.get("reviewComment") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    // 拒绝时审批意见必填
    if (parsed.data.status === "rejected" && !parsed.data.reviewComment?.trim()) {
      return { success: false, message: t("errors.reviewCommentRequired") }
    }

    // 校验审批人对该请假所在班级的归属
    const target = await getLeaveRequest(id, ctx.dataScope, ctx.userId)
    if (!target) {
      return { success: false, message: t("errors.notFound") }
    }

    // class_taught scope 下，data-access 已通过 buildScopeFilter 过滤；admin 直接放行
    // 但仍需再次确认 target.status === 'pending'（reviewLeaveRequest 内部也会校验）
    if (target.status !== "pending") {
      return { success: false, message: t("errors.alreadyReviewed") }
    }

    const updated = await reviewLeaveRequest(id, parsed.data, ctx.userId)
    if (!updated) {
      return { success: false, message: t("errors.alreadyReviewed") }
    }

    // 审批通过后异步同步考勤（写入 excused 记录）
    if (updated.status === "approved" && !updated.attendanceSynced) {
      try {
        const leaveTypeLabel = leaveTypeReasonLabel(updated.leaveType)
        await syncExcusedFromLeaveRequest({
          studentId: updated.studentId,
          classId: updated.classId,
          startDate: updated.startDate,
          endDate: updated.endDate,
          reason: `请假：${leaveTypeLabel}（${updated.reason.slice(0, 80)}）`,
          reviewerId: ctx.userId,
        })
        await markAttendanceSynced(id)
      } catch {
        // 考勤同步失败不阻断审批结果（审批已成功，考勤可由管理员后续手动补录）
        // 不抛出错误，但也不标记 attendanceSynced，便于后续重试
      }
    }

    revalidatePath("/teacher/leave")
    revalidatePath("/parent/leave")
    revalidatePath(`/teacher/leave/${id}`)
    await trackEvent({
      event: "leave_request.reviewed",
      userId: ctx.userId,
      targetId: id,
      targetType: "leave_request",
      properties: { status: parsed.data.status },
    })
    return {
      success: true,
      message:
        parsed.data.status === "approved"
          ? t("messages.approved")
          : t("messages.rejected"),
    }
  } catch (e) {
    return handleActionError(e)
  }
}

/** 撤销请假申请（仅 pending 状态、提交人本人可撤销）。 */
export async function cancelLeaveRequestAction(
  id: string,
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("leave")
    const ctx = await requirePermission(Permissions.LEAVE_REQUEST_CREATE)

    const target = await getLeaveRequest(id, ctx.dataScope, ctx.userId)
    if (!target) {
      return { success: false, message: t("errors.notFound") }
    }
    if (target.requesterId !== ctx.userId) {
      return { success: false, message: t("errors.notOwner") }
    }
    if (target.status !== "pending") {
      return { success: false, message: t("errors.cannotCancel") }
    }

    const updated = await cancelLeaveRequest(id, ctx.userId)
    if (!updated) {
      return { success: false, message: t("errors.cannotCancel") }
    }

    revalidatePath("/parent/leave")
    revalidatePath("/student/leave")
    revalidatePath("/teacher/leave")
    await trackEvent({
      event: "leave_request.cancelled",
      userId: ctx.userId,
      targetId: id,
      targetType: "leave_request",
    })
    return { success: true, message: t("messages.cancelled") }
  } catch (e) {
    return handleActionError(e)
  }
}

/** 请假类型中文标签（用于考勤同步 reason 文本，服务端无 i18n 上下文）。 */
function leaveTypeReasonLabel(type: LeaveType): string {
  const labels: Record<LeaveType, string> = {
    sick: "病假",
    personal: "事假",
    family: "家庭事务",
    other: "其他",
  }
  return labels[type] ?? type
}

/** 内部查询辅助：供页面 Server Component 使用（包装 dataScope）。 */
export async function listMyLeaveRequests(
  scope: Parameters<typeof getLeaveRequests>[0]["scope"],
  currentUserId: string,
  status?: Parameters<typeof getLeaveRequests>[0]["status"],
): ReturnType<typeof getLeaveRequests> {
  return getLeaveRequests({ scope, currentUserId, status, page: 1, pageSize: 50 })
}
