import ical from "ical-generator";
import { NextResponse } from "next/server";
import { prisma } from "./prisma";

const DEFAULT_APP_NAME = "Vereinskalender";

const toFilename = (value: string) =>
  value
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/(^-|-$)/g, "") || "kalender";

export async function getIcalResponse(request: Request, token: string) {
  const view = await prisma.userView.findUnique({
    where: { token },
    include: {
      items: { include: { event: true } },
      categories: true,
      exclusions: true,
      user: true
    }
  });

  if (!view) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }

  const appNameSetting = await prisma.setting.findUnique({
    where: { key: "app_name" }
  });
  const appName = appNameSetting?.value || DEFAULT_APP_NAME;
  const url = new URL(request.url);
  const pastDaysParam = Number(url.searchParams.get("pastDays"));
  const rawPastDays =
    Number.isFinite(pastDaysParam) && pastDaysParam >= 0
      ? pastDaysParam
      : Number.isFinite(view.icalPastDays) && view.icalPastDays >= 0
      ? view.icalPastDays
      : 14;
  const pastDays = Math.min(365, Math.floor(rawPastDays));
  const cutoff = new Date(Date.now() - pastDays * 24 * 60 * 60 * 1000);

  const calendar = ical({
    name: appName,
    timezone: "Europe/Berlin"
  });

  const excludedIds = new Set(view.exclusions.map((item) => item.eventId));
  const explicitEvents = view.items
    .map((item) => item.event)
    .filter((event) => event.status === "APPROVED");

  const categoryIds = view.categories.map((item) => item.categoryId);
  const categoryEvents =
    categoryIds.length > 0
      ? await prisma.event.findMany({
          where: { categoryId: { in: categoryIds }, status: "APPROVED" }
        })
      : [];

  const combined = [...explicitEvents, ...categoryEvents].filter(
    (event, index, all) =>
      all.findIndex((item) => item.id === event.id) === index &&
      !excludedIds.has(event.id) &&
      event.startAt >= cutoff
  );

  combined.forEach((event) => {
    const start = event.startAt;
    const end =
      event.endAt || new Date(event.startAt.getTime() + 3 * 60 * 60 * 1000);
    calendar.createEvent({
      id: event.id,
      summary: event.title,
      description: event.description || undefined,
      location: event.location || undefined,
      start,
      end
    });
  });

  const filename = `${toFilename(appName)}.ical`;

  return new NextResponse(calendar.toString(), {
    headers: {
      "Content-Type": "text/calendar; charset=utf-8",
      "Content-Disposition": `attachment; filename="${filename}"`
    }
  });
}
