"use client";

import Link from "next/link";
import {
  useCallback,
  useEffect,
  useId,
  useRef,
  useState,
  useSyncExternalStore,
} from "react";
import { createPortal } from "react-dom";
import {
  bookingStyleReviews,
  overallRatingOutOfFive,
} from "@/lib/mocks/bookingReviews";
import { siteConfig } from "@/lib/mocks/site";

function useIsClient() {
  return useSyncExternalStore(
    () => () => {},
    () => true,
    () => false,
  );
}

type ReviewsMenuProps = { variant?: "default" | "topBar" };

export function ReviewsMenu({ variant = "default" }: ReviewsMenuProps) {
  const [open, setOpen] = useState(false);
  const isTopBar = variant === "topBar";
  const mounted = useIsClient();
  const triggerRef = useRef<HTMLButtonElement>(null);
  const panelRef = useRef<HTMLDivElement>(null);

  const close = useCallback(() => setOpen(false), []);

  useEffect(() => {
    if (!open) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const triggerEl = triggerRef.current;

    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") close();
    }
    document.addEventListener("keydown", onKey);
    queueMicrotask(() => {
      panelRef.current
        ?.querySelector<HTMLElement>("button[aria-label='Close']")
        ?.focus();
    });

    return () => {
      document.body.style.overflow = prev;
      document.removeEventListener("keydown", onKey);
      triggerEl?.focus();
    };
  }, [open, close]);

  const dialog =
    open && mounted ? (
      <div
        className="fixed inset-0 z-[100] overflow-x-hidden overflow-y-auto overscroll-contain"
        role="presentation"
      >
        <button
          type="button"
          className="fixed inset-0 bg-black/50 backdrop-blur-[2px]"
          aria-label="Close reviews dialog"
          onClick={close}
        />
        {/* min-h-full = full viewport inside fixed inset-0; items-center centers the card */}
        <div
          className="flex min-h-full w-full items-center justify-center px-4 py-6 sm:px-6 sm:py-10"
          style={{
            paddingTop: "max(1.5rem, env(safe-area-inset-top, 0px))",
            paddingBottom: "max(1.5rem, env(safe-area-inset-bottom, 0px))",
            paddingLeft: "max(1rem, env(safe-area-inset-left, 0px))",
            paddingRight: "max(1rem, env(safe-area-inset-right, 0px))",
          }}
        >
          <div
            ref={panelRef}
            role="dialog"
            aria-modal="true"
            aria-labelledby="reviews-dialog-title"
            className="relative z-10 flex min-h-0 w-full max-w-lg flex-col overflow-hidden rounded-2xl border border-[var(--color-border)] bg-[var(--color-surface)] shadow-2xl"
            style={{ maxHeight: "min(calc(100dvh - 3rem), 640px)" }}
            onClick={(e) => e.stopPropagation()}
          >
            <div className="flex shrink-0 items-start justify-between gap-3 border-b border-[var(--color-border)] px-4 py-4 sm:px-5 sm:py-4">
              <div className="min-w-0 flex-1 pr-2">
                <BookingDotLogo />
                <h2
                  id="reviews-dialog-title"
                  className="mt-3 font-heading text-lg text-[var(--color-text)] sm:text-xl"
                >
                  Guest reviews
                </h2>
                <p className="mt-1 hidden text-xs text-[var(--color-muted)] sm:block sm:text-sm">
                  Sample scores for layout — connect your live Booking.com page when ready.
                </p>
                <div className="mt-3 flex flex-wrap items-center gap-2 sm:mt-4 sm:gap-3">
                  <CircleRatingRow rating={overallRatingOutOfFive} />
                  <span className="text-base font-semibold tabular-nums text-[var(--color-text)] sm:text-lg">
                    {overallRatingOutOfFive}
                    <span className="text-xs font-normal text-[var(--color-muted)] sm:text-sm">
                      {" "}
                      / 5
                    </span>
                  </span>
                </div>
              </div>
              <button
                type="button"
                onClick={close}
                className="shrink-0 rounded-full border border-[var(--color-border)] p-2 text-[var(--color-muted)] transition hover:bg-[var(--color-surface-muted)] hover:text-[var(--color-text)]"
                aria-label="Close"
              >
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden>
                  <path
                    d="M6 6l12 12M18 6L6 18"
                    stroke="currentColor"
                    strokeWidth="2"
                    strokeLinecap="round"
                  />
                </svg>
              </button>
            </div>

            <ul className="min-h-0 flex-1 space-y-3 overflow-y-auto overscroll-contain px-4 py-3 sm:px-5 sm:py-4">
              {bookingStyleReviews.map((r) => (
                <li
                  key={r.id}
                  className="rounded-xl border border-[var(--color-border)] bg-[var(--color-bg)] p-3 text-sm"
                >
                  <div className="flex items-start justify-between gap-2">
                    <div className="min-w-0">
                      <p className="font-semibold text-[var(--color-text)]">{r.author}</p>
                      <p className="text-xs text-[var(--color-muted)]">
                        {r.country} · {r.stayDate}
                      </p>
                    </div>
                    <span className="badge-mustard shrink-0 tabular-nums">
                      {r.rating.toFixed(1)}/{r.maxRating}
                    </span>
                  </div>
                  <p className="mt-2 font-medium text-[var(--color-text)]">{r.title}</p>
                  <p className="mt-1 line-clamp-3 leading-relaxed text-[var(--color-muted)] sm:line-clamp-none">
                    {r.text}
                  </p>
                  <p className="mt-2 text-xs text-[var(--color-muted)]">Stayed in: {r.roomType}</p>
                </li>
              ))}
            </ul>

            <div className="shrink-0 border-t border-[var(--color-border)] p-4 sm:p-5">
              <Link
                href={siteConfig.bookingComReviewsUrl}
                target="_blank"
                rel="noopener noreferrer"
                className="btn-mustard flex w-full flex-col items-center justify-center gap-2 px-4 py-3 text-center text-sm sm:flex-row sm:gap-3"
                onClick={close}
              >
                <BookingDotLogo compact />
                <span>Read all reviews</span>
              </Link>
            </div>
          </div>
        </div>
      </div>
    ) : null;

  return (
    <>
      <button
        ref={triggerRef}
        type="button"
        onClick={() => setOpen(true)}
        className={
          isTopBar
            ? "flex items-center gap-2 rounded-md border border-white/20 px-2.5 py-1 text-xs font-medium text-white/95 transition hover:border-white/35 hover:bg-white/10 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white sm:gap-2 sm:px-3 sm:text-sm"
            : "flex items-center gap-1.5 rounded-full border border-transparent px-2 py-2 text-sm font-medium text-[var(--color-text)] transition hover:border-[var(--color-border)] hover:bg-[var(--color-surface-muted)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary)] sm:gap-2 sm:px-3"
        }
        aria-haspopup="dialog"
        aria-expanded={open}
        aria-label={`Guest reviews, ${overallRatingOutOfFive} out of 5`}
      >
        <span className={isTopBar ? "inline" : "hidden sm:inline"}>Reviews</span>
        <span
          className={
            isTopBar
              ? "badge-mustard flex items-center gap-1 px-2 py-0.5"
              : "badge-mustard flex items-center gap-1 px-2 py-1 sm:py-0.5"
          }
        >
          <span>{overallRatingOutOfFive}</span>
          <span className={isTopBar ? "inline" : "hidden sm:inline"}>
            <CircleRatingMini rating={overallRatingOutOfFive} />
          </span>
        </span>
      </button>

      {mounted && dialog ? createPortal(dialog, document.body) : null}
    </>
  );
}

/** Booking.com–style wordmark: “Booking” + yellow dot + “.com” */
function BookingDotLogo({
  className = "",
  compact = false,
}: {
  className?: string;
  compact?: boolean;
}) {
  if (compact) {
    return (
      <span
        className={`inline-flex items-center gap-0.5 font-bold tracking-tight text-white ${className}`}
      >
        <span className="text-[15px]">Booking</span>
        <span
          className="mx-px inline-block h-2 w-2 shrink-0 rounded-full bg-[#febb02]"
          aria-hidden
        />
        <span className="text-[15px]">.com</span>
      </span>
    );
  }
  return (
    <div className={`inline-flex items-baseline gap-0 ${className}`}>
      <span className="text-xl font-bold tracking-tight text-[var(--color-primary)] sm:text-2xl">Booking</span>
      <span
        className="mx-0.5 inline-block h-2 w-2 shrink-0 translate-y-0.5 rounded-full bg-[#febb02] sm:h-2.5 sm:w-2.5"
        aria-hidden
      />
      <span className="text-xl font-bold tracking-tight text-[var(--color-primary)] sm:text-2xl">.com</span>
    </div>
  );
}

/** Five circles: filled amount per position = min(1, max(0, rating - i)) */
function CircleRatingRow({ rating, max = 5 }: { rating: number; max?: number }) {
  const uid = useId().replace(/:/g, "");
  const size = 26;
  const vb = 24;
  const cx = 12;
  const cy = 12;
  const r = 8;
  const stroke = "#d6d3d1";

  return (
    <div className="flex flex-wrap items-center gap-1 sm:gap-1.5" aria-label={`${rating} out of ${max}`}>
      {Array.from({ length: max }, (_, i) => {
        const fill = Math.min(1, Math.max(0, rating - i));
        const clipW = vb * fill;
        const clipId = `${uid}-clip-${i}`;
        return (
          <svg
            key={i}
            width={size}
            height={size}
            viewBox={`0 0 ${vb} ${vb}`}
            className="shrink-0"
            aria-hidden
          >
            <circle cx={cx} cy={cy} r={r} fill="none" stroke={stroke} strokeWidth="1.75" />
            {fill > 0 ? (
              <>
                <defs>
                  <clipPath id={clipId}>
                    <rect x="0" y="0" width={clipW} height={vb} />
                  </clipPath>
                </defs>
                <circle
                  cx={cx}
                  cy={cy}
                  r={r}
                  fill="#febb02"
                  clipPath={`url(#${clipId})`}
                />
              </>
            ) : null}
          </svg>
        );
      })}
    </div>
  );
}

function CircleRatingMini({ rating }: { rating: number }) {
  const uid = useId().replace(/:/g, "");
  const max = 5;
  const vb = 24;
  const cx = 12;
  const cy = 12;
  const r = 7;

  return (
    <span className="inline-flex items-center gap-px" aria-hidden>
      {Array.from({ length: max }, (_, i) => {
        const fill = Math.min(1, Math.max(0, rating - i));
        const clipW = vb * fill;
        const clipId = `${uid}-m-${i}`;
        return (
          <svg key={i} width="10" height="10" viewBox={`0 0 ${vb} ${vb}`} className="shrink-0">
            <circle cx={cx} cy={cy} r={r} fill="none" stroke="rgba(255,255,255,0.45)" strokeWidth="2" />
            {fill > 0 ? (
              <>
                <defs>
                  <clipPath id={clipId}>
                    <rect x="0" y="0" width={clipW} height={vb} />
                  </clipPath>
                </defs>
                <circle cx={cx} cy={cy} r={r} fill="#febb02" clipPath={`url(#${clipId})`} />
              </>
            ) : null}
          </svg>
        );
      })}
    </span>
  );
}
