"use server"

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

import {
  CreateCoursePlanSchema,
  UpdateCoursePlanSchema,
  CreateCoursePlanItemSchema,
  UpdateCoursePlanItemSchema,
} from "./schema"
import {
  getCoursePlans,
  getCoursePlanById,
  createCoursePlan,
  updateCoursePlan,
  deleteCoursePlan,
  createCoursePlanItem,
  updateCoursePlanItem,
  deleteCoursePlanItem,
} from "./data-access"
import type { CoursePlanWithItems, GetCoursePlansParams, CoursePlanListItem } from "./types"

const handleError = (e: unknown): ActionState<never> => {
  if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
  if (e instanceof Error) return { success: false, message: e.message }
  return { success: false, message: "Unexpected error" }
}

const revalidatePlanPaths = (id?: string) => {
  revalidatePath("/admin/course-plans")
  revalidatePath("/teacher/course-plans")
  if (id) {
    revalidatePath(`/admin/course-plans/${id}`)
    revalidatePath(`/teacher/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 handleError(e)
  }
}

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

    const existing = await getCoursePlanById(id)
    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 handleError(e)
  }
}

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

    const existing = await getCoursePlanById(id)
    if (!existing) return { success: false, message: "Course plan not found" }

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

export async function getCoursePlansAction(
  params?: GetCoursePlansParams
): Promise<ActionState<CoursePlanListItem[]>> {
  try {
    await requirePermission(Permissions.COURSE_PLAN_READ)
    const data = await getCoursePlans(params)
    return { success: true, data }
  } catch (e) {
    return handleError(e)
  }
}

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

export async function createCoursePlanItemAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    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,
      }
    }

    const itemId = await createCoursePlanItem(parsed.data)
    revalidatePlanPaths(parsed.data.planId)
    return { success: true, message: "Week plan added", data: itemId }
  } catch (e) {
    return handleError(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 handleError(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 handleError(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 handleError(e)
  }
}
