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 { nextExpenseVoucherNumber } from "@/lib/voucher";

/** سلف المنتسبين (v8.1) — قائمة السلف مع المسدد والمتبقي لكل سلفة (نطاق المدرسة) */
export async function GET(req: NextRequest) {
  try {
    const user = await requirePageRole("finance", "ADMIN", "ACCOUNTANT");
    const schoolId = await resolveSchoolId(user, req.nextUrl.searchParams.get("schoolId"));
    const loans = await db.employeeLoan.findMany({
      where: { schoolId },
      orderBy: { loanedAt: "desc" },
      include: {
        employee: { select: { name: true, role: true, employeeType: true } },
        repayments: { orderBy: { paidAt: "asc" }, select: { id: true, amount: true, paidAt: true, notes: true } },
        expense: { select: { voucherNumber: true } },
      },
    });
    const rows = loans.map((l) => {
      const repaid = l.repayments.reduce((s, r) => s + r.amount, 0);
      return {
        id: l.id,
        employeeId: l.employeeId,
        employeeName: l.employee.name,
        employeeRole: l.employee.role,
        employeeType: l.employee.employeeType,
        amount: l.amount,
        reason: l.reason,
        loanedAt: l.loanedAt,
        notes: l.notes,
        voucherNumber: l.expense?.voucherNumber ?? null,
        repaid,
        remaining: Math.max(0, l.amount - repaid),
        fullyRepaid: repaid >= l.amount,
        repayments: l.repayments,
      };
    });
    return NextResponse.json({ loans: rows });
  } catch (err) {
    return handleApiError(err);
  }
}

/** منح سلفة لموظف — تُسجل مصروفاً تلقائياً (سلف منتسبين) مع رقم وصل صرف */
export async function POST(req: NextRequest) {
  try {
    const user = await requirePageRole("finance", "ADMIN", "ACCOUNTANT", "SUPER_ADMIN");
    const schoolId = await resolveSchoolId(user, req.nextUrl.searchParams.get("schoolId"));
    const body = (await req.json()) as Record<string, unknown>;
    const employeeId = String(body.employeeId ?? "");
    const amount = Number(body.amount);
    const reason = String(body.reason ?? "").trim();
    const notes = body.notes == null || String(body.notes).trim() === "" ? null : String(body.notes).trim();
    const loanedAt = body.loanedAt ? new Date(String(body.loanedAt)) : new Date();
    const manualVoucher = body.voucherNumber ? String(body.voucherNumber).trim() : "";

    if (!employeeId) throw new ApiError("الموظف مطلوب", 400);
    const employee = await db.employee.findFirst({ where: { id: employeeId, schoolId, deletedAt: null } });
    if (!employee) throw new ApiError("الموظف غير موجود", 404);
    if (!Number.isFinite(amount) || amount <= 0) throw new ApiError("مبلغ السلفة غير صالح", 400);
    if (reason.length < 2) throw new ApiError("سبب السلفة مطلوب", 400);
    if (isNaN(loanedAt.getTime())) throw new ApiError("تاريخ السلفة غير صالح", 400);

    const voucherNumber = manualVoucher || (await nextExpenseVoucherNumber(schoolId, loanedAt));

    const loan = await db.$transaction(async (tx) => {
      const expense = await tx.expense.create({
        data: {
          category: "سلف منتسبين",
          kind: "STAFF_LOAN_GIVEN",
          description: `سلفة للموظف: ${employee.name} — ${reason}`,
          amount,
          spentAt: loanedAt,
          voucherNumber,
          createdById: user.id,
          schoolId,
        },
      });
      return tx.employeeLoan.create({
        data: {
          employeeId, amount, reason, notes, loanedAt,
          expenseId: expense.id,
          creatorId: user.id,
          schoolId,
        },
        include: { employee: { select: { name: true } } },
      });
    });

    await logAudit(user, {
      action: "CREATE",
      entity: "EmployeeLoan",
      entityId: loan.id,
      details: `منح سلفة للموظف ${employee.name} — مبلغ: ${amount} — وصل صرف: ${voucherNumber}`,
    });
    return NextResponse.json({ loan }, { status: 201 });
  } catch (err) {
    return handleApiError(err);
  }
}
