import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getSessionClientId } from "@/lib/auth";
import { isAdminSession, hasPermission } from "@/lib/adminAuth";
import { connectDB } from "@/lib/db";
import { Client } from "@/models/Client";
import { VacationRequest } from "@/models/VacationRequest";
import { remainingVacationDays } from "@/lib/vacationBalance";
import { requestVacationAction } from "@/lib/actions/vacation";
import { corsHeaders, corsPreflight } from "@/lib/teamApiCors";

export async function OPTIONS(request: NextRequest) {
  return corsPreflight(request);
}

// Selbstbedienung (eigenes Kontingent+Anträge) IMMER geliefert, dazu bei
// "hr"-Berechtigung zusätzlich die team-weite Warteschlange offener Anträge
// (sonst bräuchte die App zwei Requests für Zeiterfassungs-Selbstbedienung
// und Urlaubsanträge-Eingang, wie die zwei getrennten Web-Seiten es tun).
export async function GET(request: NextRequest) {
  const headers = corsHeaders(request);
  const clientId = await getSessionClientId();
  if (!clientId || !(await isAdminSession())) {
    return NextResponse.json({ error: "Nicht angemeldet." }, { status: 401, headers });
  }

  await connectDB();
  const now = new Date();
  const [ownClient, ownRequests, canApprove] = await Promise.all([
    Client.findById(clientId).select("vacationDaysPerYear").lean(),
    VacationRequest.find({ clientId }).sort({ startDate: -1 }).lean(),
    hasPermission("hr"),
  ]);
  const ownBalance = remainingVacationDays(
    ownClient?.vacationDaysPerYear ?? null,
    ownRequests.filter((r) => new Date(r.startDate).getFullYear() === now.getFullYear())
  );

  let pending: unknown[] = [];
  if (canApprove) {
    const pendingRequests = await VacationRequest.find({ status: "requested" }).sort({ createdAt: 1 }).lean();
    const clientIds = [...new Set(pendingRequests.map((r) => String(r.clientId)))];
    const [staff, activeForThoseClients] = await Promise.all([
      Client.find({ _id: { $in: clientIds } }).select("name vacationDaysPerYear").lean(),
      VacationRequest.find({ clientId: { $in: clientIds }, status: { $in: ["requested", "approved"] } })
        .select("clientId status workDaysCount startDate")
        .lean(),
    ]);
    const staffById = new Map(staff.map((c) => [String(c._id), c]));
    pending = pendingRequests.map((r) => {
      const year = new Date(r.startDate).getFullYear();
      const client = staffById.get(String(r.clientId));
      const sameEmployeeYear = activeForThoseClients.filter(
        (x) => String(x.clientId) === String(r.clientId) && new Date(x.startDate).getFullYear() === year
      );
      const allowance = client?.vacationDaysPerYear ?? null;
      const balance = remainingVacationDays(allowance, sameEmployeeYear);
      return {
        id: String(r._id),
        employeeName: client?.name || "—",
        startDate: new Date(r.startDate).toISOString(),
        endDate: new Date(r.endDate).toISOString(),
        workDaysCount: r.workDaysCount,
        note: r.note || "",
        allowance,
        approvedDays: balance.approvedDays,
        pendingDays: balance.pendingDays,
        wouldExceed: allowance !== null && balance.approvedDays + balance.pendingDays > allowance,
      };
    });
  }

  return NextResponse.json(
    {
      allowance: ownClient?.vacationDaysPerYear ?? null,
      approvedDays: ownBalance.approvedDays,
      pendingDays: ownBalance.pendingDays,
      requests: ownRequests.map((r) => ({
        id: String(r._id),
        startDate: new Date(r.startDate).toISOString(),
        endDate: new Date(r.endDate).toISOString(),
        workDaysCount: r.workDaysCount,
        status: r.status,
        note: r.note || "",
      })),
      canApprove,
      pending,
    },
    { headers }
  );
}

export async function POST(request: NextRequest) {
  const headers = corsHeaders(request);
  const clientId = await getSessionClientId();
  if (!clientId || !(await isAdminSession())) {
    return NextResponse.json({ error: "Nicht angemeldet." }, { status: 401, headers });
  }
  const body = await request.json().catch(() => null);
  const formData = new FormData();
  formData.set("startDate", typeof body?.startDate === "string" ? body.startDate : "");
  formData.set("endDate", typeof body?.endDate === "string" ? body.endDate : "");
  formData.set("note", typeof body?.note === "string" ? body.note : "");
  const result = await requestVacationAction(formData);
  if (result?.error) return NextResponse.json({ error: result.error }, { status: 400, headers });
  return NextResponse.json({ ok: true, warning: result?.warning ?? null }, { headers });
}
