import { Controller, Get, Query } from '@nestjs/common';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { and, desc, eq, gte, ilike, lte, sql } from 'drizzle-orm';
import { z } from 'zod';
import { PaginationQuery, Uuid } from '@wms/shared';
import { RequirePermissions } from '@/common/auth/decorators';
import { zodQuery } from '@/common/validation/zod.pipe';
import { DbService } from '@/common/db/db.service';
import { auditLogs } from '@/db/schema';
import { paginate, offsetOf, serialize } from '@/common/util';

const AuditQuery = PaginationQuery.extend({
  entityType: z.string().optional(),
  entityId: Uuid.optional(),
  action: z.string().optional(),
  actorId: z.string().optional(),
  from: z.string().optional(),
  to: z.string().optional(),
});

/** Read-only audit trail (tenant scoped by RLS). */
@ApiTags('audit')
@ApiBearerAuth()
@Controller('audit')
export class AuditController {
  constructor(private readonly db: DbService) {}

  @Get() @RequirePermissions('audit.read')
  list(@Query(zodQuery(AuditQuery)) q: z.infer<typeof AuditQuery>) {
    return this.db.run(async (tx) => {
      const where = and(
        q.entityType ? eq(auditLogs.entityType, q.entityType) : undefined,
        q.entityId ? eq(auditLogs.entityId, q.entityId) : undefined,
        q.action ? ilike(auditLogs.action, `${q.action}%`) : undefined,
        q.actorId ? eq(auditLogs.actorId, q.actorId) : undefined,
        q.from ? gte(auditLogs.createdAt, new Date(`${q.from}T00:00:00Z`)) : undefined,
        q.to ? lte(auditLogs.createdAt, new Date(`${q.to}T23:59:59Z`)) : undefined,
      );
      const [{ count }] = await tx.select({ count: sql<number>`count(*)`.mapWith(Number) }).from(auditLogs).where(where);
      const rows = await tx.select().from(auditLogs).where(where).orderBy(desc(auditLogs.createdAt)).limit(q.pageSize).offset(offsetOf(q));
      return paginate(serialize(rows), count, q);
    });
  }
}
