"use client";

import React, { useEffect, useRef, useState } from "react";
import { m } from "framer-motion";
import Select from "react-select";
import {
  Building2,
  Loader2,
  MapPin,
  Pencil,
  Plus,
  Search,
  Smartphone,
  Trash2,
  UserCheck,
  Users,
  X,
  XCircle,
} from "lucide-react";
import { Container } from "@/components/common/Container";
import { Button } from "@/components/common/Button";
import { SEARCHABLE_SELECT_COMPONENTS } from "@/components/common/SearchableSelectParts";
import { useControlledSelectMenu } from "@/hooks/useControlledSelectMenu";
import { AgentRecipientsSkeleton } from "@/components/skeletons/AgentRecipientsSkeleton";
import {
  useAgentRecipients,
  useAgentRecipientBasicData,
  useAgentRecipientDetail,
  useAgentRecipientBankList,
  useAgentRecipientMobileMethodList,
  useAgentRecipientPickupPointList,
  useAgentCreateRecipient,
  useAgentUpdateRecipient,
  useAgentDeleteRecipient,
  useAgentCheckRecipientUser,
  type RecipientListItem,
} from "@/hooks/queries/useAgentRecipient";
import { notify } from "@/lib/notify";
import { cn } from "@/lib/utils";
import { useTranslation } from "@/hooks/useTranslation";

// ─── Shared styles ─────────────────────────────────────────────────────────────

const INPUT =
  "h-10 w-full rounded-xl border border-slate-200 bg-white px-3.5 text-sm outline-none transition focus:border-brand-400 dark:border-slate-700 dark:bg-slate-800/60 dark:text-white";
const LABEL = "text-[length:var(--text-sm-fixed)] font-medium text-slate-600 dark:text-slate-300";

// Menu attaches flush to the control (no gap, square-off shared corners) so
// opening reads as the control expanding downward rather than a floating menu.
function selectCls(extra?: string) {
  return {
    control: ({ menuIsOpen }: { menuIsOpen: boolean }) =>
      cn(
        "flex h-10 w-full cursor-pointer items-center border border-slate-200 bg-white px-3.5 text-sm transition-[border-radius] duration-150 dark:border-slate-700 dark:bg-slate-800/60 dark:text-white",
        menuIsOpen ? "rounded-t-xl rounded-b-none" : "rounded-xl",
        extra,
      ),
    menu: () =>
      "select-menu-portal overflow-hidden rounded-b-xl border border-t-0 border-slate-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-800 z-50",
    menuList: () => "max-h-52 overflow-y-auto",
    option: ({ isFocused }: { isFocused: boolean }) =>
      cn(
        "px-3.5 py-2 text-sm cursor-pointer",
        isFocused
          ? "bg-brand-50 text-brand-700 dark:bg-brand-500/10 dark:text-brand-300"
          : "text-slate-700 dark:text-slate-200",
      ),
    placeholder: () => "text-slate-400 text-sm",
    singleValue: () => "text-sm text-slate-800 dark:text-slate-200",
    noOptionsMessage: () => "px-3.5 py-3 text-sm text-slate-400",
  };
}

// ─── Method badge ──────────────────────────────────────────────────────────────

const METHOD_STYLES: Record<string, { cls: string; icon: React.ReactNode }> = {
  "Bank Transfer": {
    cls: "bg-brand-50 text-brand-700 dark:bg-brand-500/10 dark:text-brand-300",
    icon: <Building2 className="icon-xs" />,
  },
  "Mobile Money": {
    cls: "bg-emerald-50 text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-300",
    icon: <Smartphone className="icon-xs" />,
  },
  "Cash Pickup": {
    cls: "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300",
    icon: <UserCheck className="icon-xs" />,
  },
};

function translateMethodName(m: string, t: (k: string) => string): string {
  if (m === "All") return t("agent.recipients.filterAll");
  if (m === "Bank Transfer") return t("agent.recipients.methodBankTransfer");
  if (m === "Mobile Money") return t("agent.recipients.methodMobileMoney");
  if (m === "Cash Pickup") return t("agent.recipients.methodCashPickup");
  return m;
}

function MethodBadge({ method }: { method: string }) {
  const { t } = useTranslation();
  const style = METHOD_STYLES[method] ?? {
    cls: "bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400",
    icon: null,
  };
  return (
    <span className={cn("badge gap-1 text-[length:var(--text-sm-fixed)] font-medium", style.cls)}>
      {style.icon}
      {translateMethodName(method, t)}
    </span>
  );
}

// ─── Modal ─────────────────────────────────────────────────────────────────────

function Modal({
  open,
  onClose,
  children,
}: {
  open: boolean;
  onClose: () => void;
  children: React.ReactNode;
}) {
  // Keep mounted through the close transition, then fully unmount — any
  // react-select menu portalled to document.body must be torn down with it,
  // or it's left floating over whatever page follows.
  const [shouldRender, setShouldRender] = useState(open);

  useEffect(() => {
    if (open) { setShouldRender(true); return; }
    const timeout = setTimeout(() => setShouldRender(false), 200);
    return () => clearTimeout(timeout);
  }, [open]);

  useEffect(() => {
    if (!open) return;
    const h = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", h);
    return () => document.removeEventListener("keydown", h);
  }, [open, onClose]);

  if (!shouldRender) return null;

  return (
    <>
      <div
        className={cn(
          "fixed inset-0 z-[80] bg-slate-900/50 backdrop-blur-sm transition-opacity duration-200 dark:bg-black/70",
          open ? "opacity-100" : "pointer-events-none opacity-0",
        )}
        onMouseDown={onClose}
      />
      <div
        className={cn(
          "fixed inset-0 z-[90] flex items-center justify-center p-4 transition-all duration-200",
          open ? "opacity-100" : "pointer-events-none opacity-0",
        )}
      >
        <div
          className={cn(
            "flex max-h-[92vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-900/5 transition-all duration-200 dark:bg-slate-900 dark:ring-white/10",
            open ? "scale-100 translate-y-0" : "scale-95 translate-y-4",
          )}
        >
          {children}
        </div>
      </div>
    </>
  );
}

// ─── Form state ────────────────────────────────────────────────────────────────

type RecipientForm = {
  first_name: string;
  last_name: string;
  email: string;
  phone: string;
  country: string;
  state: string;
  city: string;
  zip_code: string;
  address: string;
  method: string;
  bank_name: string;
  iban_number: string;
  mobile_name: string;
  account_number: string;
  pickup_point: string;
};

const EMPTY: RecipientForm = {
  first_name: "", last_name: "", email: "", phone: "",
  country: "", state: "", city: "", zip_code: "", address: "",
  method: "", bank_name: "", iban_number: "",
  mobile_name: "", account_number: "", pickup_point: "",
};

// ─── Recipient form modal ──────────────────────────────────────────────────────

function RecipientFormModal({
  open,
  editSlug,
  onClose,
  countries,
  methods,
}: {
  open: boolean;
  editSlug: string | null;
  onClose: () => void;
  countries: string[];
  methods: string[];
}) {
  const { t } = useTranslation();
  const isEdit = !!editSlug;
  const [form, setForm] = useState<RecipientForm>(EMPTY);
  const [emailQuery, setEmailQuery] = useState("");
  const [checkError, setCheckError] = useState<string | null>(null);
  const [countrySearch, setCountrySearch] = useState("");
  const countryRef = useRef<HTMLDivElement>(null);
  const countryMenu = useControlledSelectMenu(countryRef, "select-menu-portal");
  const [methodSearch, setMethodSearch] = useState("");
  const methodRef = useRef<HTMLDivElement>(null);
  const methodMenu = useControlledSelectMenu(methodRef, "select-menu-portal");
  const [bankSearch, setBankSearch] = useState("");
  const bankRef = useRef<HTMLDivElement>(null);
  const bankMenu = useControlledSelectMenu(bankRef, "select-menu-portal");
  const [mobileSearch, setMobileSearch] = useState("");
  const mobileRef = useRef<HTMLDivElement>(null);
  const mobileMenu = useControlledSelectMenu(mobileRef, "select-menu-portal");
  const [pickupSearch, setPickupSearch] = useState("");
  const pickupRef = useRef<HTMLDivElement>(null);
  const pickupMenu = useControlledSelectMenu(pickupRef, "select-menu-portal");

  // Country select's menu is portalled to document.body, so closing the modal
  // can't hide it via CSS — force it shut before closing.
  function handleClose() {
    countryMenu.onMenuClose();
    onClose();
  }

  const { data: detail, isLoading: loadingDetail } = useAgentRecipientDetail(editSlug ?? "");
  const { data: banks = [], isFetching: fetchingBanks } = useAgentRecipientBankList(
    form.method === "Bank Transfer" ? form.country : "",
  );
  const { data: mobileMethods = [], isFetching: fetchingMobile } = useAgentRecipientMobileMethodList(
    form.method === "Mobile Money" ? form.country : "",
  );
  const { data: pickupPoints = [], isFetching: fetchingPickup } = useAgentRecipientPickupPointList(
    form.method === "Cash Pickup" ? form.country : "",
  );

  const { mutate: checkUser, isPending: checking } = useAgentCheckRecipientUser();
  const { mutate: create, isPending: creating } = useAgentCreateRecipient();
  const { mutate: update, isPending: updating } = useAgentUpdateRecipient();
  const isPending = creating || updating;

  useEffect(() => {
    if (isEdit && detail) {
      setForm({
        first_name: detail.first_name ?? "",
        last_name: detail.last_name ?? "",
        email: detail.email ?? "",
        phone: detail.phone ?? "",
        country: detail.country ?? "",
        state: detail.state ?? "",
        city: detail.city ?? "",
        zip_code: detail.zip_code ?? "",
        address: detail.address ?? "",
        method: detail.method ?? "",
        bank_name: detail.bank_name ?? "",
        iban_number: detail.iban_number ?? "",
        mobile_name: detail.mobile_name ?? "",
        account_number: detail.account_number ?? "",
        pickup_point: detail.pickup_point ?? "",
      });
    } else if (!isEdit) {
      setForm(EMPTY);
      setEmailQuery("");
      setCheckError(null);
    }
  }, [isEdit, detail, open]);

  function patch(field: keyof RecipientForm) {
    return (e: React.ChangeEvent<HTMLInputElement>) =>
      setForm((p) => ({ ...p, [field]: e.target.value }));
  }

  function handleCheckUser() {
    if (!emailQuery.trim()) return;
    setCheckError(null);
    checkUser(emailQuery.trim(), {
      onSuccess: (u) => {
        setForm((p) => ({
          ...p,
          first_name: u.first_name,
          last_name: u.last_name,
          email: u.email,
          phone: u.phone,
          country: u.country,
          state: u.state,
          city: u.city,
          zip_code: u.zip_code,
        }));
        notify(t("agent.recipients.autoFilled"), "success");
      },
      onError: (err: Error) => setCheckError(err.message || t("agent.recipients.userNotFound")),
    });
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    const input = {
      method: form.method,
      country: form.country,
      first_name: form.first_name,
      last_name: form.last_name,
      phone: form.phone,
      ...(form.email ? { email: form.email } : {}),
      ...(form.state ? { state: form.state } : {}),
      ...(form.city ? { city: form.city } : {}),
      ...(form.zip_code ? { zip_code: form.zip_code } : {}),
      ...(form.address ? { address: form.address } : {}),
      ...(form.method === "Bank Transfer"
        ? { bank_name: form.bank_name, iban_number: form.iban_number }
        : {}),
      ...(form.method === "Mobile Money"
        ? { mobile_name: form.mobile_name, account_number: form.account_number }
        : {}),
      ...(form.method === "Cash Pickup" ? { pickup_point: form.pickup_point } : {}),
    };

    if (isEdit && editSlug) {
      update(
        { slug: editSlug, input },
        {
          onSuccess: () => { notify(t("agent.recipients.updated"), "success"); handleClose(); },
          onError: (err: Error) => notify(err.message || t("agent.recipients.updateFailed"), "error"),
        },
      );
    } else {
      create(input, {
        onSuccess: () => { notify(t("agent.recipients.added"), "success"); handleClose(); },
        onError: (err: Error) => notify(err.message || t("agent.recipients.addFailed"), "error"),
      });
    }
  }

  const countryOptions = countries.map((c) => ({ value: c, label: c }));
  const methodOptions = methods.map((m) => ({ value: m, label: translateMethodName(m, t) }));
  const bankOptions = banks.map((b) => ({ value: b.name, label: b.name }));
  const mobileOptions = mobileMethods.map((m) => ({ value: m.name, label: m.name }));
  const pickupOptions = pickupPoints.map((p) => ({ value: p.address, label: p.address }));

  return (
    <Modal open={open} onClose={handleClose}>
      {/* Header */}
      <div className="flex items-center justify-between border-b border-slate-200 px-6 py-4 dark:border-slate-800">
        <h2 className="text-[length:var(--text-lg-fixed)] font-bold text-slate-900 dark:text-white">
          {isEdit ? t("agent.recipients.editModal") : t("agent.recipients.addModal")}
        </h2>
        <button
          type="button"
          onMouseDown={handleClose}
          className="btn-icon-sm text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:hover:bg-slate-800 dark:hover:text-slate-200"
        >
          <X className="icon-md" />
        </button>
      </div>

      {/* Body */}
      <div className="flex-1 overflow-y-auto px-6 py-5">
        {isEdit && loadingDetail ? (
          <div className="flex h-40 items-center justify-center">
            <Loader2 className="h-6 w-6 animate-spin text-slate-400" />
          </div>
        ) : (
          <form id="recipient-form" onSubmit={handleSubmit} className="space-y-6">
            {/* Email lookup (add mode) */}
            {!isEdit && (
              <div className="rounded-xl border border-brand-200/60 bg-brand-50/50 p-4 dark:border-brand-500/20 dark:bg-brand-500/5">
                <p className="mb-2.5 text-[length:var(--text-sm-fixed)] font-medium text-brand-700 dark:text-brand-300">
                  {t("agent.recipients.lookupLabel")}
                </p>
                <div className="flex gap-2">
                  <input
                    type="email"
                    value={emailQuery}
                    onChange={(e) => { setEmailQuery(e.target.value); setCheckError(null); }}
                    placeholder={t("agent.recipients.emailPlaceholder")}
                    className={cn(INPUT, "flex-1", checkError ? "border-rose-400" : "")}
                  />
                  <Button
                    type="button"
                    size="sm"
                    onClick={handleCheckUser}
                    disabled={!emailQuery.trim()}
                    loading={checking}
                  >
                    {!checking && <Search className="icon-sm" />}
                    {t("agent.recipients.find")}
                  </Button>
                </div>
                {checkError && (
                  <p className="mt-1.5 flex items-center gap-1 text-xs font-medium text-rose-600 dark:text-rose-400">
                    <XCircle className="icon-sm shrink-0" />
                    {checkError}
                  </p>
                )}
              </div>
            )}

            {/* Name */}
            <div className="grid grid-cols-2 gap-3">
              <div className="flex flex-col gap-1.5">
                <label className={LABEL}>{t("agent.recipients.firstNameLabel")} <span className="text-rose-500">*</span></label>
                <input type="text" value={form.first_name} onChange={patch("first_name")} placeholder={t("agent.recipients.firstNamePlaceholder")} required className={INPUT} />
              </div>
              <div className="flex flex-col gap-1.5">
                <label className={LABEL}>{t("agent.recipients.lastNameLabel")} <span className="text-rose-500">*</span></label>
                <input type="text" value={form.last_name} onChange={patch("last_name")} placeholder={t("agent.recipients.lastNamePlaceholder")} required className={INPUT} />
              </div>
            </div>

            <div className="flex flex-col gap-1.5">
              <label className={LABEL}>{t("agent.recipients.emailLabel")}</label>
              <input type="email" value={form.email} onChange={patch("email")} placeholder={t("agent.recipients.emailPlaceholder")} className={INPUT} />
            </div>

            <div className="flex flex-col gap-1.5">
              <label className={LABEL}>{t("agent.recipients.phoneLabel")} <span className="text-rose-500">*</span></label>
              <input type="tel" value={form.phone} onChange={patch("phone")} placeholder={t("agent.recipients.phonePlaceholder")} required className={INPUT} />
            </div>

            {/* Country */}
            <div className="flex flex-col gap-1.5">
              <label className={LABEL}>{t("agent.recipients.countryLabel")} <span className="text-rose-500">*</span></label>
              <div ref={countryRef}>
                <Select
                  unstyled
                  isSearchable
                  menuIsOpen={countryMenu.menuIsOpen}
                  onMenuOpen={countryMenu.onMenuOpen}
                  inputValue={countrySearch}
                  onInputChange={(val, { action }) => { if (action === "input-change") setCountrySearch(val); }}
                  onMenuClose={() => { countryMenu.onMenuClose(); setCountrySearch(""); }}
                  components={SEARCHABLE_SELECT_COMPONENTS}
                  menuPortalTarget={typeof document !== "undefined" ? document.body : undefined}
                  menuPosition="fixed"
                  styles={{ menuPortal: (base) => ({ ...base, zIndex: 9999 }) }}
                  options={countryOptions}
                  value={form.country ? { value: form.country, label: form.country } : null}
                  onChange={(opt) => setForm((p) => ({ ...p, country: opt?.value ?? "", bank_name: "", mobile_name: "", pickup_point: "" }))}
                  placeholder={t("agent.recipients.countryPlaceholder")}
                  classNames={selectCls()}
                />
              </div>
            </div>

            {/* State / City / Zip */}
            <div className="grid grid-cols-3 gap-3">
              <div className="flex flex-col gap-1.5">
                <label className={LABEL}>{t("agent.recipients.stateLabel")}</label>
                <input type="text" value={form.state} onChange={patch("state")} placeholder={t("agent.recipients.statePlaceholder")} className={INPUT} />
              </div>
              <div className="flex flex-col gap-1.5">
                <label className={LABEL}>{t("agent.recipients.cityLabel")}</label>
                <input type="text" value={form.city} onChange={patch("city")} placeholder={t("agent.recipients.cityPlaceholder")} className={INPUT} />
              </div>
              <div className="flex flex-col gap-1.5">
                <label className={LABEL}>{t("agent.recipients.zipLabel")}</label>
                <input type="text" value={form.zip_code} onChange={patch("zip_code")} placeholder={t("agent.recipients.zipPlaceholder")} className={INPUT} />
              </div>
            </div>

            <div className="flex flex-col gap-1.5">
              <label className={LABEL}>{t("agent.recipients.addressLabel")}</label>
              <input type="text" value={form.address} onChange={patch("address")} placeholder={t("agent.recipients.addressPlaceholder")} className={INPUT} />
            </div>

            {/* Method */}
            <div className="flex flex-col gap-1.5">
              <label className={LABEL}>{t("agent.recipients.methodLabel")} <span className="text-rose-500">*</span></label>
              <div ref={methodRef}>
                <Select
                  unstyled
                  isSearchable
                  menuIsOpen={methodMenu.menuIsOpen}
                  onMenuOpen={methodMenu.onMenuOpen}
                  inputValue={methodSearch}
                  onInputChange={(val, { action }) => { if (action === "input-change") setMethodSearch(val); }}
                  onMenuClose={() => { methodMenu.onMenuClose(); setMethodSearch(""); }}
                  components={SEARCHABLE_SELECT_COMPONENTS}
                  options={methodOptions}
                  value={form.method ? { value: form.method, label: form.method } : null}
                  onChange={(opt) => setForm((p) => ({ ...p, method: opt?.value ?? "", bank_name: "", iban_number: "", mobile_name: "", account_number: "", pickup_point: "" }))}
                  placeholder={t("agent.recipients.methodPlaceholder")}
                  classNames={selectCls()}
                />
              </div>
            </div>

            {/* Method-specific fields */}
            {form.method === "Bank Transfer" && (
              <div className="space-y-6 rounded-xl border border-brand-100 bg-brand-50/30 p-4 dark:border-brand-500/10 dark:bg-brand-500/5">
                <div className="flex flex-col gap-1.5">
                  <label className={LABEL}>
                    {t("agent.recipients.bankNameLabel")} <span className="text-rose-500">*</span>
                    {fetchingBanks && <Loader2 className="ms-1 inline h-3 w-3 animate-spin" />}
                  </label>
                  <div ref={bankRef}>
                    <Select
                      unstyled
                      isSearchable
                      menuIsOpen={bankMenu.menuIsOpen}
                      onMenuOpen={bankMenu.onMenuOpen}
                      inputValue={bankSearch}
                      onInputChange={(val, { action }) => { if (action === "input-change") setBankSearch(val); }}
                      onMenuClose={() => { bankMenu.onMenuClose(); setBankSearch(""); }}
                      components={SEARCHABLE_SELECT_COMPONENTS}
                      options={bankOptions}
                      value={form.bank_name ? { value: form.bank_name, label: form.bank_name } : null}
                      onChange={(opt) => setForm((p) => ({ ...p, bank_name: opt?.value ?? "" }))}
                      placeholder={form.country ? t("agent.recipients.bankPlaceholder") : t("agent.recipients.countryFirstPlaceholder")}
                      isDisabled={!form.country}
                      classNames={selectCls()}
                    />
                  </div>
                </div>
                <div className="flex flex-col gap-1.5">
                  <label className={LABEL}>{t("agent.recipients.ibanLabel")} <span className="text-rose-500">*</span></label>
                  <input type="text" placeholder="Enter IBAN number" value={form.iban_number} onChange={patch("iban_number")} className={INPUT} />
                </div>
              </div>
            )}

            {form.method === "Mobile Money" && (
              <div className="space-y-6 rounded-xl border border-emerald-100 bg-emerald-50/30 p-4 dark:border-emerald-500/10 dark:bg-emerald-500/5">
                <div className="flex flex-col gap-1.5">
                  <label className={LABEL}>
                    {t("agent.recipients.mobileProviderLabel")} <span className="text-rose-500">*</span>
                    {fetchingMobile && <Loader2 className="ms-1 inline h-3 w-3 animate-spin" />}
                  </label>
                  <div ref={mobileRef}>
                    <Select
                      unstyled
                      isSearchable
                      menuIsOpen={mobileMenu.menuIsOpen}
                      onMenuOpen={mobileMenu.onMenuOpen}
                      inputValue={mobileSearch}
                      onInputChange={(val, { action }) => { if (action === "input-change") setMobileSearch(val); }}
                      onMenuClose={() => { mobileMenu.onMenuClose(); setMobileSearch(""); }}
                      components={SEARCHABLE_SELECT_COMPONENTS}
                      options={mobileOptions}
                      value={form.mobile_name ? { value: form.mobile_name, label: form.mobile_name } : null}
                      onChange={(opt) => setForm((p) => ({ ...p, mobile_name: opt?.value ?? "" }))}
                      placeholder={form.country ? t("agent.recipients.providerPlaceholder") : t("agent.recipients.countryFirstPlaceholder")}
                      isDisabled={!form.country}
                      classNames={selectCls()}
                    />
                  </div>
                </div>
                <div className="flex flex-col gap-1.5">
                  <label className={LABEL}>{t("agent.recipients.accountNumberLabel")} <span className="text-rose-500">*</span></label>
                  <input type="text" placeholder="Enter account number" value={form.account_number} onChange={patch("account_number")} className={INPUT} />
                </div>
              </div>
            )}

            {form.method === "Cash Pickup" && (
              <div className="space-y-6 rounded-xl border border-amber-100 bg-amber-50/30 p-4 dark:border-amber-500/10 dark:bg-amber-500/5">
                <div className="flex flex-col gap-1.5">
                  <label className={LABEL}>
                    {t("agent.recipients.pickupPointLabel")} <span className="text-rose-500">*</span>
                    {fetchingPickup && <Loader2 className="ms-1 inline h-3 w-3 animate-spin" />}
                  </label>
                  <div ref={pickupRef}>
                    <Select
                      unstyled
                      isSearchable
                      menuIsOpen={pickupMenu.menuIsOpen}
                      onMenuOpen={pickupMenu.onMenuOpen}
                      inputValue={pickupSearch}
                      onInputChange={(val, { action }) => { if (action === "input-change") setPickupSearch(val); }}
                      onMenuClose={() => { pickupMenu.onMenuClose(); setPickupSearch(""); }}
                      components={SEARCHABLE_SELECT_COMPONENTS}
                      options={pickupOptions}
                      value={form.pickup_point ? { value: form.pickup_point, label: form.pickup_point } : null}
                      onChange={(opt) => setForm((p) => ({ ...p, pickup_point: opt?.value ?? "" }))}
                      placeholder={form.country ? t("agent.recipients.pickupPlaceholder") : t("agent.recipients.countryFirstPlaceholder")}
                      isDisabled={!form.country}
                      classNames={selectCls()}
                    />
                  </div>
                </div>
              </div>
            )}
          </form>
        )}
      </div>

      {/* Footer */}
      <div className="border-t border-slate-200 px-6 py-4 dark:border-slate-800">
        <div className="flex gap-3">
          <Button type="submit" form="recipient-form" size="md" disabled={isPending} className="flex-1">
            {isPending
              ? isEdit ? t("agent.recipients.saving") : t("agent.recipients.adding")
              : isEdit ? t("agent.recipients.saveChanges") : t("agent.recipients.addRecipientSubmit")}
          </Button>
          <Button
            size="md"
            onMouseDown={handleClose}
            className="border-slate-200 bg-white text-slate-700 hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200"
          >
            {t("agent.recipients.cancel")}
          </Button>
        </div>
      </div>
    </Modal>
  );
}

// ─── Recipient row ─────────────────────────────────────────────────────────────

function RecipientRow({
  recipient,
  onEdit,
  index,
}: {
  recipient: RecipientListItem;
  onEdit: () => void;
  index: number;
}) {
  const { t } = useTranslation();
  const [confirming, setConfirming] = useState(false);
  const { mutate: remove, isPending } = useAgentDeleteRecipient();

  const initials =
    recipient.full_name
      .split(" ")
      .map((p) => p.charAt(0))
      .slice(0, 2)
      .join("")
      .toUpperCase() || "?";

  function handleDelete() {
    remove(recipient.slug, {
      onSuccess: () => { notify(t("agent.recipients.removed"), "success"); setConfirming(false); },
      onError: (err: Error) => notify(err.message || t("agent.recipients.deleteFailed"), "error"),
    });
  }

  const paymentDetail =
    recipient.method === "Bank Transfer"
      ? recipient.bank_name ?? "—"
      : recipient.method === "Mobile Money"
        ? recipient.mobile_name ?? "—"
        : recipient.pickup_point ?? "—";

  const paymentId =
    recipient.method === "Bank Transfer"
      ? recipient.iban_number
      : recipient.method === "Mobile Money"
        ? recipient.account_number
        : null;

  const paymentLabel =
    recipient.method === "Bank Transfer" ? t("agent.recipients.bankLabel") :
    recipient.method === "Mobile Money" ? t("agent.recipients.providerLabel") : t("agent.recipients.pickupLabel");

  if (confirming) {
    return (
      <m.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        className="flex items-center justify-between gap-4 px-6 py-4 bg-rose-50/60 dark:bg-rose-500/5"
      >
        <p className="text-sm font-medium text-slate-700 dark:text-slate-200">
          {t("agent.recipients.confirmDelete").replace("{name}", recipient.full_name)}
        </p>
        <div className="flex shrink-0 gap-2">
          <Button
            type="button"
            size="sm"
            variant="destructive"
            loading={isPending}
            onClick={handleDelete}
          >
            {!isPending && <Trash2 className="icon-sm" />}
            {t("agent.recipients.confirmBtn")}
          </Button>
          <Button
            type="button"
            size="sm"
            variant="outline"
            onClick={() => setConfirming(false)}
          >
            {t("agent.recipients.cancel")}
          </Button>
        </div>
      </m.div>
    );
  }

  return (
    <m.div
      initial={{ opacity: 0, y: 6 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ delay: index * 0.03, type: "spring", stiffness: 300, damping: 26 }}
      className={cn(
        "group flex items-center gap-4 px-6 py-4 transition-colors hover:bg-brand-50/40 dark:hover:bg-brand-500/5 sm:grid sm:grid-cols-[2.25rem_1fr_1fr_4rem] xl:grid-cols-[2.25rem_1fr_1fr_1fr_1fr_1fr_4rem] sm:px-7",
        index % 2 === 0
          ? "bg-white dark:bg-transparent"
          : "bg-slate-50/60 dark:bg-slate-800/20",
      )}
    >
      {/* Avatar */}
      <span className="grid h-9 w-9 shrink-0 place-items-center rounded-full bg-gradient-to-br from-brand-500 to-accent-500 text-sm font-bold text-white">
        {initials}
      </span>

      {/* Name + email */}
      <div className="min-w-0 flex-1">
        <p className="truncate text-sm font-semibold text-slate-900 dark:text-white">
          {recipient.full_name}
        </p>
        <p className="truncate text-xs text-slate-400">{recipient.email || "—"}</p>
      </div>

      {/* Phone */}
      <div className="hidden xl:flex items-center gap-2">
        <Smartphone className="h-3.5 w-3.5 shrink-0 text-slate-400" />
        <p className="truncate text-sm text-slate-700 dark:text-slate-200">{recipient.phone || "—"}</p>
      </div>

      {/* Country */}
      <div className="hidden xl:flex items-center gap-2">
        <MapPin className="h-3.5 w-3.5 shrink-0 text-slate-400" />
        <p className="truncate text-sm text-slate-700 dark:text-slate-200">{recipient.country || "—"}</p>
      </div>

      {/* Method */}
      <div className="hidden sm:block">
        <MethodBadge method={recipient.method} />
      </div>

      {/* Payment detail */}
      <div className="hidden xl:block">
        <p className="text-sm font-medium capitalize text-slate-400">
          {paymentLabel}
        </p>
        <p className="truncate text-sm font-medium text-slate-700 dark:text-slate-200">
          {paymentDetail}
        </p>
        {paymentId && (
          <p className="truncate text-xs tabular-nums text-slate-400">{paymentId}</p>
        )}
      </div>

      {/* Actions */}
      <div className="flex shrink-0 items-center gap-1.5 opacity-0 transition-all group-hover:opacity-100 sm:opacity-60 sm:group-hover:opacity-100">
        <button
          type="button"
          onClick={onEdit}
          className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-brand-200 bg-brand-50 text-brand-600 shadow-sm transition-all hover:-translate-y-0.5 hover:border-brand-300 hover:bg-brand-100 hover:shadow-md active:translate-y-0 dark:border-brand-500/30 dark:bg-brand-500/10 dark:text-brand-400 dark:hover:bg-brand-500/20"
          aria-label="Edit recipient"
        >
          <Pencil className="icon-sm" />
        </button>
        <button
          type="button"
          onClick={() => setConfirming(true)}
          className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-rose-200 bg-rose-50 text-rose-600 shadow-sm transition-all hover:-translate-y-0.5 hover:border-rose-300 hover:bg-rose-100 hover:shadow-md active:translate-y-0 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-400 dark:hover:bg-rose-500/20"
          aria-label="Delete recipient"
        >
          <Trash2 className="icon-sm" />
        </button>
      </div>
    </m.div>
  );
}

// ─── Main view ─────────────────────────────────────────────────────────────────

export function AgentRecipientsView() {
  const { t } = useTranslation();
  const { data, isLoading, isError } = useAgentRecipients();
  const { data: basicData } = useAgentRecipientBasicData();
  const [search, setSearch] = useState("");
  const [methodFilter, setMethodFilter] = useState("All");
  const [modalOpen, setModalOpen] = useState(false);
  const [editSlug, setEditSlug] = useState<string | null>(null);

  const recipients = data ?? [];
  const countries = (basicData?.receiver_country ?? []).map((c) => c.country);
  const methods = basicData?.method_list ?? [];

  const filtered = recipients.filter((r) => {
    const q = search.toLowerCase();
    const matchSearch =
      !q ||
      r.full_name.toLowerCase().includes(q) ||
      r.email.toLowerCase().includes(q) ||
      r.country.toLowerCase().includes(q);
    const matchMethod = methodFilter === "All" || r.method === methodFilter;
    return matchSearch && matchMethod;
  });

  function openAdd() { setEditSlug(null); setModalOpen(true); }
  function openEdit(slug: string) { setEditSlug(slug); setModalOpen(true); }
  function closeModal() { setModalOpen(false); setEditSlug(null); }

  const allMethods = ["All", ...methods];

  if (isLoading) return <AgentRecipientsSkeleton />;

  if (isError) {
    return (
      <Container className="max-w-full pb-10">
        <div className="flex flex-col items-center gap-4 rounded-3xl border border-rose-200 bg-rose-50 p-16 text-center dark:border-rose-500/20 dark:bg-rose-500/10">
          <XCircle className="h-10 w-10 text-rose-500" />
          <p className="font-semibold text-slate-900 dark:text-white">{t("agent.recipients.failedToLoad")}</p>
        </div>
      </Container>
    );
  }

  const containerVariants = {
    hidden: { opacity: 0 },
    visible: { opacity: 1, transition: { staggerChildren: 0.08, delayChildren: 0.05 } },
  };
  const itemVariants = {
    hidden: { opacity: 0, y: 15 },
    visible: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 300, damping: 24 } },
  };

  return (
    <>
      <Container className="max-w-full space-y-6 lg:space-y-8">
        <m.div
          variants={containerVariants}
          initial="hidden"
          animate="visible"
          className="space-y-6 lg:space-y-8"
        >
          {/* Page header */}
          <m.div variants={itemVariants}>
            <header className="flex items-center gap-4">
              <div className="icon-box-md grid place-items-center rounded-2xl bg-gradient-to-br from-brand-500 to-accent-500 text-white shadow-lg">
                <Users className="icon-xl" />
              </div>
              <div>
                <h1 className="text-2xl font-bold tracking-tight text-slate-900 dark:text-white">{t("agent.recipients.title")}</h1>
                <p className="mt-1 text-sm text-slate-500 dark:text-slate-400">
                  {t("agent.recipients.subtitle").replace("{n}", String(recipients.length))}
                </p>
              </div>
            </header>
          </m.div>

          {/* List card */}
          <m.div variants={itemVariants}>
            <div className="overflow-hidden rounded-3xl border border-slate-200/60 bg-white shadow-sm dark:border-slate-800/60 dark:bg-slate-900/40">

              {/* Card header */}
              <div className="flex items-center justify-between gap-4 border-b border-slate-100/80 bg-slate-50/50 p-6 sm:p-7 dark:border-slate-800/60 dark:bg-slate-800/30">
                <div className="flex items-center gap-3">
                  <div className="grid h-9 w-9 place-items-center rounded-xl bg-brand-50 dark:bg-brand-500/10">
                    <Users className="h-4 w-4 text-brand-600 dark:text-brand-400" />
                  </div>
                  <div>
                    <h2 className="text-[length:var(--text-lg-fixed)] font-semibold text-slate-900 dark:text-white">{t("agent.recipients.cardTitle")}</h2>
                    <p className="text-[length:var(--text-sm-fixed)] text-slate-400">{t("agent.recipients.cardSaved").replace("{n}", String(recipients.length))}</p>
                  </div>
                </div>
                <Button size="sm" onClick={openAdd}>
                  <Plus className="me-1.5 h-4 w-4" />
                  {t("agent.recipients.addRecipient")}
                </Button>
              </div>

              {/* Search + filter bar */}
              <div className="flex flex-wrap items-center gap-3 border-b border-slate-100/80 px-6 py-4 sm:px-7 dark:border-slate-800/60">
                <div className="relative w-full max-w-sm">
                  <Search className="pointer-events-none absolute start-3.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-slate-400" />
                  <input
                    type="search"
                    value={search}
                    onChange={(e) => setSearch(e.target.value)}
                    placeholder={t("agent.recipients.searchPlaceholder")}
                    autoComplete="off"
                    className="h-9 w-full rounded-xl border border-slate-200 bg-slate-50 ps-9 pe-4 text-sm outline-none transition focus:border-brand-400 focus:bg-white dark:border-slate-700 dark:bg-slate-800/60 dark:text-white dark:focus:bg-slate-800"
                  />
                </div>
                <div className="flex flex-wrap gap-1.5">
                  {allMethods.map((method) => (
                    <button
                      key={method}
                      type="button"
                      onClick={() => setMethodFilter(method)}
                      className={cn(
                        "rounded-full px-3 py-1.5 text-[length:var(--text-sm-fixed)] font-medium transition",
                        methodFilter === method
                          ? "bg-brand-600 text-white shadow-sm"
                          : "bg-slate-100 text-slate-500 hover:bg-slate-200 hover:text-slate-700 dark:bg-slate-800 dark:text-slate-400 dark:hover:bg-slate-700 dark:hover:text-slate-200",
                      )}
                    >
                      {translateMethodName(method, t)}
                    </button>
                  ))}
                </div>
              </div>

              {filtered.length === 0 ? (
                <div className="flex flex-col items-center gap-4 py-20 text-center">
                  <div className="icon-box-lg grid place-items-center rounded-2xl bg-slate-100 dark:bg-slate-800">
                    <Users className="h-6 w-6 text-slate-400" />
                  </div>
                  <div>
                    <p className="text-sm font-semibold text-slate-600 dark:text-slate-300">
                      {search || methodFilter !== "All" ? t("agent.recipients.noMatch") : t("agent.recipients.noRecipients")}
                    </p>
                    <p className="mt-0.5 text-xs text-slate-400">
                      {search || methodFilter !== "All"
                        ? t("agent.recipients.noMatchSub")
                        : t("agent.recipients.noRecipientsSub")}
                    </p>
                  </div>
                  {!search && methodFilter === "All" && (
                    <Button size="sm" onClick={openAdd}>
                      <Plus className="me-1.5 h-4 w-4" />
                      {t("agent.recipients.addRecipient")}
                    </Button>
                  )}
                </div>
              ) : (
                <>
                  {/* Column headers */}
                  <div className="hidden grid-cols-[2.25rem_1fr_1fr_4rem] items-center gap-4 border-b border-slate-100/80 bg-slate-50/60 px-6 py-3 dark:border-slate-800/60 dark:bg-slate-800/20 sm:grid xl:grid-cols-[2.25rem_1fr_1fr_1fr_1fr_1fr_4rem] sm:px-7">
                    <div />
                    <p className="text-sm font-medium capitalize text-slate-400">{t("agent.recipients.colRecipient")}</p>
                    <p className="hidden text-sm font-medium capitalize text-slate-400 xl:block">{t("agent.recipients.colPhone")}</p>
                    <p className="hidden text-sm font-medium capitalize text-slate-400 xl:block">{t("agent.recipients.colCountry")}</p>
                    <p className="text-sm font-medium capitalize text-slate-400">{t("agent.recipients.colMethod")}</p>
                    <p className="hidden text-sm font-medium capitalize text-slate-400 xl:block">{t("agent.recipients.colDetails")}</p>
                    <p className="text-sm font-medium capitalize text-slate-400">{t("agent.recipients.colAction")}</p>
                  </div>

                  {/* Rows */}
                  <div className="divide-y divide-slate-100/80 dark:divide-slate-800/60">
                    {filtered.map((r, i) => (
                      <RecipientRow
                        key={r.slug}
                        recipient={r}
                        index={i}
                        onEdit={() => openEdit(r.slug)}
                      />
                    ))}
                  </div>
                </>
              )}
            </div>
          </m.div>
        </m.div>
      </Container>

      <RecipientFormModal
        open={modalOpen}
        editSlug={editSlug}
        onClose={closeModal}
        countries={countries}
        methods={methods}
      />
    </>
  );
}
