import { NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { DepartmentKey } from "@prisma/client";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { mapMeeting, parseStringArray } from "@/lib/marketing/meetings";
import { canManageMarketing } from "@/lib/marketing/persistence";

type UpdateMeetingBody = {
  action?: "schedule" | "complete" | "cancel";
  scheduledFor?: string;
  commitments?: Array<{
    title?: string;
    description?: string;
    ownerName?: string;
    dueDate?: string;
  }>;
  participantNames?: unknown;
};

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;
}

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 (!canManageMarketing(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Only owners or leaders can update meetings." }, { status: 403 });
  }

  const meetingId = context.params.id;
  const existing = await prisma.marketingMeeting.findFirst({
    where: {
      id: meetingId,
      department: DepartmentKey.marketing,
    },
    select: { id: true },
  });

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

  const body = (await request.json()) as UpdateMeetingBody;
  const action = body.action;

  if (!action || (action !== "schedule" && action !== "complete" && action !== "cancel")) {
    return NextResponse.json({ error: "Invalid action." }, { status: 400 });
  }

  if (action === "schedule") {
    const scheduledFor = parseIsoDate(body.scheduledFor);
    if (!scheduledFor) {
      return NextResponse.json({ error: "Invalid scheduledFor." }, { status: 400 });
    }

    const participantNames = body.participantNames ? parseStringArray(body.participantNames) : undefined;

    const meeting = await prisma.marketingMeeting.update({
      where: { id: meetingId },
      data: {
        status: "scheduled",
        scheduledFor,
        participantNames: participantNames && participantNames.length > 0 ? participantNames : undefined,
      },
      include: {
        commitments: {
          orderBy: { createdAt: "asc" },
        },
      },
    });

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

  if (action === "cancel") {
    const meeting = await prisma.marketingMeeting.update({
      where: { id: meetingId },
      data: {
        status: "cancelled",
      },
      include: {
        commitments: {
          orderBy: { createdAt: "asc" },
        },
      },
    });

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

  const commitmentsInput = (body.commitments ?? [])
    .map((item) => ({
      title: item.title?.trim() ?? "",
      description: item.description?.trim() || null,
      ownerName: item.ownerName?.trim() || null,
      dueDate: parseIsoDate(item.dueDate),
    }))
    .filter((item) => item.title.length > 0);

  if (commitmentsInput.length === 0) {
    return NextResponse.json({ error: "At least one commitment is required." }, { status: 400 });
  }

  const meeting = await prisma.$transaction(async (tx) => {
    await tx.marketingCommitment.createMany({
      data: commitmentsInput.map((item) => ({
        meetingId,
        title: item.title,
        description: item.description,
        ownerName: item.ownerName,
        dueDate: item.dueDate,
      })),
    });

    return tx.marketingMeeting.update({
      where: { id: meetingId },
      data: {
        status: "completed",
        completedAt: new Date(),
      },
      include: {
        commitments: {
          orderBy: { createdAt: "asc" },
        },
      },
    });
  });

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