"use client";

import { useEffect, useRef, useState, useTransition } from "react";
import { useRouter } from "@/i18n/navigation";
import { useSession } from "next-auth/react";
import { useTranslations } from "next-intl";
import { Building2, Check, ChevronDown, Loader2, X } from "lucide-react";
import Button from "@/components/ui/Button";
import { readApiJson, toastPromise } from "@/lib/toast";

interface StaffOption {
  userId: string;
  name: string;
  roleName: string | null;
  membershipLabel: string;
}

export default function BusinessImpersonationBanner() {
  const t = useTranslations("businesses");
  const tc = useTranslations("common");
  const { data: session, update } = useSession();
  const router = useRouter();
  const [stopping, setStopping] = useState(false);
  const [switching, setSwitching] = useState(false);
  const [staffOptions, setStaffOptions] = useState<StaffOption[]>([]);
  const [staffMenuOpen, setStaffMenuOpen] = useState(false);
  const staffMenuRef = useRef<HTMLDivElement>(null);
  const [isPending, startTransition] = useTransition();

  const user = session?.user as {
    name?: string | null;
    impersonatingBusiness?: boolean;
    businessContext?: {
      id: string;
      name: string;
      slug: string;
      staff?: { userId: string; name: string } | null;
    };
  } | undefined;

  const businessContext = user?.businessContext;

  useEffect(() => {
    if (!businessContext?.id) return;
    fetch(`/api/businesses/${businessContext.id}/impersonate-staff`)
      .then(async (res) => {
        if (!res.ok) return;
        const data = await res.json();
        setStaffOptions(data.staff ?? []);
      })
      .catch(() => setStaffOptions([]));
  }, [businessContext?.id]);

  useEffect(() => {
    if (!staffMenuOpen) return;

    const closeOnOutsideClick = (event: MouseEvent) => {
      if (!staffMenuRef.current?.contains(event.target as Node)) setStaffMenuOpen(false);
    };
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") setStaffMenuOpen(false);
    };

    document.addEventListener("mousedown", closeOnOutsideClick);
    document.addEventListener("keydown", closeOnEscape);
    return () => {
      document.removeEventListener("mousedown", closeOnOutsideClick);
      document.removeEventListener("keydown", closeOnEscape);
    };
  }, [staffMenuOpen]);

  if (!user?.impersonatingBusiness || !businessContext) return null;

  const selectedStaffId = businessContext.staff?.userId ?? "";
  const selectedStaff = staffOptions.find((member) => member.userId === selectedStaffId);
  const selectedLabel = selectedStaff
    ? `${selectedStaff.name}${selectedStaff.roleName ? ` (${selectedStaff.roleName})` : ""}`
    : t("ownerView");

  async function applyStaff(staffUserId: string) {
    if (staffUserId === selectedStaffId) return;
    setSwitching(true);
    try {
      const payload = await toastPromise(
        readApiJson(
          await fetch("/api/businesses/impersonate", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              businessId: businessContext!.id,
              staffUserId: staffUserId || null,
            }),
          }),
          tc("somethingWrong")
        ),
        { loading: t("switchingStaffView"), success: t("staffViewSwitched") }
      );
      await update({ impersonateBusiness: payload });
      startTransition(() => router.refresh());
    } catch {
      // toast
    } finally {
      setSwitching(false);
    }
  }

  async function stopBusinessImpersonation() {
    setStopping(true);
    try {
      await toastPromise(
        readApiJson(
          await fetch("/api/businesses/impersonate", { method: "DELETE" }),
          tc("somethingWrong")
        ),
        {
          loading: t("stoppingBusinessImpersonation"),
          success: t("businessImpersonationStopped"),
        }
      );
      await update({ stopBusinessImpersonate: true });
      startTransition(() => {
        router.push("/dashboard/businesses");
        router.refresh();
      });
    } catch {
      // toast
    } finally {
      setStopping(false);
    }
  }

  return (
    <div className="flex shrink-0 flex-col gap-2 border-b border-sky-500/25 bg-sky-500/10 px-4 py-2.5 sm:flex-row sm:items-center sm:justify-between sm:px-6">
      <div className="flex min-w-0 items-center gap-2.5">
        <Building2 className="h-4 w-4 shrink-0 text-sky-300" />
        <p className="truncate text-sm text-sky-100">
          {businessContext.staff
            ? t("impersonatingBusinessStaff", {
                business: businessContext.name,
                staff: businessContext.staff.name,
                actor: user.name ?? "—",
              })
            : t("impersonatingBusinessAs", {
                business: businessContext.name,
                actor: user.name ?? "—",
              })}
        </p>
      </div>

      <div className="flex flex-wrap items-center gap-2">
        <div ref={staffMenuRef} className="relative min-w-[180px] flex-1 sm:max-w-[240px]">
          {switching && (
            <Loader2 className="pointer-events-none absolute end-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 animate-spin text-sky-200" />
          )}
          <button
            type="button"
            aria-expanded={staffMenuOpen}
            aria-haspopup="listbox"
            aria-label={t("switchingStaffView")}
            onClick={() => setStaffMenuOpen((open) => !open)}
            disabled={switching || stopping || isPending}
            className="flex w-full items-center justify-between gap-2 rounded-lg border border-sky-500/30 bg-sky-950/20 py-1.5 pe-3 ps-3 text-left text-xs font-medium text-sky-100 shadow-sm transition hover:border-sky-400/50 hover:bg-sky-500/10 focus:border-sky-400/60 focus:outline-none focus:ring-2 focus:ring-sky-400/30 disabled:cursor-not-allowed disabled:opacity-60"
          >
            <span className="truncate">{selectedLabel}</span>
            <ChevronDown className={`h-4 w-4 shrink-0 transition-transform ${staffMenuOpen ? "rotate-180" : ""} ${switching ? "invisible" : ""}`} />
          </button>

          {staffMenuOpen && (
            <div
              role="listbox"
              aria-label={t("switchingStaffView")}
              className="absolute end-0 z-50 mt-1.5 max-h-64 w-full overflow-y-auto rounded-lg border border-sky-400/30 bg-[var(--bg-elevated)] p-1 shadow-[0_16px_40px_rgba(0,0,0,0.38)]"
            >
              <StaffOptionButton
                active={!selectedStaffId}
                label={t("ownerView")}
                onClick={() => {
                  setStaffMenuOpen(false);
                  void applyStaff("");
                }}
              />
              {staffOptions.map((member) => (
                <StaffOptionButton
                  key={member.userId}
                  active={member.userId === selectedStaffId}
                  label={`${member.name}${member.roleName ? ` (${member.roleName})` : ""}`}
                  detail={member.membershipLabel}
                  onClick={() => {
                    setStaffMenuOpen(false);
                    void applyStaff(member.userId);
                  }}
                />
              ))}
            </div>
          )}
        </div>

        <Button
          variant="secondary"
          size="sm"
          onClick={stopBusinessImpersonation}
          disabled={stopping || switching || isPending}
          className="shrink-0 border-sky-500/30 bg-sky-500/10 text-sky-100 hover:bg-sky-500/20"
        >
          <X className="h-3.5 w-3.5" />
          {t("stopBusinessImpersonation")}
        </Button>
      </div>
    </div>
  );
}

function StaffOptionButton({ active, label, detail, onClick }: { active: boolean; label: string; detail?: string; onClick: () => void }) {
  return (
    <button
      type="button"
      role="option"
      aria-selected={active}
      onClick={onClick}
      className={`flex w-full items-center justify-between gap-3 rounded-md px-3 py-2 text-left text-xs transition ${
        active
          ? "bg-sky-500/20 text-sky-100"
          : "text-[var(--text-muted)] hover:bg-sky-500/10 hover:text-[var(--text)]"
      }`}
    >
      <span className="min-w-0">
        <span className="block truncate font-medium">{label}</span>
        {detail && <span className="mt-0.5 block truncate text-[11px] text-[var(--text-faint)]">{detail}</span>}
      </span>
      {active && <Check className="h-3.5 w-3.5 shrink-0 text-sky-300" />}
    </button>
  );
}
