import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { requirePageRole, resolveSchoolId, ApiError } from "@/lib/auth";
import { handleApiError } from "@/lib/api-helpers";

const MONTH_RE = /^\d{4}-\d{2}$/;

const MONTH_NAMES_AR = [
  "كانون الثاني", "شباط", "آذار", "نيسان", "أيار", "حزيران",
  "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول",
];

/** حدود شهر معين */
function monthRange(month: string): { start: Date; end: Date } {
  const [y, m] = month.split("-").map(Number);
  const start = new Date(y, m - 1, 1, 0, 0, 0, 0);
  const end = new Date(y, m, 1, 0, 0, 0, 0); // بداية الشهر التالي = نهاية هذا الشهر
  return { start, end };
}

/**
 * تقرير الميزانية / حركة الصندوق الشهرية (v8.1):
 * يقارن تلقائياً بين بنود الإيرادات المقبوضة وبنود المصروفات المدفوعة في الشهر،
 * ويحسب صافي الرصيد المدور للشهر التالي (صندوق البداية للشهر الجديد).
 * الرصيد = الرصيد الافتتاحي (الإعدادات) + مجمل الإيرادات التراكمي - مجمل المصروفات التراكمي حتى نهاية الشهر.
 */
export async function GET(req: NextRequest) {
  try {
    const user = await requirePageRole("reports", "ADMIN", "ACCOUNTANT");
    const schoolId = await resolveSchoolId(user, req.nextUrl.searchParams.get("schoolId"));
    const monthParam = req.nextUrl.searchParams.get("month")?.trim() ?? "";
    if (!MONTH_RE.test(monthParam)) throw new ApiError("الشهر مطلوب بصيغة YYYY-MM", 400);
    const { start, end } = monthRange(monthParam);
    const [year, monthNum] = monthParam.split("-").map(Number);

    const settings = await db.schoolSettings.findUnique({ where: { id: "main" } });
    const openingBase = settings?.openingBalance ?? 0;

    // ==== إيرادات الشهر ====
    const [studentIncomeAgg, otherByKind, expenseByKind, bonusesAgg] = await Promise.all([
      db.payment.aggregate({
        where: { schoolId, paidAt: { gte: start, lt: end } },
        _sum: { amount: true },
      }),
      db.otherIncome.groupBy({
        by: ["kind"],
        where: { schoolId, receivedAt: { gte: start, lt: end } },
        _sum: { amount: true },
      }),
      db.expense.groupBy({
        by: ["kind"],
        where: { schoolId, spentAt: { gte: start, lt: end } },
        _sum: { amount: true },
      }),
      db.employeePayment.aggregate({
        where: { employee: { schoolId }, paidAt: { gte: start, lt: end } },
        _sum: { bonuses: true, deductions: true },
      }),
    ]);

    const otherKindSum = (k: string) => otherByKind.find((r) => r.kind === k)?._sum.amount ?? 0;
    const expenseKindSum = (k: string) => expenseByKind.find((r) => r.kind === k)?._sum.amount ?? 0;

    const studentIncome = studentIncomeAgg._sum.amount ?? 0;
    const staffLoanRepayIncome = otherKindSum("STAFF_LOAN_REPAY");
    const activityLoanRepayIncome = otherKindSum("ACTIVITY_LOAN_REPAY");
    const otherSchoolIncome = otherKindSum("OTHER_SCHOOL");
    const transferIncome = otherKindSum("TRANSFER");
    const otherMiscIncome = otherKindSum("OTHER");
    const otherIncomeTotal = staffLoanRepayIncome + activityLoanRepayIncome + otherSchoolIncome + transferIncome + otherMiscIncome;
    const totalIncome = studentIncome + otherIncomeTotal;

    // ==== مصروفات الشهر ====
    const salaryExpense = expenseKindSum("SALARY");
    const lectureWageExpense = expenseKindSum("LECTURE_WAGE");
    const salaryAndLecture = salaryExpense + lectureWageExpense;
    const bonuses = bonusesAgg._sum.bonuses ?? 0; // تفصيل فرعي (مضمّن في الرواتب)
    const deductions = bonusesAgg._sum.deductions ?? 0; // تفصيل فرعي
    const staffLoanGiven = expenseKindSum("STAFF_LOAN_GIVEN");
    const activityLoanGiven = expenseKindSum("ACTIVITY_LOAN_GIVEN");
    const maintenance = expenseKindSum("MAINTENANCE");
    const operational = expenseKindSum("OPERATIONAL");
    const otherSchoolExpenses = expenseKindSum("OTHER");
    const loans = expenseKindSum("LOAN");
    const transfers = expenseKindSum("TRANSFER");
    const companyInvoices = expenseKindSum("COMPANY_INVOICE");
    const totalExpenses = salaryAndLecture + staffLoanGiven + activityLoanGiven + maintenance + operational + otherSchoolExpenses + loans + transfers + companyInvoices;

    const net = totalIncome - totalExpenses;

    // ==== الأرصدة التراكمية (حتى نهاية الشهر المحدد) ====
    const [cumIncomePayments, cumIncomeOther, cumExpenses] = await Promise.all([
      db.payment.aggregate({
        where: { schoolId, paidAt: { lt: end } },
        _sum: { amount: true },
      }),
      db.otherIncome.aggregate({
        where: { schoolId, receivedAt: { lt: end } },
        _sum: { amount: true },
      }),
      db.expense.aggregate({
        where: { schoolId, spentAt: { lt: end } },
        _sum: { amount: true },
      }),
    ]);
    const cumulativeIncome = (cumIncomePayments._sum.amount ?? 0) + (cumIncomeOther._sum.amount ?? 0);
    const cumulativeExpenses = cumExpenses._sum.amount ?? 0;
    const closingBalance = openingBase + cumulativeIncome - cumulativeExpenses; // المدور للشهر التالي
    const prevEnd = new Date(start.getTime());
    const openingCarried = closingBalance - net; // رصيد بداية الشهر = الختامي - حركة هذا الشهر
    void prevEnd;

    return NextResponse.json({
      month: monthParam,
      monthLabel: `${MONTH_NAMES_AR[monthNum - 1]} ${year}`,
      currency: settings?.currency ?? "د.ع",
      openingBalance: {
        settingsBase: openingBase,
        carriedFromPrevious: openingCarried,
      },
      income: {
        total: totalIncome,
        students: studentIncome,
        staffLoanRepay: staffLoanRepayIncome,
        activityLoanRepay: activityLoanRepayIncome,
        otherSchool: otherSchoolIncome,
        transfer: transferIncome,
        otherMisc: otherMiscIncome,
        otherTotal: otherIncomeTotal,
      },
      expenses: {
        total: totalExpenses,
        salaryAndLecture,
        salaryOnly: salaryExpense,
        lectureWages: lectureWageExpense,
        bonuses, // تفصيل فرعي مضمّن في الرواتب
        deductions, // تفصيل فرعي
        staffLoanGiven,
        activityLoanGiven,
        maintenance,
        operational,
        otherSchoolExpenses,
        loans,
        transfers,
        companyInvoices,
      },
      net,
      closingBalance, // صافي الرصيد المدور للشهر التالي
    });
  } catch (err) {
    return handleApiError(err);
  }
}
