/**
 * Review queries — list/aggregate delegate to platform; technical via deal_annotations.
 */

import { eq, and, desc } from 'drizzle-orm';
import type { DrizzleClient } from '../client.js';
import { reviews, dealAnnotations, deals } from '../schema.js';
import {
  listReviews,
  listReviewsByVendor,
  getRatingAggregate,
  toReviewsDb,
} from '@/server/reviews/reviews-platform.js';
import type { Review } from '@/server/reviews/reviews-platform.js';

export async function listByVendor(db: DrizzleClient, vendorId: string): Promise<Review[]> {
  const page = await listReviewsByVendor(toReviewsDb(db), vendorId, { audience: 'public' });
  return page.items;
}

export async function listTechnicalByVendor(db: DrizzleClient, vendorId: string) {
  // Technical reviews are authored by buyers (authorId = buyer userId) about a deal,
  // so they are keyed to a vendor via the deal, not the annotation author. Join `deals`
  // and filter on deals.vendorId — restoring the pre-migration semantics
  // (reviews.vendorId = vendorId), which a filter on dealAnnotations.authorId would never match.
  return db
    .select({
      id: dealAnnotations.id,
      dealId: dealAnnotations.dealId,
      authorId: dealAnnotations.authorId,
      authorRole: dealAnnotations.authorRole,
      body: dealAnnotations.body,
      isVisible: dealAnnotations.isVisible,
      createdAt: dealAnnotations.createdAt,
    })
    .from(dealAnnotations)
    .innerJoin(deals, eq(dealAnnotations.dealId, deals.id))
    .where(and(eq(deals.vendorId, vendorId), eq(dealAnnotations.isVisible, true)))
    .orderBy(desc(dealAnnotations.createdAt));
}

export async function listByDeal(db: DrizzleClient, dealId: string): Promise<Review[]> {
  const page = await listReviews(toReviewsDb(db), dealId, { audience: 'public' });
  return page.items;
}

export async function getReviewAggregateForDeal(
  db: DrizzleClient,
  dealId: string,
): Promise<{ ratingAvg: string | null; ratingCount: number }> {
  const agg = await getRatingAggregate(toReviewsDb(db), dealId);
  return {
    ratingAvg: agg.count > 0 ? agg.avg.toFixed(2) : null,
    ratingCount: agg.count,
  };
}

export type CreateReviewInput = {
  purchaseId: string;
  userId: string;
  vendorId: string;
  dealId: string;
  reviewType?: 'STANDARD' | 'TECHNICAL';
  rating?: number;
  body: string;
};

export async function create(db: DrizzleClient, input: CreateReviewInput) {
  const [row] = await db
    .insert(reviews)
    .values({
      orderLineId: input.purchaseId,
      userId: input.userId,
      vendorId: input.vendorId,
      dealId: input.dealId,
      reviewType: input.reviewType ?? 'STANDARD',
      rating: input.rating,
      body: input.body,
    })
    .returning();
  return row!;
}

export async function reply(db: DrizzleClient, reviewId: string, vendorReply: string) {
  const [row] = await db
    .update(reviews)
    .set({ vendorReply, vendorReplyAt: new Date() })
    .where(eq(reviews.id, reviewId))
    .returning();
  return row ?? null;
}

export async function requestRemoval(db: DrizzleClient, reviewId: string, reason: string) {
  const [row] = await db
    .update(reviews)
    .set({
      removalRequested: true,
      removalReason: reason,
      removalStatus: 'PENDING',
    })
    .where(eq(reviews.id, reviewId))
    .returning();
  return row ?? null;
}

export async function approveReviewRemoval(db: DrizzleClient, reviewId: string): Promise<void> {
  await db
    .update(reviews)
    .set({
      isVisible: false,
      removedBy: 'HUMAN',
      removalStatus: 'APPROVED',
    })
    .where(eq(reviews.id, reviewId));
}

export async function rejectReviewRemoval(db: DrizzleClient, reviewId: string): Promise<void> {
  await db.update(reviews).set({ removalStatus: 'REJECTED' }).where(eq(reviews.id, reviewId));
}
