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

import { serializeAuditTrail } from "@/features/audit-trail/lib/serialize-audit-trail";
import { requireApiAccess } from "@/lib/authorization";
import { prisma } from "@/lib/prisma";

function parseDateStart(value: string | null) {
  if (!value) return null;
  const date = new Date(`${value}T00:00:00.000Z`);
  return Number.isNaN(date.getTime()) ? null : date;
}

function parseDateEnd(value: string | null) {
  if (!value) return null;
  const date = new Date(`${value}T23:59:59.999Z`);
  return Number.isNaN(date.getTime()) ? null : date;
}

function buildWhere(searchParams: URLSearchParams): Prisma.AuditTrailWhereInput {
  const action = searchParams.get("action")?.trim();
  const userId = searchParams.get("user_id")?.trim();
  const dateFrom = parseDateStart(searchParams.get("date_from"));
  const dateTo = parseDateEnd(searchParams.get("date_to"));
  const search = searchParams.get("search")?.trim();

  const where: Prisma.AuditTrailWhereInput = {};

  if (action) {
    where.action = action;
  }

  if (userId) {
    try {
      where.userId = BigInt(userId);
    } catch {
      where.userId = BigInt(-1);
    }
  }

  if (dateFrom || dateTo) {
    where.occurredAt = {
      ...(dateFrom ? { gte: dateFrom } : {}),
      ...(dateTo ? { lte: dateTo } : {})
    };
  }

  if (search) {
    where.OR = [
      { action: { contains: search, mode: "insensitive" } },
      { entityType: { contains: search, mode: "insensitive" } },
      { entityId: { contains: search, mode: "insensitive" } },
      { pathname: { contains: search, mode: "insensitive" } },
      { summary: { contains: search, mode: "insensitive" } },
      { user: { name: { contains: search, mode: "insensitive" } } },
      { user: { email: { contains: search, mode: "insensitive" } } },
      { user: { username: { contains: search, mode: "insensitive" } } }
    ];
  }

  return where;
}

export async function GET(request: Request) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;

  const { searchParams } = new URL(request.url);
  const page = Math.max(1, Number(searchParams.get("page") ?? "1") || 1);
  const perPage = Math.min(100, Math.max(10, Number(searchParams.get("per_page") ?? "25") || 25));
  const skip = (page - 1) * perPage;
  const where = buildWhere(searchParams);

  const [items, total, actionRows] = await Promise.all([
    prisma.auditTrail.findMany({
      where,
      include: {
        user: {
          include: {
            role: { select: { code: true } }
          }
        }
      },
      orderBy: [{ occurredAt: "desc" }, { id: "desc" }],
      skip,
      take: perPage
    }),
    prisma.auditTrail.count({ where }),
    prisma.auditTrail.findMany({
      distinct: ["action"],
      select: { action: true },
      orderBy: { action: "asc" }
    })
  ]);

  return NextResponse.json({
    data: items.map(serializeAuditTrail),
    meta: {
      page,
      per_page: perPage,
      total,
      total_pages: Math.max(1, Math.ceil(total / perPage))
    },
    filters: {
      actions: actionRows.map((item) => item.action)
    }
  });
}
