import { NextRequest, NextResponse } from "next/server";
import { connectDB } from "@/lib/db";
import { Calendar } from "@/models/Calendar";
import { CalendarEvent } from "@/models/CalendarEvent";
import { Order } from "@/models/Order";
import { Absence } from "@/models/Absence";
import { Convention } from "@/models/Convention";
import { Client } from "@/models/Client";
import { buildIcsFeed, type IcsEvent } from "@/lib/ics";
import { ABSENCE_TYPE_LABELS, type AbsenceType } from "@/lib/absenceConstants";

// Öffentlich per Geheim-Token abrufbar (kein Login) — genau das Modell, das
// Google/Apple/Outlook-Kalenderabos erwarten (regelmäßiger anonymer Abruf
// derselben URL). Token kompensiert das fehlende Login.
export async function GET(req: NextRequest, { params }: { params: Promise<{ calendarId: string }> }) {
  const { calendarId } = await params;
  const token = req.nextUrl.searchParams.get("token") || "";

  await connectDB();
  const cal = await Calendar.findById(calendarId).lean();
  if (!cal || !token || cal.icsToken !== token) {
    return new NextResponse("Not found", { status: 404 });
  }

  let events: IcsEvent[] = [];

  if (cal.kind === "orders") {
    const orders = await Order.find({ shootDate: { $ne: null }, rejected: false }).lean();
    const clientIds = [...new Set(orders.map((o) => String(o.clientId)))];
    const clients = await Client.find({ _id: { $in: clientIds } }).lean();
    const clientById = new Map(clients.map((c) => [String(c._id), c]));
    events = orders.map((o) => ({
      uid: `order-${o._id}`,
      title: `${o.characterOrConcept} · ${clientById.get(String(o.clientId))?.name ?? "Kunde"}`,
      description: o.eventLocation || "",
      start: new Date(o.shootDate as Date),
      end: o.shootEndDate ? new Date(o.shootEndDate) : null,
    }));
  } else if (cal.kind === "absences") {
    const absences = await Absence.find({}).lean();
    const clientIds = [...new Set(absences.map((a) => String(a.clientId)))];
    const clients = await Client.find({ _id: { $in: clientIds } }).lean();
    const clientById = new Map(clients.map((c) => [String(c._id), c]));
    events = absences.map((a) => ({
      uid: `absence-${a._id}`,
      title: `${clientById.get(String(a.clientId))?.name ?? "Team"} – ${ABSENCE_TYPE_LABELS[a.type as AbsenceType]}`,
      description: a.note || "",
      start: new Date(a.startDate),
      // ICS-DTEND ist bei ganztägigen Terminen exklusiv (RFC 5545) — ein Tag
      // nach dem letzten Abwesenheitstag, sonst fehlt der letzte Tag in
      // Kalender-Apps.
      end: new Date(new Date(a.endDate).getTime() + 24 * 60 * 60 * 1000),
      allDay: true,
    }));
  } else if (cal.kind === "conventions") {
    const conventions = await Convention.find({ "assignedStaffIds.0": { $exists: true } }).lean();
    const staffIds = [...new Set(conventions.flatMap((c) => (c.assignedStaffIds || []).map(String)))];
    const staff = staffIds.length ? await Client.find({ _id: { $in: staffIds } }).select("name").lean() : [];
    const nameById = new Map(staff.map((s) => [String(s._id), s.name]));
    events = conventions.map((c) => ({
      uid: `conv-${c._id}`,
      title: c.name,
      description: [
        c.location,
        (c.assignedStaffIds || [])
          .map((id) => nameById.get(String(id)))
          .filter(Boolean)
          .join(", "),
      ]
        .filter(Boolean)
        .join(" · "),
      start: new Date(c.startDate),
      end: new Date(new Date(c.endDate).getTime() + 24 * 60 * 60 * 1000),
      allDay: true,
    }));
  } else {
    const items = await CalendarEvent.find({ calendarId }).lean();
    events = items.map((e) => ({
      uid: `event-${e._id}`,
      title: e.title,
      description: e.description,
      start: new Date(e.start),
      end: e.end ? new Date(e.end) : null,
      allDay: e.allDay,
    }));
  }

  const ics = buildIcsFeed(cal.name, events);
  return new NextResponse(ics, {
    headers: {
      "Content-Type": "text/calendar; charset=utf-8",
      "Content-Disposition": `inline; filename="${cal.name.replace(/[^a-z0-9]/gi, "-")}.ics"`,
      "Cache-Control": "public, max-age=1800",
    },
  });
}
