import {
  getRatingAggregate,
  listReviews,
  listReviewsByVendor,
  moderateReview,
  pushReviewsSchema,
  replyToReview,
  submitReview,
  type ListReviewsOptions,
  type ModerationAdapter,
  type Page,
  type RatingAggregate,
  type Review,
  type ReviewsSchema,
  type SubmitReviewInput,
  type VerifiedPurchasePort,
} from '@platform-modules/commerce-reviews';
import { and, eq } from 'drizzle-orm';
import type { Querier } from '@platform-modules/db';
import type { DrizzleClient } from '@/server/db/client';
import { order, orderLine, dealSkus } from '@/server/db/schema.js';

// The platform reviews functions consume a `Querier` (read + write, no transaction),
// which is exactly what `DrizzleClient` is — so the binding accepts the client type every
// host caller already holds. A `DrizzleDb` (NeonDatabase) is also assignable here.
export function toReviewsDb(db: DrizzleClient): Querier<ReviewsSchema> {
  return db as unknown as Querier<ReviewsSchema>;
}

/**
 * Multideal's review model is visible-by-default (the host `reviews.isVisible`
 * column defaults true) with remove-on-moderation; pre-publish AI scoring runs only
 * on removal *requests*, never on submission. So a newly submitted review must publish
 * immediately ('approved'). The platform default — no moderation adapter → status
 * 'pending' (D3 fail-closed) — would silently hide every new review and exclude it from
 * the live aggregate (public list filters status='approved'). This auto-approve adapter
 * is D3's host escape hatch: it ports the old visible-by-default behaviour faithfully.
 */
export const autoApproveReviewModeration: ModerationAdapter = {
  async score() {
    return { action: 'approve', score: 1 };
  },
};

export function makeVerifiedPurchasePort(db: DrizzleClient): VerifiedPurchasePort {
  return {
    async hasPurchased(userId: string, productId: string, purchaseId: string): Promise<boolean> {
      const [row] = await db
        .select({ id: orderLine.id })
        .from(orderLine)
        .innerJoin(order, eq(order.id, orderLine.orderId))
        .innerJoin(dealSkus, eq(dealSkus.id, orderLine.variantId))
        .where(
          and(
            eq(orderLine.id, purchaseId),
            eq(order.buyerUserId, userId),
            eq(dealSkus.dealId, productId),
            eq(order.status, 'completed'),
          ),
        )
        .limit(1);
      return row != null;
    },
  };
}

export {
  getRatingAggregate,
  listReviews,
  listReviewsByVendor,
  moderateReview,
  pushReviewsSchema,
  replyToReview,
  submitReview,
};
export type {
  ListReviewsOptions,
  ModerationAdapter,
  Page,
  RatingAggregate,
  Review,
  ReviewsSchema,
  SubmitReviewInput,
  VerifiedPurchasePort,
};
