import type { PrismaClient, AuditLog, Prisma } from '@prisma/client';
import type { IAuditLogRepository, AuditLogFilter } from './interfaces.js';

export class AuditLogRepository implements IAuditLogRepository {
  constructor(private readonly prisma: PrismaClient) {}

  async findAll(filter?: AuditLogFilter): Promise<AuditLog[]> {
    const where = buildWhere(filter);
    return this.prisma.auditLog.findMany({
      where,
      orderBy: { createdAt: 'desc' },
      take: filter?.limit ?? 100,
      skip: filter?.offset ?? 0,
    });
  }

  async findById(id: string): Promise<AuditLog | null> {
    return this.prisma.auditLog.findUnique({ where: { id } });
  }

  async create(data: {
    userId: string;
    action: string;
    resource: string;
    resourceId?: string;
    details?: Record<string, unknown>;
  }): Promise<AuditLog> {
    const createData: Prisma.AuditLogUncheckedCreateInput = {
      userId: data.userId,
      action: data.action,
      resource: data.resource,
      details: (data.details ?? {}) as Prisma.InputJsonValue,
    };
    if (data.resourceId !== undefined) {
      createData.resourceId = data.resourceId;
    }
    return this.prisma.auditLog.create({ data: createData });
  }

  async count(filter?: AuditLogFilter): Promise<number> {
    const where = buildWhere(filter);
    return this.prisma.auditLog.count({ where });
  }

  async deleteOlderThan(date: Date): Promise<number> {
    const result = await this.prisma.auditLog.deleteMany({
      where: { createdAt: { lt: date } },
    });
    return result.count;
  }
}

function buildWhere(filter?: AuditLogFilter): Prisma.AuditLogWhereInput {
  const where: Prisma.AuditLogWhereInput = {};
  if (!filter) return where;

  if (filter.userId !== undefined) where.userId = filter.userId;
  if (filter.action !== undefined) where.action = filter.action;
  if (filter.resource !== undefined) where.resource = filter.resource;
  if (filter.resourceId !== undefined) where.resourceId = filter.resourceId;

  if (filter.since !== undefined || filter.until !== undefined) {
    const createdAt: Prisma.DateTimeFilter = {};
    if (filter.since !== undefined) createdAt.gte = filter.since;
    if (filter.until !== undefined) createdAt.lte = filter.until;
    where.createdAt = createdAt;
  }

  return where;
}
