"use server";

import { db } from "@/lib/prisma";
import { requireTeacher } from "@/lib/auth/requireTeacher";
import { z } from "zod";
import { revalidatePath } from "next/cache";
import { ContentStatus, Prisma, ProficiencyLevel } from "@prisma/client";
import {
  buildLessonDescriptionMeta,
  parseLessonDescriptionMeta,
  type LessonContentType,
} from "@/lib/courses/lessonContent";

// --- VALIDATION SCHEMAS (Zod) ---

const createCourseSchema = z.object({
    title: z.string().min(3, "El título debe tener al menos 3 caracteres"),
});

// --- ACTIONS ---

/**
 * 1. LIST COURSES
 * Used by: app/(protected)/teacher/page.tsx (Dashboard)
 */
export async function getTeacherCourses() {
    const user = await requireTeacher();

    if (!user) {
        return { success: false, error: "No autorizado" };
    }

    try {
        const courses = await db.course.findMany({
            where: {
                authorId: user.id,
            },
            orderBy: {
                updatedAt: "desc",
            },
            select: {
                id: true,
                title: true,
                slug: true,
                price: true,
                status: true,
                level: true,
                _count: {
                    select: {
                        modules: true,
                        enrollments: true,
                    }
                }
            }
        });

        return { success: true, data: courses };
    } catch (error) {
        console.error("Error fetching courses:", error);
        return { success: false, error: "Error al cargar los cursos" };
    }
}

/**
 * 2. CREATE COURSE (Draft) */
export async function createCourse(formData: FormData) {
    const user = await requireTeacher();

    if (!user) {
        return { success: false, error: "No autorizado" };
    }

    // 1. Extract & Validate
    const rawTitle = formData.get("title");
    const validated = createCourseSchema.safeParse({ title: rawTitle });

    if (!validated.success) {
        return { success: false, error: validated.error.flatten().fieldErrors.title?.[0] || "Error en el título" };
    }

    const title = validated.data.title;

    // 2. Generate basic slug
    const slug = `${title.toLowerCase().replace(/ /g, "-").replace(/[^\w-]/g, "")}-${Math.floor(Math.random() * 10000)}`;

    try {
        // 3. Create DB Record
        const course = await db.course.create({
            data: {
                title: title,
                slug: slug,
                authorId: user.id,
                description: "Descripción pendiente...",
                status: "DRAFT",
            },
        });

        // 4. Revalidate & Return
        revalidatePath("/teacher/courses");
        return { success: true, data: course };

    } catch (error) {
        console.error("Create course error:", error);
        return { success: false, error: "No se pudo crear el curso." };
    }
}

/**
 * 3. DELETE COURSE */
export async function deleteCourse(courseId: string) {
    const user = await requireTeacher();

    if (!user) return { success: false, error: "No autorizado" };

    try {
        const course = await db.course.findUnique({
            where: { id: courseId },
            select: { authorId: true }
        });

        if (!course || course.authorId !== user.id) {
            return { success: false, error: "No tienes permiso para eliminar este curso." };
        }

        await db.course.delete({
            where: { id: courseId },
        });

        revalidatePath("/teacher/courses");
        return { success: true, data: "Curso eliminado" };

    } catch {
        return { success: false, error: "Error al eliminar el curso" };
    }
}

function parseLearningOutcomes(raw: FormDataEntryValue | null): string[] {
    if (raw == null || typeof raw !== "string") return [];
    try {
        const parsed = JSON.parse(raw) as unknown;
        if (!Array.isArray(parsed)) return [];
        return parsed.filter((x): x is string => typeof x === "string");
    } catch {
        return [];
    }
}

export async function updateCourse(courseId: string, courseSlug: string, formData: FormData) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };

    try {
        const title = formData.get("title") as string;
        const summary = formData.get("summary") as string;
        // Direct cast is okay if you trust the select/input values
        const level = formData.get("level") as ProficiencyLevel;
        const status = formData.get("status") as ContentStatus;
        const price = parseFloat(formData.get("price") as string) || 0;
        const learningOutcomes = parseLearningOutcomes(formData.get("learningOutcomes"));

        await db.course.update({
            where: { id: courseId, authorId: user.id },
            data: {
                title,
                description: summary,
                level,
                status,
                price,
                learningOutcomes:
                    learningOutcomes.length > 0 ? (learningOutcomes as Prisma.InputJsonValue) : Prisma.JsonNull,
            } as Prisma.CourseUpdateInput,
        });

        // Revalidate teacher list, editor page + layout (so router.refresh() gets fresh data), and public catalog
        revalidatePath("/teacher/courses");
        revalidatePath(`/teacher/courses/${courseSlug}/edit`, "page");
        revalidatePath(`/teacher/courses/${courseSlug}/edit`, "layout");
        revalidatePath("/courses");
        return { success: true };
    } catch {
        return { success: false, error: "Failed to update" };
    }
}

export async function updateLesson(lessonId: string, data: {
    title?: string;
    description?: string;
    videoUrl?: string;
    youtubeUrl?: string;
    materialUrl?: string;
    contentType?: LessonContentType;
    estimatedDurationMinutes?: number;
    isPreview?: boolean; // maps to DB field isFreePreview
    isPublished?: boolean; // optional: for later
}) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };

    try {
        const updateData: Prisma.LessonUpdateInput = { updatedAt: new Date() };
        if (data.title !== undefined) updateData.title = data.title;
        if (data.videoUrl !== undefined) updateData.videoUrl = data.videoUrl;
        if (data.youtubeUrl !== undefined) updateData.youtubeUrl = data.youtubeUrl;
        if (data.estimatedDurationMinutes !== undefined) {
          const minutes = Math.max(0, Math.round(data.estimatedDurationMinutes));
          updateData.estimatedDuration = minutes * 60;
        }
        if (data.isPreview !== undefined) updateData.isFreePreview = data.isPreview;

        const shouldUpdateMeta =
          data.description !== undefined || data.contentType !== undefined || data.materialUrl !== undefined;

        if (shouldUpdateMeta) {
          const lesson = await db.lesson.findUnique({
            where: { id: lessonId },
            select: { description: true },
          });

          const existingMeta = parseLessonDescriptionMeta(lesson?.description);
          updateData.description = buildLessonDescriptionMeta({
            text: data.description ?? existingMeta.text,
            contentType: data.contentType ?? existingMeta.contentType,
            materialUrl: data.materialUrl ?? existingMeta.materialUrl,
          });
        }

        await db.lesson.update({
            where: { id: lessonId },
            data: updateData,
        });

        // 2. Revalidate to show changes immediately
        revalidatePath("/teacher/courses");
        return { success: true };
    } catch (error) {
        console.error("Update Lesson Error:", error);
        return { success: false, error: "Failed to update lesson" };
    }
}

export async function createModule(courseId: string) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };

    try {
        // Find the highest orderIndex so we can put the new one at the end
        const lastModule = await db.module.findFirst({
            where: { courseId },
            orderBy: { orderIndex: "desc" },
        });

        const newOrder = lastModule ? lastModule.orderIndex + 1 : 0;

        await db.module.create({
            data: {
                courseId,
                title: "Nuevo Módulo", // Default title
                orderIndex: newOrder,
            },
        });

        revalidatePath("/teacher/courses");
        return { success: true };
    } catch (error) {
        console.error("Create Module Error:", error);
        return { success: false, error: "Failed to create module" };
    }
}

/**
 * UPDATE MODULE TITLE
 */
export async function updateModuleTitle(moduleId: string, title: string) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };

    const trimmed = title?.trim() || "";
    if (!trimmed) return { success: false, error: "El título no puede estar vacío" };

    try {
        const moduleRow = await db.module.findFirst({
            where: { id: moduleId, course: { authorId: user.id } },
            select: { id: true, course: { select: { slug: true } } },
        });
        if (!moduleRow) return { success: false, error: "Módulo no encontrado" };

        await db.module.update({
            where: { id: moduleId },
            data: { title: trimmed },
        });

        revalidatePath("/teacher/courses");
        revalidatePath(`/teacher/courses/${moduleRow.course.slug}/edit`, "page");
        revalidatePath(`/teacher/courses/${moduleRow.course.slug}/edit`, "layout");
        return { success: true };
    } catch (error) {
        console.error("Update Module Title Error:", error);
        return { success: false, error: "No se pudo actualizar el título" };
    }
}

// 2. CREATE LESSON
export async function createLesson(moduleId: string) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };

    try {
        // Find the highest orderIndex for lessons in this module
        const lastLesson = await db.lesson.findFirst({
            where: { moduleId },
            orderBy: { orderIndex: "desc" },
        });

        const newOrder = lastLesson ? lastLesson.orderIndex + 1 : 0;

        // Create the lesson with default values
        const lesson = await db.lesson.create({
            data: {
                moduleId,
                title: "Nueva Lección",
                description: {
                  contentType: "VIDEO",
                },
                orderIndex: newOrder,
                estimatedDuration: 0,
                version: 1,
                // The type field is required in your schema (based on previous context)
                // If you have a 'type' enum, set a default like 'VIDEO' or 'TEXT'
                // type: "VIDEO", 
            },
        });

        revalidatePath(`/teacher/courses/${moduleId}/edit`, "page");
        return { success: true, lessonId: lesson.id };
    } catch (error) {
        console.error("Create Lesson Error:", error);
        return { success: false, error: "Failed to create lesson" };
    }
}

/**
 * DELETE MODULE
 * Also deletes all lessons inside it due to Prisma cascade or manual cleanup
 */
export async function deleteModule(moduleId: string) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };
  
    try {
      await db.module.delete({
        where: { 
          id: moduleId,
          course: { authorId: user.id } // Security: ownership check
        },
      });
  
      revalidatePath("/teacher/courses");
      return { success: true };
    } catch {
      return { success: false, error: "No se pudo eliminar el módulo" };
    }
  }
  
  /**
   * DELETE LESSON
   */
  export async function deleteLesson(lessonId: string) {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };
  
    try {
      await db.lesson.delete({
        where: { 
          id: lessonId,
          module: { course: { authorId: user.id } } // Deep ownership check
        },
      });
  
      revalidatePath("/teacher/courses");
      return { success: true };
    } catch {
      return { success: false, error: "No se pudo eliminar la lección" };
    }
  }

  export async function reorderModules(moduleId: string, direction: 'up' | 'down') {
    const user = await requireTeacher();
    if (!user) return { success: false, error: "Unauthorized" };
  
    const currentModule = await db.module.findUnique({
      where: { id: moduleId },
      include: { course: true }
    });
  
    if (!currentModule || currentModule.course.authorId !== user.id) {
      return { success: false, error: "Module not found" };
    }
  
    const siblingModule = await db.module.findFirst({
      where: {
        courseId: currentModule.courseId,
        orderIndex: direction === 'up' 
          ? { lt: currentModule.orderIndex } 
          : { gt: currentModule.orderIndex }
      },
      orderBy: { orderIndex: direction === 'up' ? 'desc' : 'asc' }
    });
  
    if (!siblingModule) return { success: true }; // Already at the top/bottom
  
    // Swap orderIndex values
    await db.$transaction([
      db.module.update({
        where: { id: currentModule.id },
        data: { orderIndex: siblingModule.orderIndex }
      }),
      db.module.update({
        where: { id: siblingModule.id },
        data: { orderIndex: currentModule.orderIndex }
      })
    ]);
  
    revalidatePath(`/teacher/courses/${currentModule.course.slug}/edit`, "page");
    return { success: true };
  }

/**
 * Reorder lessons within the same module (swap orderIndex with sibling)
 */
export async function reorderLessons(lessonId: string, direction: "up" | "down") {
  const user = await requireTeacher();
  if (!user) return { success: false, error: "Unauthorized" };

  const currentLesson = await db.lesson.findUnique({
    where: { id: lessonId },
    include: { module: { include: { course: true } } },
  });

  if (!currentLesson || currentLesson.module.course.authorId !== user.id) {
    return { success: false, error: "Lesson not found" };
  }

  const siblingLesson = await db.lesson.findFirst({
    where: {
      moduleId: currentLesson.moduleId,
      orderIndex:
        direction === "up"
          ? { lt: currentLesson.orderIndex }
          : { gt: currentLesson.orderIndex },
    },
    orderBy: { orderIndex: direction === "up" ? "desc" : "asc" },
  });

  if (!siblingLesson) return { success: true }; // Already at top/bottom

  await db.$transaction([
    db.lesson.update({
      where: { id: currentLesson.id },
      data: { orderIndex: siblingLesson.orderIndex },
    }),
    db.lesson.update({
      where: { id: siblingLesson.id },
      data: { orderIndex: currentLesson.orderIndex },
    }),
  ]);

  revalidatePath(`/teacher/courses/${currentLesson.module.course.slug}/edit`, "page");
  return { success: true };
}
