import { NextResponse } from "next/server";
import { DepartmentKey, ProjectCalendarVisibility } from "@prisma/client";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { canAccessProjects, canManageProjects, mapProjectCalendarEvent } from "@/lib/projects/persistence";

type UpdateEventBody = {
  title?: string;
  notes?: string;
  startAt?: string;
  endAt?: string;
  visibility?: string;
};

function parseIsoDate(value: string | undefined): Date | null {
  if (!value) {
    return null;
  }

  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return null;
  }

  return parsed;
}

function parseVisibility(value: string | undefined): ProjectCalendarVisibility | null {
  if (value === undefined) {
    return null;
  }

  return value === "team" ? ProjectCalendarVisibility.team : ProjectCalendarVisibility.personal;
}

export async function PATCH(request: Request, context: { params: { id: string } }) {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  if (!canAccessProjects(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const event = await prisma.projectCalendarEvent.findFirst({
    where: {
      id: context.params.id,
      department: DepartmentKey.proyectos,
    },
  });

  if (!event) {
    return NextResponse.json({ error: "Event not found." }, { status: 404 });
  }

  const canManage = canManageProjects(session.user.role, session.user.department);
  const canEditOwn = event.ownerUserId === session.user.id;

  if (!canManage && !canEditOwn) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const body = (await request.json()) as UpdateEventBody;
  const visibility = parseVisibility(body.visibility);

  if (visibility === ProjectCalendarVisibility.team && !canManage) {
    return NextResponse.json({ error: "Only owners or leaders can set team visibility." }, { status: 403 });
  }

  const parsedStartAt = body.startAt !== undefined ? parseIsoDate(body.startAt) : undefined;
  const parsedEndAt = body.endAt !== undefined ? parseIsoDate(body.endAt) : undefined;

  if (body.startAt !== undefined && !parsedStartAt) {
    return NextResponse.json({ error: "Invalid startAt." }, { status: 400 });
  }

  if (body.endAt !== undefined && !parsedEndAt) {
    return NextResponse.json({ error: "Invalid endAt." }, { status: 400 });
  }

  const startAt = parsedStartAt ?? undefined;
  const endAt = parsedEndAt ?? undefined;

  const nextStart = startAt ?? event.startAt;
  const nextEnd = endAt ?? event.endAt;

  if (nextEnd.getTime() <= nextStart.getTime()) {
    return NextResponse.json({ error: "endAt must be later than startAt." }, { status: 400 });
  }

  const updated = await prisma.projectCalendarEvent.update({
    where: { id: event.id },
    data: {
      title: body.title?.trim() || undefined,
      notes: body.notes?.trim() || (body.notes !== undefined ? null : undefined),
      startAt,
      endAt,
      visibility: visibility ?? undefined,
    },
  });

  return NextResponse.json({
    ok: true,
    event: mapProjectCalendarEvent(updated),
  });
}

export async function DELETE(_request: Request, context: { params: { id: string } }) {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  if (!canAccessProjects(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const event = await prisma.projectCalendarEvent.findFirst({
    where: {
      id: context.params.id,
      department: DepartmentKey.proyectos,
    },
  });

  if (!event) {
    return NextResponse.json({ error: "Event not found." }, { status: 404 });
  }

  const canManage = canManageProjects(session.user.role, session.user.department);
  const canEditOwn = event.ownerUserId === session.user.id;

  if (!canManage && !canEditOwn) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  if (event.meetingId && !canManage) {
    return NextResponse.json({ error: "Meeting events can only be removed by owners or leaders." }, { status: 403 });
  }

  await prisma.projectCalendarEvent.delete({
    where: { id: event.id },
  });

  return NextResponse.json({ ok: true });
}
