import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { requirePageRole, resolveSchoolId, ApiError } from "@/lib/auth";
import { logAudit } from "@/lib/audit";
import { handleApiError } from "@/lib/api-helpers";
import { generateStudentCode, normalizeArabicName, effectiveFee, GRADES } from "@/lib/constants";
import { isValidGradeCode } from "@/lib/grade-helpers";
import { rebuildInstallmentSchedule } from "@/lib/installments";

/** البحث عن الطلاب بالاسم أو الكود + قائمة الطلاب مع حالة الأقساط (نطاق المدرسة) */
export async function GET(req: NextRequest) {
  try {
    const user = await requirePageRole("students", "ADMIN", "ACCOUNTANT", "STAFF");
    const schoolId = await resolveSchoolId(user, req.nextUrl.searchParams.get("schoolId"));
    const { searchParams } = new URL(req.url);
    const query = searchParams.get("q")?.trim() ?? "";
    const grade = searchParams.get("grade")?.trim() ?? "";
    const limit = Math.min(parseInt(searchParams.get("limit") || "50"), 200);

    const where: Record<string, unknown> = { isActive: true, schoolId };
    if (query) {
      where.OR = [
        { nameAr: { contains: query } },
        { nameEn: { contains: query } },
        { studentCode: { contains: query } },
        { guardianPhone: { contains: query } },
      ];
    }
    if (grade) where.grade = grade;

    const students = await db.student.findMany({
      where,
      orderBy: { createdAt: "desc" },
      take: limit,
      include: { payments: { select: { amount: true } } },
    });

    const data = students.map((s) => {
      const paid = s.payments.reduce((sum, p) => sum + p.amount, 0);
      const eff = effectiveFee(s.totalFee, s.discountPercent);
      return {
        id: s.id,
        studentCode: s.studentCode,
        nameAr: s.nameAr,
        nameEn: s.nameEn,
        grade: s.grade,
        classroom: s.classroom,
        guardianName: s.guardianName,
        guardianPhone: s.guardianPhone,
        guardianAddress: s.guardianAddress,
        notes: s.notes,
        totalFee: s.totalFee,
        discountPercent: s.discountPercent,
        effectiveFee: eff,
        feeDueDate: s.feeDueDate,
        registeredAt: s.registeredAt,
        createdAt: s.createdAt,
        paid,
        remaining: Math.max(0, eff - paid),
        paymentsCount: s.payments.length,
      };
    });
    return NextResponse.json({ students: data, viewerRole: user.role });
  } catch (err) {
    return handleApiError(err);
  }
}

/** تسجيل طالب جديد مع توليد الكود التلقائي + شرط الاسم الرباعي + فحص التطابق (داخل المدرسة) */
export async function POST(req: NextRequest) {
  try {
    const user = await requirePageRole("students", "ADMIN", "STAFF", "SUPER_ADMIN");
    const schoolId = await resolveSchoolId(user, req.nextUrl.searchParams.get("schoolId"));
    const body = await req.json();
    const {
      nameAr, nameEn, grade, classroom, guardianName, guardianPhone,
      guardianAddress, notes, totalFee, feeDueDate, discountPercent, allowDuplicate,
      registeredAt,
    } = body as Record<string, string | number | boolean | undefined>;

    // تاريخ التسجيل الفعلي (قابل للتعديل من الموظف مثل تاريخ شهر آب) — الافتراضي الآن ولا يقبل تواريخ مستقبلية
    let registeredAtDate = new Date();
    if (registeredAt !== undefined && registeredAt !== null && String(registeredAt).trim() !== "") {
      const d = new Date(String(registeredAt));
      if (isNaN(d.getTime())) throw new ApiError("تاريخ التسجيل غير صالح", 400);
      if (d.getTime() > Date.now() + 5 * 60 * 1000) {
        throw new ApiError("لا يمكن تسجيل طالب بتاريخ مستقبلي", 400);
      }
      registeredAtDate = d;
    }

    const cleanNameAr = String(nameAr || "").trim().replace(/\s+/g, " ");
    const wordCount = cleanNameAr ? cleanNameAr.split(" ").length : 0;
    if (wordCount < 4) {
      return NextResponse.json(
        { error: `الاسم الرباعي إجباري — يجب إدخال الاسم بصيغة: الاسم + الأب + الجد + اللقب (المدخل ${wordCount} كلمات فقط)` },
        { status: 400 }
      );
    }
    if (!nameEn || String(nameEn).trim().length < 3) {
      return NextResponse.json({ error: "الاسم بالإنجليزية مطلوب" }, { status: 400 });
    }
    if (!grade || !classroom) {
      return NextResponse.json({ error: "المرحلة والشعبة مطلوبان" }, { status: 400 });
    }
    if (!(await isValidGradeCode(String(grade), schoolId))) {
      return NextResponse.json({ error: "الصف الدراسي غير صالح" }, { status: 400 });
    }
    const classroomExists = await db.classroom.findFirst({ where: { name: String(classroom), schoolId } });
    if (!classroomExists) {
      return NextResponse.json({ error: "الشعبة غير موجودة — أضفها من صفحة الصفوف والشعب" }, { status: 400 });
    }
    if (!guardianName || !guardianPhone) {
      return NextResponse.json({ error: "اسم ولي الأمر ورقم هاتفه مطلوبان" }, { status: 400 });
    }
    const fee = Number(totalFee);
    if (isNaN(fee) || fee < 0) {
      return NextResponse.json({ error: "القسط الكلي الإجمالي غير صالح" }, { status: 400 });
    }
    let discount = Number(discountPercent ?? 0);
    if (isNaN(discount) || discount < 0 || discount > 100) {
      return NextResponse.json({ error: "نسبة الخصم يجب أن تكون بين 0 و 100" }, { status: 400 });
    }
    discount = Math.round(discount * 100) / 100;

    // فحص تطابق الاسم داخل نفس المدرسة (توحيد الألف/الهاء/الياء والمسافات)
    const normalized = normalizeArabicName(cleanNameAr);
    const existingStudents = await db.student.findMany({
      where: { isActive: true, schoolId },
      select: { id: true, nameAr: true, grade: true, classroom: true, studentCode: true },
    });
    const duplicate = existingStudents.find((s) => normalizeArabicName(s.nameAr) === normalized);
    if (duplicate && allowDuplicate !== true) {
      return NextResponse.json(
        { error: `الاسم مسجل مسبقاً — الطالب: ${duplicate.nameAr} (${duplicate.studentCode}) في ${duplicate.grade} / شعبة ${duplicate.classroom}. إذا كان طالباً مختلفاً فعّل خيار السماح بالتسجيل بنفس الاسم.`, duplicateOf: duplicate.id },
        { status: 409 }
      );
    }

    // توليد الكود التلقائي: CODE-YEAR-SEQUENCE (تسلسل داخل المدرسة)
    const gradeDef = String(grade); // grade stores the code like "G5"
    const year = new Date().getFullYear();
    const prefix = `${gradeDef}-${year}-`;
    const lastStudent = await db.student.findFirst({
      where: { studentCode: { startsWith: prefix }, schoolId },
      orderBy: { studentCode: "desc" },
    });
    let sequence = 1;
    if (lastStudent) {
      const lastSeq = parseInt(lastStudent.studentCode.split("-")[2] || "0", 10);
      sequence = lastSeq + 1;
    }
    const studentCode = generateStudentCode(gradeDef, year, sequence);

    const student = await db.student.create({
      data: {
        studentCode,
        nameAr: cleanNameAr,
        nameEn: String(nameEn).trim(),
        grade: gradeDef,
        classroom: String(classroom),
        guardianName: String(guardianName).trim(),
        guardianPhone: String(guardianPhone).trim(),
        guardianAddress: guardianAddress ? String(guardianAddress) : null,
        notes: notes ? String(notes) : null,
        totalFee: fee,
        discountPercent: discount,
        feeDueDate: feeDueDate ? new Date(String(feeDueDate)) : null,
        registeredAt: registeredAtDate,
        registeredById: user.id,
        schoolId,
      },
    });

    // توليد جدول الأقساط التلقائي (v8.1) — 8 أقساط شهرية من تاريخ التسجيل
    await rebuildInstallmentSchedule(student.id);

    await logAudit(user, {
      action: "CREATE",
      entity: "Student",
      entityId: student.id,
      details: `تسجيل طالب جديد: ${student.nameAr} (${student.studentCode}) - القسط الكلي: ${fee}` +
        (discount > 0 ? ` - خصم: ${discount}%` : "") +
        ` - تاريخ التسجيل: ${student.registeredAt.toISOString().slice(0, 10)}` +
        (duplicate ? " - تم التسجيل بنفس اسم طالب موجود بتأكيد صريح" : ""),
    });

    return NextResponse.json({ student }, { status: 201 });
  } catch (err) {
    return handleApiError(err);
  }
}
