import { Star } from 'lucide-react';
import type { ProductReview } from 'brainerce';
import { getServerClient } from '@/core/lib/brainerce.server';
import { CdnImage } from '@/ui/shared/cdn-image';
import { Badge } from '@/components/ui/badge';
<% if (i18nEnabled) { %>import { getMessages, defaultLocale } from '@/i18n';<% } else { %>import { defaultLocale, messages } from '@/i18n';<% } %>
import { ReviewForm } from './review-form';

// Server component — it renders before any client i18n context exists, so the
// wrapper strings (title / empty state / verified badge) are read straight
// from the `reviews` namespace in messages/, keyed by the store locale.
type ReviewStrings = Record<string, string>;

<% if (i18nEnabled) { %>async function getReviewStrings(locale: string): Promise<ReviewStrings> {
  return ((await getMessages(locale)).reviews ?? {}) as ReviewStrings;
}<% } else { %>async function getReviewStrings(_locale: string): Promise<ReviewStrings> {
  return messages.reviews as ReviewStrings;
}<% } %>

interface ReviewsSectionProps {
  productId: string;
  initialReviews?: ProductReview[];
  locale?: string;
  /** Where to send users back to after submit (defaults to the current product URL). */
  returnUrl?: string;
}

/**
 * Renders the visible reviews for a product plus a submit form.
 *
 * Server component — fetches with the SDK on the server so reviews are in
 * the initial HTML payload (good for SEO; JSON-LD on the same page already
 * carries `aggregateRating` when reviewCount > 0).
 */
export async function ReviewsSection({
  productId,
  initialReviews,
  locale = defaultLocale,
}: ReviewsSectionProps) {
  const t = await getReviewStrings(locale);
  let reviews: ProductReview[] = initialReviews ?? [];

  if (!initialReviews) {
    try {
      const result = await (await getServerClient()).listProductReviews(productId, { page: 1, limit: 20, sort: 'photos_first' });
      reviews = result.data;
    } catch {
      // Review listing disabled at store level or network error — render the form anyway.
      reviews = [];
    }
  }

  return (
    <section className="mt-8" aria-labelledby="reviews-heading">
      <h2 id="reviews-heading" className="mb-4 text-xl font-semibold">
        {t.title}
      </h2>

      {reviews.length === 0 ? (
        <p className="text-muted-foreground mb-6 text-sm">{t.noReviews}</p>
      ) : (
        <ul className="mb-6 space-y-4">
          {reviews.map((review) => (
            <ReviewCard key={review.id} review={review} verifiedLabel={t.verifiedPurchase} />
          ))}
        </ul>
      )}

      <ReviewForm productId={productId} />
    </section>
  );
}

function ReviewCard({ review, verifiedLabel }: { review: ProductReview; verifiedLabel: string }) {
  return (
    <li className="rounded-md border p-4">
      <header className="flex flex-wrap items-center gap-2">
        <Stars rating={review.rating} />
        <span className="text-sm font-medium">{review.authorName}</span>
        {review.verifiedPurchase && (
          <Badge
            variant="outline"
            className="rounded border-transparent bg-emerald-50 px-2 py-0.5 font-normal text-emerald-700"
          >
            {verifiedLabel}
          </Badge>
        )}
        <time className="text-muted-foreground ms-auto text-xs">
          {new Date(review.createdAt).toLocaleDateString()}
        </time>
      </header>
      {review.body && <p className="mt-2 whitespace-pre-line break-words text-sm">{review.body}</p>}
      <ReviewPhotos review={review} />
    </li>
  );
}

/**
 * Photos the reviewer attached. `review.images` is always an array and already
 * carries only what shoppers are allowed to see, so there is nothing to filter.
 *
 * The intrinsic width/height come back from the API — passing them through is
 * what stops the page jumping as the photos load.
 */
function ReviewPhotos({ review }: { review: ProductReview }) {
  if (review.images.length === 0) return null;

  return (
    <ul className="mt-3 flex flex-wrap gap-2">
      {review.images.map((image) => (
        <li key={image.id}>
          <a href={image.url} target="_blank" rel="noopener noreferrer">
            <CdnImage
              src={image.thumbnailUrl ?? image.url}
              alt=""
              width={image.width ?? 96}
              height={image.height ?? 96}
              className="h-24 w-24 rounded-md border object-cover"
            />
          </a>
        </li>
      ))}
    </ul>
  );
}

function Stars({ rating }: { rating: number }) {
  return (
    <span aria-label={`${rating} of 5 stars`} className="inline-flex">
      {[1, 2, 3, 4, 5].map((n) => (
        <Star
          key={n}
          className={`h-4 w-4 fill-current ${n <= rating ? 'text-yellow-500' : 'text-gray-300'}`}
          aria-hidden="true"
        />
      ))}
    </span>
  );
}
