import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { requireRole, requireSchoolScope, hashPassword, ApiError, getDefaultSchoolId } from "@/lib/auth";
import { logAudit } from "@/lib/audit";
import { handleApiError } from "@/lib/api-helpers";
import { DEFAULT_CLASSROOMS } from "@/lib/constants";
import { randomBytes } from "node:crypto";

/** قائمة المدارس مع إحصائيات مختصرة — المدير العام يرى الكل، وغيره مدرسته فقط */
export async function GET(req: NextRequest) {
  try {
    const viewer = await requireRole("ADMIN", "ACCOUNTANT", "STAFF");
    let schools;
    if (viewer.role === "SUPER_ADMIN") {
      schools = await db.school.findMany({ orderBy: { createdAt: "asc" } });
    } else {
      schools = viewer.schoolId
        ? await db.school.findMany({ where: { id: viewer.schoolId } })
        : [];
    }
    const studentCounts = await db.student.groupBy({
      by: ["schoolId"],
      where: { isActive: true },
      _count: { _all: true },
    });
    const userCounts = await db.user.groupBy({
      by: ["schoolId"],
      where: { deletedAt: null },
      _count: { _all: true },
    });
    const sMap = new Map(studentCounts.map((c) => [c.schoolId, c._count._all]));
    const uMap = new Map(userCounts.map((c) => [c.schoolId, c._count._all]));
    const defaultId = await getDefaultSchoolId();
    return NextResponse.json({
      schools: schools.map((s) => ({
        ...s,
        studentsCount: sMap.get(s.id) ?? 0,
        usersCount: uMap.get(s.id) ?? 0,
        isDefault: s.id === defaultId,
      })),
      activeSchoolId: defaultId,
    });
  } catch (err) {
    return handleApiError(err);
  }
}

/** إضافة مدرسة جديدة (مدير النظام العام فقط) مع إمكانية إنشاء حساب مدير للمدرسة في نفس الخطوة */
export async function POST(req: NextRequest) {
  try {
    const user = await requireRole("SUPER_ADMIN");
    const body = await req.json();
    const { name, nameEn, address, phone, adminUsername, adminPassword, adminFullName, adminPhone } =
      body as Record<string, string>;

    const cleanName = String(name || "").trim();
    if (cleanName.length < 3) {
      throw new ApiError("اسم المدرسة مطلوب (3 خانات على الأقل)", 400);
    }
    const duplicate = await db.school.findFirst({ where: { name: cleanName } });
    if (duplicate) {
      throw new ApiError(`يوجد نظام مدرسة بهذا الاسم مسبقاً: ${cleanName}`, 409);
    }

    const school = await db.school.create({
      data: {
        name: cleanName,
        nameEn: nameEn ? String(nameEn).trim() : null,
        address: address ? String(address).trim() : null,
        phone: phone ? String(phone).trim() : null,
      },
    });

    // الشعب الافتراضية للمدرسة الجديدة
    await db.classroom.createMany({
      data: DEFAULT_CLASSROOMS.map((cls) => ({ name: cls, schoolId: school.id })),
    });

    // حساب مدير للمدرسة (اختياري لكنه مستحسن)
    let createdAdmin: { username: string; fullName: string; recoveryCode: string } | null = null;
    if (adminUsername && adminPassword) {
      const uname = String(adminUsername).trim();
      if (!/^[a-zA-Z0-9_.]{3,30}$/.test(uname)) {
        throw new ApiError("اسم مستخدم مدير المدرسة غير صالح (حروف إنجليزية وأرقام، 3-30 خانة)", 400);
      }
      if (String(adminPassword).length < 8 || Buffer.byteLength(String(adminPassword), "utf8") > 72) {
        throw new ApiError("كلمة مرور مدير المدرسة يجب ألا تقل عن 8 خانات وألا تتجاوز 72 بايتاً", 400);
      }
      const cleanAdminPhone = typeof adminPhone === "string" ? adminPhone.replace(/[\s()-]/g, "") : "";
      if (!/^\+?[0-9]{7,15}$/.test(cleanAdminPhone)) throw new ApiError("رقم هاتف صحيح مطلوب لحساب مدير المدرسة", 400);
      const phoneOwner = await db.user.findFirst({ where: { phone: cleanAdminPhone, isActive: true, deletedAt: null }, select: { id: true } });
      if (phoneOwner) throw new ApiError("رقم الهاتف مرتبط بحساب نشط آخر", 409);
      const exists = await db.user.findUnique({ where: { username: uname } });
      if (exists) {
        throw new ApiError(`اسم المستخدم ${uname} محجوز مسبقاً - اختر اسماً آخر`, 409);
      }
      const passwordHash = await hashPassword(String(adminPassword));
      const recoveryCode = randomBytes(16).toString("hex").toUpperCase();
      const recoveryCodeHash = await hashPassword(recoveryCode);
      const adminUser = await db.user.create({
        data: {
          username: uname,
          passwordHash,
          phone: cleanAdminPhone,
          recoveryCodeHash,
          fullName: adminFullName ? String(adminFullName).trim() : `مدير ${cleanName}`,
          role: "ADMIN",
          schoolId: school.id,
        },
      });
      createdAdmin = { username: adminUser.username, fullName: adminUser.fullName, recoveryCode };
      await logAudit(user, {
        action: "CREATE",
        entity: "User",
        entityId: adminUser.id,
        details: `إنشاء حساب مدير للمدرسة ${cleanName}: ${adminUser.fullName} (${adminUser.username})`,
      });
    }

    await logAudit(user, {
      action: "CREATE",
      entity: "School",
      entityId: school.id,
      details: `إضافة مدرسة جديدة: ${school.name}${createdAdmin ? ` مع حساب مدير (${createdAdmin.username})` : ""}`,
    });

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

/** تحديث بيانات مدرسة / تفعيل أو إيقاف (مدير النظام العام، أو مدير مدرسته فقط) */
export async function PATCH(req: NextRequest) {
  try {
    const user = await requireRole("ADMIN", "SUPER_ADMIN");
    const body = await req.json();
    const { id, name, nameEn, address, phone, isActive } = body as Record<string, string | boolean>;
    if (!id) throw new ApiError("يجب تحديد المدرسة", 400);

    const scope = await requireSchoolScope(req.nextUrl.searchParams.get("schoolId"));
    if (!scope.isSuperAdmin && scope.schoolId !== String(id)) {
      throw new ApiError("ليست لديك صلاحية تعديل هذه المدرسة", 403);
    }

    const school = await db.school.findUnique({ where: { id: String(id) } });
    if (!school) throw new ApiError("المدرسة غير موجودة", 404);

    const data: Record<string, string | boolean | null> = {};
    if (name !== undefined) {
      const cleanName = String(name).trim();
      if (cleanName.length < 3) throw new ApiError("اسم المدرسة قصير جداً", 400);
      const duplicate = await db.school.findFirst({ where: { name: cleanName, id: { not: school.id } } });
      if (duplicate) throw new ApiError(`يوجد نظام مدرسة بهذا الاسم مسبقاً: ${cleanName}`, 409);
      data.name = cleanName;
    }
    if (nameEn !== undefined) data.nameEn = String(nameEn).trim() || null;
    if (address !== undefined) data.address = String(address).trim() || null;
    if (phone !== undefined) data.phone = String(phone).trim() || null;
    if (typeof isActive === "boolean") data.isActive = isActive;

    const updated = await db.school.update({ where: { id: school.id }, data });
    await logAudit(user, {
      action: "UPDATE",
      entity: "School",
      entityId: school.id,
      details: `تعديل بيانات المدرسة: ${updated.name}${typeof isActive === "boolean" ? ` (${isActive ? "تفعيل" : "إيقاف"})` : ""}`,
    });
    return NextResponse.json({ school: updated });
  } catch (err) {
    return handleApiError(err);
  }
}
