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 CreateEventBody = {
  title?: string;
  notes?: string;
  startAt?: string;
  endAt?: string;
  visibility?: string;
};

function parseIsoDate(value: string | null): 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 {
  return value === "team" ? ProjectCalendarVisibility.team : ProjectCalendarVisibility.personal;
}

export async function GET(request: Request) {
  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 url = new URL(request.url);
  const start = parseIsoDate(url.searchParams.get("start"));
  const end = parseIsoDate(url.searchParams.get("end"));

  const events = await prisma.projectCalendarEvent.findMany({
    where: {
      department: DepartmentKey.proyectos,
      ...(start || end
        ? {
            AND: [
              start
                ? {
                    endAt: {
                      gte: start,
                    },
                  }
                : {},
              end
                ? {
                    startAt: {
                      lte: end,
                    },
                  }
                : {},
            ],
          }
        : {}),
      OR: [{ ownerUserId: session.user.id }, { visibility: ProjectCalendarVisibility.team }],
    },
    orderBy: [{ startAt: "asc" }, { createdAt: "asc" }],
    take: 400,
  });

  return NextResponse.json({
    ok: true,
    events: events.map(mapProjectCalendarEvent),
  });
}

export async function POST(request: Request) {
  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 body = (await request.json()) as CreateEventBody;
  const title = body.title?.trim() ?? "";
  const notes = body.notes?.trim() || null;
  const startAt = parseIsoDate(body.startAt ?? null);
  const endAt = parseIsoDate(body.endAt ?? null);
  const visibility = parseVisibility(body.visibility);

  if (!title || !startAt || !endAt) {
    return NextResponse.json({ error: "title, startAt and endAt are required." }, { status: 400 });
  }

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

  const canManage = canManageProjects(session.user.role, session.user.department);
  if (visibility === ProjectCalendarVisibility.team && !canManage) {
    return NextResponse.json({ error: "Only owners or leaders can create team events." }, { status: 403 });
  }

  const event = await prisma.projectCalendarEvent.create({
    data: {
      department: DepartmentKey.proyectos,
      ownerUserId: session.user.id,
      title,
      notes,
      startAt,
      endAt,
      visibility,
    },
  });

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