import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { FilterQuery, Model, Types } from 'mongoose';
import { Report, ReportDocument, ReportStatus } from './schemas/report.schema';

@Injectable()
export class ReportsRepository {
  constructor(@InjectModel(Report.name) private readonly reportModel: Model<ReportDocument>) {}

  async create(payload: {
    reporterId: string;
    targetType: string;
    targetId: string;
    reason: string;
    details?: string;
  }): Promise<ReportDocument> {
    return this.reportModel
      .findOneAndUpdate(
        {
          reporterId: new Types.ObjectId(payload.reporterId),
          targetType: payload.targetType,
          targetId: new Types.ObjectId(payload.targetId),
        },
        {
          $setOnInsert: {
            reporterId: new Types.ObjectId(payload.reporterId),
            targetType: payload.targetType,
            targetId: new Types.ObjectId(payload.targetId),
          },
          $set: {
            reason: payload.reason,
            details: payload.details ?? '',
            status: 'open',
            resolutionNote: '',
            resolvedBy: '',
            resolvedAt: null,
          },
        },
        { new: true, upsert: true },
      )
      .exec();
  }

  async findMany(filter: FilterQuery<ReportDocument>, skip: number, limit: number, sort: Record<string, 1 | -1>) {
    return this.reportModel
      .find(filter)
      .populate({ path: 'reporterId', select: 'name username avatar stageName isVerified' })
      .sort(sort)
      .skip(skip)
      .limit(limit)
      .exec();
  }

  async count(filter: FilterQuery<ReportDocument>): Promise<number> {
    return this.reportModel.countDocuments(filter).exec();
  }

  async updateStatus(
    reportId: string,
    status: ReportStatus,
    resolutionNote: string,
    resolvedBy: string,
  ): Promise<ReportDocument | null> {
    return this.reportModel
      .findByIdAndUpdate(
        reportId,
        {
          status,
          resolutionNote,
          resolvedBy,
          resolvedAt: ['resolved', 'rejected'].includes(status) ? new Date() : null,
        },
        { new: true },
      )
      .exec();
  }
}
