import { Prisma } from "@prisma/client";
import { getServerSession } from "next-auth";
import { EmptyState } from "../../components/empty-state";
import { authOptions } from "../../lib/auth/options";
import { prisma } from "../../lib/db/prisma";

type AuditSearchParams = {
  organizationId?: string;
  actorUserId?: string;
  action?: string;
  targetType?: string;
  from?: string;
  to?: string;
  cursor?: string;
};

function parseDate(value?: string) {
  if (!value) return undefined;
  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? undefined : date;
}

function formatMetadata(value: string | null) {
  if (!value) return "-";
  try {
    return JSON.stringify(JSON.parse(value));
  } catch {
    return value;
  }
}

function auditHref(searchParams: AuditSearchParams, updates: Record<string, string | undefined>) {
  const params = new URLSearchParams();
  for (const [key, value] of Object.entries({ ...searchParams, ...updates })) {
    if (value) params.set(key, value);
  }
  return `/admin/audit-logs?${params.toString()}`;
}

function auditExportHref(searchParams: AuditSearchParams) {
  const params = new URLSearchParams();
  for (const [key, value] of Object.entries(searchParams)) {
    if (value && key !== "cursor") params.set(key, value);
  }
  return `/api/audit-logs/export?${params.toString()}`;
}

export default async function AuditLogsPage({ searchParams }: { searchParams: AuditSearchParams }) {
  const session = await getServerSession(authOptions);
  const systemAdmin = session?.user.systemRole === "SYSTEM_ADMIN";
  const from = parseDate(searchParams.from);
  const to = parseDate(searchParams.to);

  const where: Prisma.AuditLogWhereInput = systemAdmin ? {} : { organizationId: session?.user.organizationId! };
  if (systemAdmin && searchParams.organizationId) where.organizationId = searchParams.organizationId;
  if (searchParams.actorUserId) where.actorUserId = searchParams.actorUserId;
  if (searchParams.action) where.action = { contains: searchParams.action };
  if (searchParams.targetType) where.targetType = searchParams.targetType;
  if (from || to) where.createdAt = { gte: from, lte: to };

  const baseWhere = systemAdmin ? {} : { organizationId: session?.user.organizationId! };
  const pageSize = 100;
  const [pageLogs, actors, organizations, actions, targetTypes] = await Promise.all([
    prisma.auditLog.findMany({
      where,
      take: pageSize + 1,
      ...(searchParams.cursor ? { cursor: { id: searchParams.cursor }, skip: 1 } : {}),
      orderBy: [{ createdAt: "desc" }, { id: "desc" }],
      include: {
        actor: { select: { id: true, name: true, email: true } },
        organization: { select: { id: true, name: true } }
      }
    }),
    prisma.user.findMany({ where: baseWhere, select: { id: true, name: true, email: true }, orderBy: { name: "asc" } }),
    systemAdmin
      ? prisma.organization.findMany({ select: { id: true, name: true }, orderBy: { name: "asc" } })
      : Promise.resolve([]),
    prisma.auditLog.findMany({
      where: baseWhere,
      distinct: ["action"],
      select: { action: true },
      orderBy: { action: "asc" }
    }),
    prisma.auditLog.findMany({
      where: { ...baseWhere, targetType: { not: null } },
      distinct: ["targetType"],
      select: { targetType: true },
      orderBy: { targetType: "asc" }
    })
  ]);
  const logs = pageLogs.slice(0, pageSize);
  const nextCursor = pageLogs.length > pageSize ? logs.at(-1)?.id : undefined;

  return (
    <div>
      <div className="flex flex-wrap items-end justify-between gap-4">
        <div>
          <h1 className="text-3xl font-semibold">Audit Logs</h1>
          <p className="mt-2 text-slate-600">Review admin changes, approvals, invites, and password reset requests.</p>
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <a className="brand-button-secondary" href={auditExportHref(searchParams)}>Export CSV</a>
          <div className="rounded-lg border border-brand-primary/20 bg-white px-4 py-3 text-sm shadow-sm">
            <span className="font-semibold">{logs.length}</span>{nextCursor ? "+" : ""} events
          </div>
        </div>
      </div>

      <form className="mt-5 grid gap-3 rounded-lg border border-brand-secondary/20 bg-white p-4 shadow-sm md:grid-cols-6">
        {systemAdmin ? (
          <select className="rounded-lg border border-slate-300 px-3 py-2 text-sm" name="organizationId" defaultValue={searchParams.organizationId ?? ""}>
            <option value="">All organizations</option>
            {organizations.map((organization) => <option key={organization.id} value={organization.id}>{organization.name}</option>)}
          </select>
        ) : null}
        <select className="rounded-lg border border-slate-300 px-3 py-2 text-sm" name="actorUserId" defaultValue={searchParams.actorUserId ?? ""}>
          <option value="">All actors</option>
          {actors.map((actor) => <option key={actor.id} value={actor.id}>{actor.name ?? actor.email}</option>)}
        </select>
        <select className="rounded-lg border border-slate-300 px-3 py-2 text-sm" name="action" defaultValue={searchParams.action ?? ""}>
          <option value="">All actions</option>
          {actions.map((item) => <option key={item.action} value={item.action}>{item.action}</option>)}
        </select>
        <select className="rounded-lg border border-slate-300 px-3 py-2 text-sm" name="targetType" defaultValue={searchParams.targetType ?? ""}>
          <option value="">All targets</option>
          {targetTypes.map((item) => item.targetType ? <option key={item.targetType} value={item.targetType}>{item.targetType}</option> : null)}
        </select>
        <input className="rounded-lg border border-slate-300 px-3 py-2 text-sm" name="from" type="date" defaultValue={searchParams.from ?? ""} />
        <input className="rounded-lg border border-slate-300 px-3 py-2 text-sm" name="to" type="date" defaultValue={searchParams.to ?? ""} />
        <button className="brand-button md:col-span-6" type="submit">Apply filters</button>
      </form>

      <section className="mt-6 rounded-lg border border-brand-primary/20 bg-white p-5 shadow-sm">
        <div className="flex items-center justify-between gap-4">
          <h2 className="text-lg font-semibold">Recent activity</h2>
          <p className="text-sm text-slate-500">Showing {logs.length} records</p>
        </div>
        {logs.length ? (
          <div className="mt-4 overflow-x-auto">
            <table className="w-full min-w-[960px] text-left text-sm">
              <thead className="text-slate-500">
                <tr>
                  <th className="py-2">Time</th>
                  <th>Actor</th>
                  {systemAdmin ? <th>Organization</th> : null}
                  <th>Action</th>
                  <th>Target</th>
                  <th>Metadata</th>
                </tr>
              </thead>
              <tbody>
                {logs.map((log) => (
                  <tr className="border-t border-slate-200 align-top" key={log.id}>
                    <td className="whitespace-nowrap py-3">{log.createdAt.toLocaleString()}</td>
                    <td>
                      <div className="font-medium">{log.actor?.name ?? "System"}</div>
                      <div className="text-xs text-slate-500">{log.actor?.email ?? log.actorUserId ?? "-"}</div>
                    </td>
                    {systemAdmin ? <td>{log.organization?.name ?? "Global"}</td> : null}
                    <td><span className="rounded-lg bg-brand-paper px-2 py-1 text-xs font-semibold text-brand-primary">{log.action}</span></td>
                    <td>
                      <div>{log.targetType ?? "-"}</div>
                      <div className="text-xs text-slate-500">{log.targetId ?? "-"}</div>
                    </td>
                    <td className="max-w-md truncate font-mono text-xs text-slate-600" title={formatMetadata(log.metadata)}>
                      {formatMetadata(log.metadata)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <div className="mt-4">
            <EmptyState title="No audit events found" description="Try changing filters or perform an admin action to create a new audit event." />
          </div>
        )}
        {nextCursor ? (
          <div className="mt-5 flex justify-center">
            <a className="brand-button-secondary" href={auditHref(searchParams, { cursor: nextCursor })}>Load older events</a>
          </div>
        ) : null}
      </section>
    </div>
  );
}
