"use client";

import { useState } from "react";
import Link from "next/link";
import { usePathname, useSearchParams } from "next/navigation";
import Icon from "@/components/ui/Icon";
import { submitReview } from "@/lib/api/auth";
import { useAuth } from "@/store/auth";
import { FormAlert, readError } from "./Form";

const LABEL = ["", "Poor", "Fair", "Good", "Very good", "Excellent"];

/** Star rating plus an optional comment. New reviews wait for approval, so the page says so instead of listing them. */
export default function ReviewForm({ reviewableId, reviewerIds = [] }: { reviewableId: number; reviewerIds?: number[] }) {
  const path = usePathname();
  const search = useSearchParams().toString();
  const status = useAuth((s) => s.status);
  const userId = useAuth((s) => s.user?.id);
  const [rating, setRating] = useState(0);
  const [hover, setHover] = useState(0);
  const [comment, setComment] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [done, setDone] = useState(false);

  if (status === "unknown") return null;
  if (status === "guest") {
    const here = search ? `${path}?${search}` : path;
    return (
      <p className="lfd-review-cta">
        <Link className="acct-link" href={`/login?next=${encodeURIComponent(here)}`}>
          Sign in
        </Link>{" "}
        to write a review.
      </p>
    );
  }
  // The API allows one review per person. Approved ones are in the list; a pending one still gets the API message.
  if (userId && reviewerIds.includes(userId)) return <p className="lfd-review-cta">You have reviewed this place. Thank you.</p>;
  if (done) return <FormAlert tone="ok">Thanks for your review. It will appear here once it is approved.</FormAlert>;

  const submit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!rating) return setError("Choose a rating from 1 to 5 stars.");
    setBusy(true);
    setError(null);
    try {
      await submitReview({ reviewable_id: reviewableId, rating, comment: comment.trim() || undefined });
      setDone(true);
    } catch (err) {
      const r = readError(err);
      setError(r.message ?? Object.values(r.fields)[0]?.[0] ?? "Your review could not be sent.");
    } finally {
      setBusy(false);
    }
  };

  const shown = hover || rating;
  return (
    <form className="lfd-review-form" onSubmit={submit} noValidate>
      <h3 className="lfd-review-title">Write a review</h3>
      <div className="lfd-stars" role="radiogroup" aria-label="Rating" onPointerLeave={() => setHover(0)}>
        {[1, 2, 3, 4, 5].map((n) => (
          <button
            key={n}
            type="button"
            role="radio"
            aria-checked={rating === n}
            aria-label={`${n} star${n > 1 ? "s" : ""}, ${LABEL[n]}`}
            tabIndex={rating === n || (!rating && n === 1) ? 0 : -1}
            onClick={() => setRating(n)}
            onPointerEnter={(e) => e.pointerType === "mouse" && setHover(n)}
            onKeyDown={(e) => {
              const d = e.key === "ArrowRight" || e.key === "ArrowUp" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowDown" ? -1 : 0;
              if (!d) return;
              e.preventDefault();
              const next = Math.min(5, Math.max(1, (rating || n) + d));
              setRating(next);
              (e.currentTarget.parentElement?.children[next - 1] as HTMLElement | undefined)?.focus();
            }}
          >
            <Icon name="star" filled={n <= shown} />
          </button>
        ))}
        <span className="lfd-stars-label" aria-hidden="true">
          {LABEL[shown]}
        </span>
      </div>
      <label className="acct-field">
        <span className="lf-label">Your review (optional)</span>
        <textarea className="lf-input" rows={4} maxLength={2000} value={comment} onChange={(e) => setComment(e.target.value)} />
      </label>
      {error && <FormAlert>{error}</FormAlert>}
      <button type="submit" className="btn btn-rose btn-sm" disabled={busy}>
        {busy ? "Sending" : "Post review"}
      </button>
    </form>
  );
}
