import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireRole } from "@/lib/auth";

/** Voucher register: filterable income / expense entries. */
export async function GET(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const url = new URL(req.url);
  const type = url.searchParams.get("type");
  const headId = url.searchParams.get("headId");
  const from = url.searchParams.get("from");
  const to = url.searchParams.get("to");

  const entries = await prisma.accountEntry.findMany({
    where: {
      institutionId: session.institutionId,
      ...(type === "INCOME" || type === "EXPENSE" ? { type } : {}),
      ...(headId ? { headId: Number(headId) } : {}),
      ...(from || to
        ? {
            date: {
              ...(from ? { gte: new Date(`${from}T00:00:00`) } : {}),
              ...(to ? { lte: new Date(`${to}T23:59:59`) } : {}),
            },
          }
        : {}),
    },
    orderBy: [{ date: "desc" }, { id: "desc" }],
    include: {
      head: { select: { name: true, nameBn: true, type: true } },
      createdBy: { select: { name: true } },
    },
  });

  const totals = entries.reduce(
    (acc, e) => {
      if (e.type === "INCOME") acc.income += Number(e.amount);
      else acc.expense += Number(e.amount);
      return acc;
    },
    { income: 0, expense: 0 },
  );

  return NextResponse.json({ entries, totals, count: entries.length });
}

/** Create a voucher — voucherNo is generated per type (INC-/EXP- + count). */
export async function POST(req: Request) {
  const session = await requireRole("INSTITUTION_ADMIN");
  if (!session || !session.institutionId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const headId = Number(body.headId);
    const amount = Number(body.amount);
    const date = String(body.date ?? "");
    const party = String(body.party ?? "").trim() || null;
    const note = String(body.note ?? "").trim() || null;
    const method = String(body.method ?? "CASH");

    if (!headId || !Number.isFinite(amount) || amount <= 0 || !/^\d{4}-\d{2}-\d{2}$/.test(date)) {
      return NextResponse.json({ error: "Missing or invalid fields" }, { status: 400 });
    }

    const head = await prisma.accountHead.findFirst({
      where: { id: headId, institutionId: session.institutionId },
    });
    if (!head) return NextResponse.json({ error: "Head not found" }, { status: 404 });

    const entry = await prisma.$transaction(async (tx) => {
      const count = await tx.accountEntry.count({
        where: { institutionId: session.institutionId!, type: head.type },
      });
      const prefix = head.type === "INCOME" ? "INC" : "EXP";
      const voucherNo = `${prefix}-${String(count + 1).padStart(6, "0")}`;
      return tx.accountEntry.create({
        data: {
          institutionId: session.institutionId!,
          headId,
          type: head.type,
          voucherNo,
          amount,
          date: new Date(`${date}T00:00:00`),
          method: method as never,
          party,
          note,
          createdById: session.userId,
        },
        include: {
          head: { select: { name: true, nameBn: true, type: true } },
          createdBy: { select: { name: true } },
        },
      });
    });
    return NextResponse.json({ entry });
  } catch {
    return NextResponse.json({ error: "Could not create voucher" }, { status: 500 });
  }
}
