/**
 * POST /api/client-portal/users — add a client user
 * GET  /api/client-portal/users?portalId=X — list client users
 */

import { NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { Prisma } from "@prisma/client";

export const dynamic = "force-dynamic";

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

async function authPortal(portalId: string, userId: string) {
  const portal = await prisma.clientPortal.findUnique({
    where: { id: portalId },
    include: { brand: { include: { organization: { include: { memberships: true } } } } },
  });
  if (!portal) return { error: "Portal not found" as const, status: 404 };
  if (!portal.brand.organization.memberships.some((m) => m.userId === userId)) {
    return { error: "Access denied" as const, status: 403 };
  }
  return { portal };
}

export async function POST(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const body = await req.json().catch(() => null) as {
    portalId?: string; email?: string; name?: string; role?: string;
    permissions?: Record<string, boolean>;
    /** Per-client page-visibility override. When present, fully
     *  replaces the portal's default portalConfig for this user. */
    pageOverrides?: object | null;
  } | null;
  if (!body?.portalId || !body?.email) return NextResponse.json({ error: "portalId and email required" }, { status: 400 });
  if (!EMAIL_RE.test(body.email)) return NextResponse.json({ error: "Invalid email" }, { status: 400 });

  const resolved = await authPortal(body.portalId, user.id);
  if ("error" in resolved) return NextResponse.json({ error: resolved.error }, { status: resolved.status });

  // pageOverrides semantics:
  //   null      → explicitly clear the override (use portal default)
  //   undefined → leave untouched
  //   object    → store as-is (empty object treated as clear)
  // Prisma requires Prisma.JsonNull sentinel to set a nullable Json
  // column to SQL NULL; a JS null doesn't typecheck against the
  // NullableJsonNullValueInput union.
  let pageOverridesCreate: Prisma.InputJsonValue | undefined;
  let pageOverridesUpdate: Prisma.InputJsonValue | typeof Prisma.JsonNull | undefined;
  if (body.pageOverrides === null) {
    pageOverridesUpdate = Prisma.JsonNull;
  } else if (body.pageOverrides && typeof body.pageOverrides === "object" && Object.keys(body.pageOverrides).length > 0) {
    pageOverridesCreate = body.pageOverrides as Prisma.InputJsonValue;
    pageOverridesUpdate = body.pageOverrides as Prisma.InputJsonValue;
  }

  const clientUser = await prisma.clientUser.upsert({
    where: { portalId_email: { portalId: body.portalId, email: body.email.toLowerCase() } },
    create: {
      portalId: body.portalId,
      email: body.email.toLowerCase(),
      name: body.name || null,
      role: body.role === "admin" ? "admin" : body.role === "editor" ? "editor" : "viewer",
      permissions: body.permissions ? (body.permissions as object) : undefined,
      ...(pageOverridesCreate !== undefined ? { pageOverrides: pageOverridesCreate } : {}),
      status: "pending",
      invitedAt: new Date(),
    },
    update: {
      name: body.name || undefined,
      role: body.role === "admin" ? "admin" : body.role === "editor" ? "editor" : undefined,
      permissions: body.permissions ? (body.permissions as object) : undefined,
      ...(pageOverridesUpdate !== undefined ? { pageOverrides: pageOverridesUpdate } : {}),
      isActive: true,
    },
  });

  return NextResponse.json({ clientUser });
}

export async function GET(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const portalId = new URL(req.url).searchParams.get("portalId");
  if (!portalId) return NextResponse.json({ error: "portalId required" }, { status: 400 });

  const resolved = await authPortal(portalId, user.id);
  if ("error" in resolved) return NextResponse.json({ error: resolved.error }, { status: resolved.status });

  const users = await prisma.clientUser.findMany({
    where: { portalId },
    orderBy: { createdAt: "desc" },
    select: {
      id: true, email: true, name: true, role: true,
      lastLoginAt: true, isActive: true, createdAt: true,
      status: true, invitedAt: true, pageOverrides: true,
    },
  });

  return NextResponse.json({ users });
}
