import { Injectable } from '@nestjs/common';
import { type Prisma } from '@prisma/client';
import { PrismaService } from '@modules/shared';
import {
  type CreateModerationAuditLogInput,
  type IModerationAuditLogRepository,
  type ModerationAuditLogEntry,
  type ModerationAuditLogListParams,
  type ModerationAuditLogListResult,
} from '../../domain/repositories/moderation-audit-log.repository';

@Injectable()
export class PrismaModerationAuditLogRepository
  implements IModerationAuditLogRepository
{
  constructor(private readonly prisma: PrismaService) {}

  async create(
    input: CreateModerationAuditLogInput,
  ): Promise<ModerationAuditLogEntry> {
    const record = await this.prisma.moderationAuditLog.create({
      data: {
        targetType: input.targetType,
        targetId: input.targetId,
        action: input.action,
        moderatorId: input.moderatorId,
        reason: input.reason ?? null,
        metadata:
          (input.metadata as Prisma.InputJsonValue | undefined) ?? undefined,
      },
    });

    return this.toEntry(record);
  }

  async findAll(
    params: ModerationAuditLogListParams,
  ): Promise<ModerationAuditLogListResult> {
    const {
      page,
      limit,
      targetType,
      targetId,
      action,
      moderatorId,
      startDate,
      endDate,
    } = params;

    const safePage = Math.max(1, Math.floor(page));
    const safeLimit = Math.min(Math.max(1, Math.floor(limit)), 100);
    const skip = (safePage - 1) * safeLimit;

    const where: Prisma.ModerationAuditLogWhereInput = {};
    if (targetType) where.targetType = targetType;
    if (targetId) where.targetId = targetId;
    if (action) where.action = action;
    if (moderatorId) where.moderatorId = moderatorId;
    if (startDate || endDate) {
      where.createdAt = {};
      if (startDate) where.createdAt.gte = startDate;
      if (endDate) where.createdAt.lte = endDate;
    }

    const [records, total] = await Promise.all([
      this.prisma.moderationAuditLog.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        skip,
        take: safeLimit,
      }),
      this.prisma.moderationAuditLog.count({ where }),
    ]);

    return {
      data: records.map((r) => this.toEntry(r)),
      total,
      page: safePage,
      limit: safeLimit,
      totalPages: Math.ceil(total / safeLimit),
    };
  }

  private toEntry(record: {
    id: string;
    targetType: string;
    targetId: string;
    action: string;
    moderatorId: string;
    reason: string | null;
    metadata: Prisma.JsonValue | null;
    createdAt: Date;
  }): ModerationAuditLogEntry {
    return {
      id: record.id,
      targetType: record.targetType,
      targetId: record.targetId,
      action: record.action,
      moderatorId: record.moderatorId,
      reason: record.reason,
      metadata: record.metadata as Record<string, unknown> | null,
      createdAt: record.createdAt,
    };
  }
}
