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 { TimeEntry } from "@/models/TimeEntry";
import { Client } from "@/models/Client";
import { clockInAction, clockOutAction } from "@/lib/actions/timeEntries";
import { computeComplianceWarnings, type ComplianceWarning } from "@/lib/workingTimeCompliance";
import { corsHeaders, corsPreflight } from "@/lib/teamApiCors";

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

function startOfDay(d: Date): Date {
  return new Date(d.getFullYear(), d.getMonth(), d.getDate());
}
function startOfWeek(d: Date): Date {
  const day = d.getDay();
  const diff = (day + 6) % 7;
  return startOfDay(new Date(d.getTime() - diff * 86_400_000));
}
function sumDuration(entries: { clockIn: Date; clockOut: Date | null }[], since: Date): number {
  const now = Date.now();
  return entries.reduce((sum, e) => {
    const start = Math.max(new Date(e.clockIn).getTime(), since.getTime());
    const end = e.clockOut ? new Date(e.clockOut).getTime() : now;
    return sum + Math.max(0, end - start);
  }, 0);
}

// Zeiterfassung fürs Team-API/App (25.09.2026, Personalsystem-Parität) -
// selbe Datenzusammenstellung wie admin/zeiterfassung/page.tsx, in einem
// einzigen GET statt mehrerer Rundreisen (eigener Status + Team-Ansicht für
// hr in einer Antwort, wie die Web-Seite es auch in einem Seitenaufruf tut).
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 todayStart = startOfDay(now);
  const weekStart = startOfWeek(now);
  const complianceWindowStart = new Date(now.getTime() - 30 * 86_400_000);
  const canViewAll = await hasPermission("hr");

  const [openEntry, weekEntries, recentEntries, ownComplianceEntries] = await Promise.all([
    TimeEntry.findOne({ clientId, clockOut: null }).lean(),
    TimeEntry.find({ clientId, clockIn: { $gte: weekStart } }).sort({ clockIn: -1 }).lean(),
    TimeEntry.find({ clientId }).sort({ clockIn: -1 }).limit(10).lean(),
    TimeEntry.find({ clientId, clockIn: { $gte: complianceWindowStart } }).lean(),
  ]);

  const todayMs = sumDuration(weekEntries, todayStart);
  const weekMs = sumDuration(weekEntries, weekStart);
  const ownWarnings = computeComplianceWarnings(ownComplianceEntries);

  let currentlyClockedIn: { name: string; since: string }[] = [];
  let teamWarnings: (ComplianceWarning & { staffName: string })[] = [];
  if (canViewAll) {
    const [openEntries, complianceEntries] = await Promise.all([
      TimeEntry.find({ clockOut: null }).sort({ clockIn: 1 }).lean(),
      TimeEntry.find({ clockIn: { $gte: complianceWindowStart } }).lean(),
    ]);
    const relevantIds = new Set([...openEntries, ...complianceEntries].map((e) => String(e.clientId)));
    const staffById = new Map(
      (await Client.find({ _id: { $in: [...relevantIds] } }).select("name").lean()).map((c) => [String(c._id), c.name])
    );
    currentlyClockedIn = openEntries.map((e) => ({ name: staffById.get(String(e.clientId)) || "—", since: new Date(e.clockIn).toISOString() }));

    const entriesByStaff = new Map<string, typeof complianceEntries>();
    for (const e of complianceEntries) {
      const key = String(e.clientId);
      if (!entriesByStaff.has(key)) entriesByStaff.set(key, []);
      entriesByStaff.get(key)!.push(e);
    }
    const collected: (ComplianceWarning & { staffName: string })[] = [];
    for (const [staffId, entries] of entriesByStaff) {
      const name = staffById.get(staffId) || "—";
      for (const w of computeComplianceWarnings(entries)) collected.push({ ...w, staffName: name });
    }
    collected.sort((a, b) => b.date.localeCompare(a.date));
    teamWarnings = collected;
  }

  return NextResponse.json(
    {
      clockInSince: openEntry ? new Date(openEntry.clockIn).toISOString() : null,
      todayMs,
      weekMs,
      ownWarnings,
      recentEntries: recentEntries.map((e) => ({
        id: String(e._id),
        clockIn: new Date(e.clockIn).toISOString(),
        clockOut: e.clockOut ? new Date(e.clockOut).toISOString() : null,
      })),
      canViewAll,
      currentlyClockedIn,
      teamWarnings,
    },
    { 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 result = body?.action === "clockOut" ? await clockOutAction() : await clockInAction();
  if (result.error) return NextResponse.json({ error: result.error }, { status: 400, headers });
  return NextResponse.json({ ok: true }, { headers });
}
