import { prisma } from "@/lib/prisma";
import { requireUser, withGuard, HttpError } from "@/lib/guard";
import { parseBody, ok } from "@/lib/http";
import { updateTaskSchema } from "@/lib/validators";
import { isManagerTier } from "@/lib/rbac";
import { getIsoWeek } from "@/lib/week";
import type { Prisma } from "@prisma/client";

export const runtime = "nodejs";

type Ctx = { params: Promise<{ id: string }> };

const INCLUDE = {
  user: { select: { id: true, name: true, position: true } },
  contributions: { include: { kpiIndicator: true } },
} satisfies Prisma.TaskInclude;

// PATCH /api/tasks/[id] — update a task. Staff may edit only their own; manager-tier may edit any.
export const PATCH = withGuard(async (req: Request, ctx: Ctx) => {
  const me = await requireUser();
  const { id } = await ctx.params;
  const data = await parseBody(req, updateTaskSchema);

  const existing = await prisma.task.findUnique({ where: { id } });
  if (!existing) throw new HttpError(404, "Task not found");

  const manager = isManagerTier(me.role);
  if (!manager && existing.userId !== me.id) {
    throw new HttpError(403, "You can only edit your own tasks");
  }

  const patch: Prisma.TaskUpdateInput = {};
  if (data.title !== undefined) patch.title = data.title;
  if (data.description !== undefined) patch.description = data.description ?? null;
  if (data.status !== undefined) patch.status = data.status;
  if (data.priority !== undefined) patch.priority = data.priority;
  if (data.channel !== undefined) patch.channel = data.channel ?? null;
  if (data.dueDate !== undefined) {
    const due = data.dueDate ? new Date(data.dueDate) : null;
    patch.dueDate = due;
    const { week, year } = getIsoWeek(due ?? new Date());
    patch.weekNumber = week;
    patch.weekYear = year;
  }
  // Reassignment is a manager-only intervention.
  if (data.userId !== undefined && data.userId !== existing.userId) {
    if (!manager) throw new HttpError(403, "Only managers can reassign tasks");
    patch.user = { connect: { id: data.userId } };
  }

  const task = await prisma.task.update({ where: { id }, data: patch, include: INCLUDE });
  return ok(task);
});

// DELETE /api/tasks/[id] — staff may delete own; manager-tier may delete any.
export const DELETE = withGuard(async (_req: Request, ctx: Ctx) => {
  const me = await requireUser();
  const { id } = await ctx.params;
  const existing = await prisma.task.findUnique({ where: { id } });
  if (!existing) throw new HttpError(404, "Task not found");
  if (!isManagerTier(me.role) && existing.userId !== me.id) {
    throw new HttpError(403, "You can only delete your own tasks");
  }
  await prisma.task.delete({ where: { id } });
  return ok({ ok: true });
});
