import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { ReportFile } from '../../../domain/entities/report-file.entity';
import { IReportFileRepository } from '../../../domain/repositories';
import { OutputFormat } from '../../../domain/value-objects';
import { ReportFileMapper } from '../mappers/report-file.mapper';

@Injectable()
export class ReportFileRepository implements IReportFileRepository {
  constructor(private readonly prisma: PrismaService) {}

  async save(file: ReportFile): Promise<ReportFile> {
    const data = ReportFileMapper.toPersistence(file);

    if (file.id) {
      const updated = await this.prisma.reportFile.update({
        where: { id: file.id },
        data: {
          fileUrl: data.fileUrl,
          downloadCount: data.downloadCount,
          lastDownloadAt: data.lastDownloadAt,
          expiresAt: data.expiresAt,
        },
      });
      return ReportFileMapper.toDomain(updated);
    }

    const created = await this.prisma.reportFile.create({
      data: {
        snapshotId: data.snapshotId,
        fileName: data.fileName,
        filePath: data.filePath,
        fileUrl: data.fileUrl,
        fileSize: data.fileSize,
        fileFormat: data.fileFormat,
        mimeType: data.mimeType,
        downloadCount: data.downloadCount,
        lastDownloadAt: data.lastDownloadAt,
        expiresAt: data.expiresAt,
      },
    });
    return ReportFileMapper.toDomain(created);
  }

  async findById(id: bigint): Promise<ReportFile | null> {
    const found = await this.prisma.reportFile.findUnique({
      where: { id },
    });
    return found ? ReportFileMapper.toDomain(found) : null;
  }

  async findBySnapshotId(snapshotId: bigint): Promise<ReportFile[]> {
    const found = await this.prisma.reportFile.findMany({
      where: { snapshotId },
      orderBy: { createdAt: 'desc' },
    });
    return found.map(ReportFileMapper.toDomain);
  }

  async findBySnapshotIdAndFormat(
    snapshotId: bigint,
    format: OutputFormat,
  ): Promise<ReportFile | null> {
    const found = await this.prisma.reportFile.findFirst({
      where: {
        snapshotId,
        fileFormat: format,
      },
      orderBy: { createdAt: 'desc' },
    });
    return found ? ReportFileMapper.toDomain(found) : null;
  }

  async findExpired(): Promise<ReportFile[]> {
    const found = await this.prisma.reportFile.findMany({
      where: {
        expiresAt: {
          lt: new Date(),
        },
      },
    });
    return found.map(ReportFileMapper.toDomain);
  }

  async deleteExpired(): Promise<number> {
    const result = await this.prisma.reportFile.deleteMany({
      where: {
        expiresAt: {
          lt: new Date(),
        },
      },
    });
    return result.count;
  }

  async delete(id: bigint): Promise<void> {
    await this.prisma.reportFile.delete({
      where: { id },
    });
  }
}
