import { NextRequest } from "next/server";
import { z } from "zod";
import { NextResponse } from "next/server";
import { getPrisma } from "../../../../lib/db";
import { getSession } from "../../../../lib/auth/session";
import { ok, fail } from "../../../../lib/http";

export const runtime = "nodejs";

const QuerySchema = z.object({
  page: z.string().default("1").transform(Number),
  search: z.string().optional(),
});

const UpdateUserSchema = z.object({
  role: z.enum(["USER", "ADMIN"]).optional(),
  isActive: z.boolean().optional(),
});

export async function GET(req: NextRequest) {
  const session = await getSession();
  if (!session || session.role !== "ADMIN") {
    return fail(new Error("Unauthorized"), { status: 401 });
  }

  const prisma = await getPrisma();
  if (!prisma) return fail(new Error("Database not configured"), { status: 503 });

  const parsed = QuerySchema.safeParse(
    Object.fromEntries(new URL(req.url).searchParams)
  );
  if (!parsed.success) return fail(new Error("Invalid query parameters"));

  const appSetup = await prisma.appSetup.findUnique({ where: { id: 1 } });
  const pageSize = appSetup?.paginationItemsPerPage || 10;
  const page = Math.max(1, parsed.data.page);
  const skip = (page - 1) * pageSize;

  const searchFilter = parsed.data.search
    ? {
        OR: [
          { email: { contains: parsed.data.search, mode: "insensitive" as const } },
          { firstName: { contains: parsed.data.search, mode: "insensitive" as const } },
          { lastName: { contains: parsed.data.search, mode: "insensitive" as const } },
        ],
      }
    : undefined;

  const [users, total] = await Promise.all([
    prisma.user.findMany({
      where: searchFilter,
      select: {
        id: true,
        email: true,
        firstName: true,
        lastName: true,
        role: true,
        isActive: true,
        emailVerified: true,
        createdAt: true,
        gender: true,
        dob: true,
        address: true,
        image: true,
      },
      orderBy: { createdAt: "desc" },
      skip,
      take: pageSize,
    }),
    prisma.user.count({ where: searchFilter }),
  ]);

  // Fetch webinars for each user
  const usersWithWebinars = await Promise.all(
    users.map(async (user) => {
      const registrations = await prisma.webinarRegistration.findMany({
        where: { userId: user.id, status: { not: "CANCELLED" } },
      });
      return {
        ...user,
        _count: {
          webinarRegistrations: registrations.length,
        },
        registeredWebinars: await prisma.webinarRegistration.findMany({
          where: { userId: user.id, status: { not: "CANCELLED" } },
          select: {
            id: true,
            status: true,
            webinar: {
              select: {
                id: true,
                title: true,
                startAt: true,
              },
            },
          },
          orderBy: { createdAt: "desc" },
          take: 5,
        }),
      };
    })
  );

  return ok({
    users: usersWithWebinars,
    pagination: {
      page,
      pageSize,
      total,
      pages: Math.ceil(total / pageSize),
      hasMore: page < Math.ceil(total / pageSize),
    },
  });
}

export async function PATCH(req: NextRequest) {
  const session = await getSession();
  if (!session || session.role !== "ADMIN") {
    return fail(new Error("Unauthorized"), { status: 401 });
  }

  const prisma = await getPrisma();
  if (!prisma) return fail(new Error("Database not configured"), { status: 503 });

  const body = await req.json().catch(() => ({}));
  const { userId, ...updateData } = body;

  if (!userId) return fail(new Error("userId is required"));

  const parsed = UpdateUserSchema.safeParse(updateData);
  if (!parsed.success) return fail(new Error("Invalid update data"));

  // Prevent disabling the current admin
  if (session.sub === userId && parsed.data.isActive === false) {
    return fail(new Error("Cannot disable your own account"), { status: 400 });
  }

  // Prevent removing admin role from self
  if (session.sub === userId && parsed.data.role && parsed.data.role !== "ADMIN") {
    return fail(new Error("Cannot change your own role"), { status: 400 });
  }

  const user = await prisma.user.update({
    where: { id: userId },
    data: {
      ...(parsed.data.role && { role: parsed.data.role }),
      ...(parsed.data.isActive !== undefined && { isActive: parsed.data.isActive }),
    },
    select: {
      id: true,
      email: true,
      firstName: true,
      lastName: true,
      role: true,
      isActive: true,
    },
  });

  return ok({
    message:
      parsed.data.isActive === false
        ? "User blocked successfully"
        : "User updated successfully",
    user,
  });
}
