import { NextResponse } from "next/server";
import { DepartmentKey, MarketingTaskStatus } from "@prisma/client";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { canAccessMarketing, canManageMarketing, mapMarketingTask } from "@/lib/marketing/persistence";

type UpdateTaskBody = {
  status?: string;
  evidenceLinks?: string[];
};

const ALLOWED_STATUS = new Set<MarketingTaskStatus>([
  MarketingTaskStatus.todo,
  MarketingTaskStatus.in_progress,
  MarketingTaskStatus.blocked,
  MarketingTaskStatus.done,
]);

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 (!canAccessMarketing(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const taskId = context.params.id;
  const task = await prisma.marketingTask.findFirst({
    where: {
      id: taskId,
      initiative: { department: DepartmentKey.marketing },
    },
    include: {
      evidenceLinks: {
        orderBy: { createdAt: "asc" },
      },
    },
  });

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

  const canManage = canManageMarketing(session.user.role, session.user.department);
  const isOwnTaskEmployee =
    session.user.role === "employee" &&
    session.user.department === DepartmentKey.marketing &&
    task.assigneeId === session.user.id;

  if (!canManage && !isOwnTaskEmployee) {
    return NextResponse.json({ error: "You can only edit your own assigned tasks." }, { status: 403 });
  }

  const body = (await request.json()) as UpdateTaskBody;
  const status = body.status;
  const evidenceLinks = body.evidenceLinks ?? [];

  if (!status && body.evidenceLinks === undefined) {
    return NextResponse.json({ error: "Nothing to update." }, { status: 400 });
  }

  if (status && !ALLOWED_STATUS.has(status as MarketingTaskStatus)) {
    return NextResponse.json({ error: "Invalid task status." }, { status: 400 });
  }

  const cleanEvidenceLinks = Array.from(
    new Set(
      evidenceLinks
        .map((value) => value.trim())
        .filter((value) => value.length > 0)
    )
  );

  const updated = await prisma.$transaction(async (tx) => {
    await tx.marketingTask.update({
      where: { id: taskId },
      data: {
        status: status as MarketingTaskStatus | undefined,
      },
    });

    if (body.evidenceLinks !== undefined) {
      await tx.marketingTaskEvidence.deleteMany({
        where: { taskId },
      });

      if (cleanEvidenceLinks.length > 0) {
        await tx.marketingTaskEvidence.createMany({
          data: cleanEvidenceLinks.map((url) => ({
            taskId,
            url,
            createdById: session.user.id,
          })),
        });
      }
    }

    return tx.marketingTask.findUniqueOrThrow({
      where: { id: taskId },
      include: {
        evidenceLinks: {
          orderBy: { createdAt: "asc" },
        },
      },
    });
  });

  return NextResponse.json({
    ok: true,
    task: mapMarketingTask(updated),
  });
}
