import { Injectable, BadRequestException, NotFoundException, ForbiddenException } from "@nestjs/common";
import { PrismaService } from "../../common/prisma/prisma.service";

@Injectable()
export class ReviewsService {
  constructor(private readonly prisma: PrismaService) {}

  /** Get all reviews for a provider (public) */
  listForProvider(revieweeId: string, limit = 20, offset = 0) {
    const take = Number.isFinite(limit) ? Math.min(50, Math.max(1, limit)) : 20;
    const skip = Number.isFinite(offset) ? Math.max(0, offset) : 0;
    return this.prisma.review.findMany({
      where: { revieweeId, isHidden: false },
      orderBy: { createdAt: "desc" },
      take,
      skip,
      include: {
        reviewer: { select: { id: true, fullName: true, avatarUrl: true } },
      },
    });
  }

  /** Get my submitted reviews */
  listMine(reviewerId: string) {
    return this.prisma.review.findMany({
      where: { reviewerId },
      orderBy: { createdAt: "desc" },
      include: {
        reviewee: { select: { id: true, fullName: true, avatarUrl: true } },
        request: { select: { id: true, title: true } },
      },
    });
  }

  /** Submit a review for a completed request */
  async create(
    reviewerId: string,
    body: { requestId: string; revieweeId: string; rating: number; comment?: string },
  ) {
    if (!Number.isInteger(body.rating) || body.rating < 1 || body.rating > 5) {
      throw new BadRequestException("rating_out_of_range");
    }

    const request = await this.prisma.serviceRequest.findUnique({
      where: { id: body.requestId },
    });

    if (!request) throw new NotFoundException("request_not_found");
    if (request.customerId !== reviewerId) throw new ForbiddenException("not_your_request");
    if (request.status !== "COMPLETED") throw new BadRequestException("request_not_completed");
    if (reviewerId === body.revieweeId) {
      throw new ForbiddenException("cannot_review_self");
    }

    const acceptedOffer = await this.prisma.offer.findFirst({
      where: { requestId: body.requestId, providerId: body.revieweeId, status: "ACCEPTED" },
    });
    if (!acceptedOffer) {
      throw new ForbiddenException("reviewee_not_accepted_offer_provider");
    }

    // Upsert — one review per (requestId, reviewerId)
    const review = await this.prisma.$transaction(async (tx) => {
      const savedReview = await tx.review.upsert({
        where: { requestId_reviewerId: { requestId: body.requestId, reviewerId } },
        create: {
          requestId: body.requestId,
          reviewerId,
          revieweeId: body.revieweeId,
          rating: body.rating,
          comment: body.comment?.trim().slice(0, 2000) || null,
        },
        update: {
          rating: body.rating,
          comment: body.comment?.trim().slice(0, 2000) || null,
        },
        include: {
          reviewer: { select: { id: true, fullName: true, avatarUrl: true } },
        },
      });

      const agg = await tx.review.aggregate({
        where: { revieweeId: body.revieweeId, isHidden: false },
        _avg: { rating: true },
        _count: true,
      });

      await tx.providerProfile.updateMany({
        where: { userId: body.revieweeId },
        data: {
          ratingAverage: agg._avg.rating ?? 0,
          ratingCount: agg._count,
        },
      });

      return savedReview;
    });

    return review;
  }
}
