"use client";

import { useState, useEffect, useRef } from "react";
import Image from "next/image";
import { useTranslations, useLocale } from "next-intl";
import { Star, Camera, X, ChefHat } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { getPublicUrl } from "@/lib/storage";
import { uploadToPresignedPost } from "@/lib/upload-client";
import { cn } from "@/lib/utils";

type Review = {
  id: string;
  score: number;
  reviewText: string | null;
  photoKey: string | null;
  createdAt: string;
  user: { id: string; name: string; username: string | null; avatarUrl: string | null };
};

function Stars({
  value,
  hovered,
  onHover,
  onPick,
}: {
  value: number;
  hovered: number;
  onHover: (v: number) => void;
  onPick: (v: number) => void;
}) {
  const display = hovered || value;
  return (
    <div className="flex items-center gap-0.5">
      {[1, 2, 3, 4, 5].map((i) => (
        <button
          key={i}
          type="button"
          onMouseEnter={() => onHover(i)}
          onMouseLeave={() => onHover(0)}
          onClick={() => onPick(i)}
          className="hover:scale-110 transition-transform"
        >
          <Star className={cn("h-6 w-6", i <= display ? "fill-yellow-400 text-yellow-400" : "text-muted-foreground/30")} />
        </button>
      ))}
    </div>
  );
}

export function CookedItReview({
  recipeId,
  initialScore = 0,
  initialText = "",
  initialPhotoKey = null,
}: {
  recipeId: string;
  initialScore?: number;
  initialText?: string;
  initialPhotoKey?: string | null;
}) {
  const t = useTranslations("social");
  const locale = useLocale();
  const [score, setScore] = useState(initialScore);
  const [hovered, setHovered] = useState(0);
  const [text, setText] = useState(initialText);
  const [photoKey, setPhotoKey] = useState<string | null>(initialPhotoKey);
  const [photoSizeMb, setPhotoSizeMb] = useState(0);
  const [preview, setPreview] = useState<string | null>(null);
  const [uploading, setUploading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [reviews, setReviews] = useState<Review[]>([]);
  const [loadingReviews, setLoadingReviews] = useState(true);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    fetch(`/api/v1/recipes/${recipeId}/reviews`)
      .then((res) => (res.ok ? res.json() : null))
      .then((data: { data: Review[] } | null) => setReviews(data?.data ?? []))
      .finally(() => setLoadingReviews(false));
  }, [recipeId]);

  async function handlePhoto(file: File) {
    setUploading(true);
    try {
      const res = await fetch("/api/v1/upload/presign", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ recipeId, contentType: file.type, purpose: "review", fileSize: file.size }),
      });
      if (!res.ok) {
        toast.error(t("reviewPhotoFailed"));
        return;
      }
      const { url, fields, key, sizeMb } = (await res.json()) as { url: string; fields: Record<string, string>; key: string; sizeMb: number };
      const uploaded = await uploadToPresignedPost(url, fields, file);
      if (!uploaded) {
        toast.error(t("reviewPhotoFailed"));
        return;
      }
      setPhotoKey(key);
      setPhotoSizeMb(sizeMb);
      setPreview(URL.createObjectURL(file));
    } finally {
      setUploading(false);
    }
  }

  async function submit() {
    if (score < 1) return;
    setSaving(true);
    try {
      const res = await fetch(`/api/v1/recipes/${recipeId}/rate`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ score, reviewText: text.trim() || undefined, photoKey: photoKey ?? undefined, photoSizeMb }),
      });
      if (!res.ok) {
        const err = (await res.json()) as { error?: string };
        toast.error(err.error ?? t("ratingFailed"));
        return;
      }
      toast.success(t("ratingSaved"));
      const listRes = await fetch(`/api/v1/recipes/${recipeId}/reviews`);
      if (listRes.ok) {
        const data = (await listRes.json()) as { data: Review[] };
        setReviews(data.data);
      }
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="space-y-6">
      <div className="rounded-lg border p-4 space-y-3">
        <div className="flex items-center gap-2 text-sm font-medium">
          <ChefHat className="h-4 w-4 text-primary" />
          {t("cookedItPrompt")}
        </div>
        <Stars value={score} hovered={hovered} onHover={setHovered} onPick={setScore} />
        <Textarea
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder={t("reviewTextPlaceholder")}
          maxLength={2000}
          rows={3}
        />
        <div className="flex items-center gap-3">
          {(preview || photoKey) && (
            <div className="relative h-16 w-16">
              <Image
                src={preview ?? getPublicUrl(photoKey!)}
                unoptimized
                alt="Your cooked-it photo"
                fill
                className="rounded-lg object-cover border"
              />
              <button
                type="button"
                onClick={() => { setPhotoKey(null); setPreview(null); setPhotoSizeMb(0); }}
                className="absolute -top-1.5 -right-1.5 rounded-full bg-background border p-0.5"
              >
                <X className="h-3 w-3" />
              </button>
            </div>
          )}
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={uploading}
            onClick={() => inputRef.current?.click()}
          >
            <Camera className="h-4 w-4 mr-1.5" />
            {uploading ? t("reviewPhotoUploading") : t("reviewPhotoAdd")}
          </Button>
          <input
            ref={inputRef}
            type="file"
            accept="image/jpeg,image/png,image/webp,image/avif"
            className="hidden"
            onChange={(e) => e.target.files?.[0] && handlePhoto(e.target.files[0])}
          />
          <Button type="button" size="sm" className="ml-auto" disabled={score < 1 || saving} onClick={submit}>
            {saving ? t("reviewSubmitting") : t("reviewSubmit")}
          </Button>
        </div>
      </div>

      {!loadingReviews && reviews.length > 0 && (
        <div className="space-y-4">
          <h3 className="text-sm font-medium text-muted-foreground">{t("reviewsTitle", { count: reviews.length })}</h3>
          {reviews.map((r) => (
            <div key={r.id} className="flex gap-3">
              <Avatar className="h-8 w-8">
                <AvatarImage src={r.user.avatarUrl ?? undefined} alt={r.user.name} />
                <AvatarFallback>{r.user.name.slice(0, 2).toUpperCase()}</AvatarFallback>
              </Avatar>
              <div className="flex-1 space-y-1.5">
                <div className="flex items-center gap-2 text-sm">
                  <span className="font-medium">{r.user.name}</span>
                  <div className="flex items-center">
                    {[1, 2, 3, 4, 5].map((i) => (
                      <Star key={i} className={cn("h-3 w-3", i <= r.score ? "fill-yellow-400 text-yellow-400" : "text-muted-foreground/30")} />
                    ))}
                  </div>
                  <span className="text-xs text-muted-foreground">
                    {new Date(r.createdAt).toLocaleDateString(locale)}
                  </span>
                </div>
                {r.reviewText && <p className="text-sm text-muted-foreground">{r.reviewText}</p>}
                {r.photoKey && (
                  <div className="relative h-32 w-32">
                    <Image
                      src={getPublicUrl(r.photoKey)}
                      unoptimized
                      alt={`${r.user.name}'s cooked-it photo`}
                      fill
                      className="rounded-lg object-cover border"
                    />
                  </div>
                )}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
