"use client";

import { useState, useEffect, ReactNode } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import StatusBadge from "@/components/StatusBadge";
import TablePagination, { usePagination } from "@/components/TablePagination";
import VerificationStamp from "@/components/VerificationStamp";
import { useToast, useConfirm, MessageThread } from "@/components/SharedUI";
import { HomeIcon, ShieldIcon, BookmarkIcon, UserIcon, ApproveIcon, RejectIcon, ViewIcon, SuspendIcon, SearchIcon, MessageIcon } from "@/components/Icons";
import { formatPrice } from "@/lib/mock-data";
import { clientExecute } from "@/lib/api/client";
import { ApiError } from "@/lib/api/shared";
import { useAuth } from "@/lib/auth-context";
import type { AccommodationBooking, PropertyReview, AppUser, Property, StayKYCApplication, Accommodation, Paginated } from "@/lib/types";
import type { KYCApplication } from "@/lib/kyc-store";

type Section = "overview" | "kyc" | "properties" | "properties-review" | "stay" | "users" | "messages";


// ─── Primitives ───────────────────────────────────────────────────────────────
function Btn({ children, onClick, variant = "primary", className = "", disabled = false }: {
  children: ReactNode; onClick?: () => void;
  variant?: "primary" | "ghost" | "danger" | "gold"; className?: string; disabled?: boolean;
}) {
  const s = {
    primary: "bg-forest text-white hover:bg-forest-deep",
    ghost: "border border-mist text-forest hover:bg-forest hover:border-forest hover:text-white",
    danger: "bg-clay text-white hover:opacity-90",
    gold: "bg-gold text-forest-deep hover:bg-gold-deep hover:text-white",
  };
  return (
    <button disabled={disabled} onClick={onClick}
      className={`inline-flex items-center justify-center gap-1.5 font-semibold text-sm px-5 py-2 rounded-pill transition-colors whitespace-nowrap disabled:opacity-40 ${s[variant]} ${className}`}>
      {children}
    </button>
  );
}

function Card({ children, className = "" }: { children: ReactNode; className?: string }) {
  return <div className={`bg-white border border-mist rounded-md overflow-hidden ${className}`}>{children}</div>;
}

function CardHeader({ title, sub, action }: { title: string; sub?: string; action?: ReactNode }) {
  return (
    <div className="flex flex-wrap justify-between items-center gap-3 px-5 py-4 border-b border-mist">
      <div>
        <h3 className="font-display font-semibold text-lg">{title}</h3>
        {sub && <p className="text-xs text-ink-soft">{sub}</p>}
      </div>
      {action}
    </div>
  );
}

function Th({ children }: { children: ReactNode }) {
  return <th className="text-left font-mono text-[11px] uppercase tracking-widest text-ink-soft px-5 py-3 border-b border-mist whitespace-nowrap bg-sage">{children}</th>;
}

function IconBtn({ title, variant = "default", onClick, children }: {
  title: string; variant?: "default" | "approve" | "reject"; onClick?: () => void; children: ReactNode;
}) {
  const hover = {
    default: "hover:border-forest hover:text-forest",
    approve: "hover:border-forest hover:text-forest hover:bg-[#E8F2EC]",
    reject: "hover:border-clay hover:text-clay hover:bg-[#F5EAE6]",
  };
  return (
    <button title={title} aria-label={title} onClick={onClick}
      className={`w-8 h-8 rounded-full border border-mist bg-white text-ink-soft flex items-center justify-center transition-colors ${hover[variant]}`}>
      <span className="w-4 h-4">{children}</span>
    </button>
  );
}

// ─── KYC Review Modal ─────────────────────────────────────────────────────────
function KYCReviewModal({ app, onApprove, onReject, onClose }: {
  app: KYCApplication;
  onApprove: () => void;
  onReject: (reason: string) => void;
  onClose: () => void;
}) {
  const [rejecting, setRejecting] = useState(false);
  const [approving, setApproving] = useState(false);
  const [reason,    setReason]    = useState("");

  const REJECT_REASONS = [
    "ID document is blurry or unreadable",
    "ID document appears expired",
    "Selfie does not match the ID document",
    "Name on ID does not match application",
    "Document type not accepted",
    "Suspected fraudulent document",
    "Other",
  ];

  function Row({ label, value }: { label: string; value: string }) {
    return (
      <div className="flex justify-between py-2.5 border-b border-mist last:border-b-0 text-sm">
        <span className="text-ink-soft">{label}</span>
        <span className="font-medium text-ink text-right max-w-[60%]">{value}</span>
      </div>
    );
  }

  function DocImg({ label, fileName }: { label: string; fileName: string }) {
    return (
      <div className="flex-1">
        <div className="font-mono text-[10px] uppercase tracking-wider text-ink-soft mb-1">{label}</div>
        <div className="h-32 bg-gradient-to-br from-mist to-sage border border-mist rounded-sm flex flex-col items-center justify-center gap-1 cursor-pointer hover:border-forest transition-colors group">
          <svg viewBox="0 0 24 24" fill="none" stroke="#5B6B63" strokeWidth="1.6" className="w-6 h-6 group-hover:stroke-forest transition-colors">
            <rect x="3" y="5" width="18" height="14" rx="2" /><circle cx="9" cy="10" r="2" />
            <path d="M21 17l-5-5-4 4-2-2-5 5" />
          </svg>
          <span className="text-[10px] text-ink-soft font-mono truncate max-w-[110px] px-2 text-center">{fileName}</span>
          <span className="text-[10px] text-forest opacity-0 group-hover:opacity-100 transition-opacity font-semibold">Tap to view</span>
        </div>
      </div>
    );
  }

  return (
    <div className="fixed inset-0 z-[90] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4 py-6 overflow-y-auto">
      <div className="bg-white rounded-xl border border-mist shadow-card-hover w-full max-w-2xl my-auto">

        {/* Header */}
        <div className="flex justify-between items-start px-6 py-5 border-b border-mist">
          <div className="flex items-center gap-3">
            <div className="w-12 h-12 rounded-full bg-mist flex items-center justify-center text-forest font-semibold text-lg shrink-0">
              {app.fullName[0]}
            </div>
            <div>
              <h3 className="font-display font-semibold text-xl text-forest-deep">{app.fullName}</h3>
              <div className="flex items-center gap-2 mt-0.5">
                <span className="font-mono text-xs text-ink-soft uppercase tracking-wider capitalize">{app.role}</span>
                <span className="text-mist">·</span>
                <span className="font-mono text-xs text-ink-soft">{app.phone}</span>
              </div>
            </div>
          </div>
          <button onClick={onClose} className="text-ink-soft hover:text-ink text-2xl leading-none mt-1">×</button>
        </div>

        {/* Body */}
        <div className="p-6 grid grid-cols-1 md:grid-cols-2 gap-6">

          {/* Left — Personal details */}
          <div>
            <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-3">Personal details</div>
            <div className="bg-sage rounded-md p-4">
              <Row label="Full name"     value={app.fullName} />
              <Row label="Date of birth" value={app.dob} />
              <Row label="Phone"         value={app.phone} />
              <Row label="Address"       value={app.address} />
              <Row label="Town"          value={app.town} />
              <Row label="Region"        value={app.region} />
              <Row label="Role"          value={app.role === "landlord" ? "Landlord" : "Agent"} />
              <Row label="Submitted"     value={app.submittedDate} />
            </div>
          </div>

          {/* Right — Documents */}
          <div className="flex flex-col gap-4">
            <div>
              <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-3">Identity document</div>
              <div className="bg-sage rounded-md p-4 mb-3">
                <Row label="Document type"   value={app.docType} />
                <Row label="Document number" value={app.docNumber} />
              </div>
              <div className="flex gap-3">
                <DocImg label="Front of ID" fileName={app.frontFileName} />
                <DocImg label="Back of ID"  fileName={app.backFileName} />
              </div>
            </div>

            {/* Selfie */}
            <div>
              <div className="font-mono text-[10px] uppercase tracking-wider text-ink-soft mb-1">Selfie with ID</div>
              <div className="h-32 bg-ink rounded-sm flex flex-col items-center justify-center gap-2 cursor-pointer hover:opacity-90 transition-opacity">
                <svg viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="1.4" className="w-7 h-7 opacity-40">
                  <path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z" />
                  <circle cx="12" cy="13" r="4" />
                </svg>
                <span className="text-xs text-white/50 font-mono">Selfie submitted</span>
              </div>
            </div>
          </div>
        </div>

        {/* ── Approve confirmation panel ── */}
        {approving && !rejecting && (
          <div className="px-6 pb-5 border-t border-mist pt-5 bg-[#E8F2EC]/50">
            <div className="flex items-start gap-3 mb-5">
              <div className="w-10 h-10 rounded-full bg-forest/10 flex items-center justify-center shrink-0 mt-0.5">
                <svg viewBox="0 0 24 24" fill="none" stroke="#1E4A3D" strokeWidth="2" className="w-5 h-5">
                  <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>
              <div>
                <div className="font-semibold text-forest-deep mb-1">Approve KYC for {app.fullName}?</div>
                <p className="text-sm text-ink-soft">
                  Confirming will verify them as a <strong className="capitalize">{app.role}</strong> on Villa. They will be able to list properties immediately and will be notified by SMS and email.
                </p>
              </div>
            </div>
            <div className="flex gap-3">
              <Btn onClick={onApprove}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" className="w-4 h-4">
                  <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                Yes, approve KYC
              </Btn>
              <Btn variant="ghost" onClick={() => setApproving(false)}>Cancel</Btn>
            </div>
          </div>
        )}

        {/* ── Reject reason picker ── */}
        {rejecting && !approving && (
          <div className="px-6 pb-5 border-t border-mist pt-5">
            <p className="text-sm text-ink-soft mb-3">
              Select a reason for rejection — <strong className="text-ink">{app.fullName}</strong> will be notified by email.
            </p>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 mb-4">
              {REJECT_REASONS.map((r) => (
                <label key={r} className="flex items-center gap-2 text-sm cursor-pointer">
                  <input type="radio" name="kyc-reject-reason" value={r} checked={reason === r}
                    onChange={() => setReason(r)} className="accent-clay w-4 h-4" />
                  {r}
                </label>
              ))}
            </div>
            {reason === "Other" && (
              <textarea placeholder="Describe the issue…" rows={2}
                className="w-full border border-mist rounded-sm px-3 py-2 text-sm mb-4 focus:outline-2 focus:outline-gold" />
            )}
            <div className="flex gap-3">
              <Btn variant="danger" disabled={!reason} onClick={() => { if (reason) onReject(reason); }}>
                Confirm rejection
              </Btn>
              <Btn variant="ghost" onClick={() => { setRejecting(false); setReason(""); }}>Cancel</Btn>
            </div>
          </div>
        )}

        {/* ── Footer actions (shown when neither approving nor rejecting) ── */}
        {!approving && !rejecting && (
          <div className="flex flex-wrap justify-between items-center gap-3 px-6 py-5 border-t border-mist bg-sage/30">
            <div className="flex gap-3">
              <Btn variant="primary" onClick={() => setApproving(true)}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-4 h-4">
                  <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                Approve KYC
              </Btn>
              <Btn variant="danger" onClick={() => setRejecting(true)}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-4 h-4">
                  <path d="M6 6l12 12M18 6L6 18" strokeLinecap="round" />
                </svg>
                Reject
              </Btn>
            </div>
            <Btn variant="ghost" onClick={onClose}>Close</Btn>
          </div>
        )}

      </div>
    </div>
  );
}

function PropertyDetailModal({ review, approving, rejecting, rejectReason, rejectReasons, onApprove, onReject, onSetApproving, onSetRejecting, onSetRejectReason, onClose }: {
  review: PropertyReview;
  approving: boolean; rejecting: boolean; rejectReason: string;
  rejectReasons: string[];
  onApprove: () => void; onReject: (reason: string) => void;
  onSetApproving: (v: boolean) => void; onSetRejecting: (v: boolean) => void;
  onSetRejectReason: (v: string) => void; onClose: () => void;
}) {
  return (
    <div className="fixed inset-0 z-[90] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4 py-6 overflow-y-auto">
      <div className="bg-white rounded-xl border border-mist shadow-card-hover w-full max-w-lg my-auto">

        {/* Header */}
        <div className="flex justify-between items-start px-6 py-5 border-b border-mist">
          <div>
            <h3 className="font-display font-semibold text-xl text-forest-deep">{review.title}</h3>
            <p className="text-xs text-ink-soft mt-0.5">{review.address} · {review.landlordName}</p>
          </div>
          <button onClick={onClose} className="text-ink-soft hover:text-ink text-2xl leading-none mt-1">×</button>
        </div>

        {/* Body */}
        <div className="p-6 flex flex-col gap-5">
          <div className="h-40 bg-gradient-to-br from-mist to-sage rounded-md flex items-center justify-center text-xs font-mono text-ink-soft">Property photo placeholder</div>
          <div className="grid grid-cols-2 gap-x-6 gap-y-3 text-sm">
            {[
              ["Landlord",  review.landlordName],
              ["Price",     `${formatPrice(review.price)}/mo`],
              ["Submitted", review.submitted],
              ["Status",    null],
            ].map(([label, value]) => (
              <div key={label as string} className="flex flex-col gap-0.5">
                <span className="text-ink-soft text-xs font-mono uppercase tracking-wider">{label}</span>
                {value ? <span className="font-medium text-ink">{value}</span> : <StatusBadge status={review.status} />}
              </div>
            ))}
          </div>
        </div>

        {/* Approve confirmation panel */}
        {approving && !rejecting && (
          <div className="px-6 pb-5 border-t border-mist pt-5 bg-[#E8F2EC]/50">
            <div className="flex items-start gap-3 mb-5">
              <div className="w-10 h-10 rounded-full bg-forest/10 flex items-center justify-center shrink-0 mt-0.5">
                <svg viewBox="0 0 24 24" fill="none" stroke="#1E4A3D" strokeWidth="2" className="w-5 h-5">
                  <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>
              <div>
                <div className="font-semibold text-forest-deep mb-1">Approve this listing?</div>
                <p className="text-sm text-ink-soft">
                  <strong>{review.title}</strong> will go live on Villa and appear in tenant searches. The landlord will be notified.
                </p>
              </div>
            </div>
            <div className="flex gap-3">
              <Btn onClick={onApprove}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" className="w-4 h-4">
                  <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                Yes, approve listing
              </Btn>
              <Btn variant="ghost" onClick={() => onSetApproving(false)}>Cancel</Btn>
            </div>
          </div>
        )}

        {/* Reject reason panel */}
        {rejecting && !approving && (
          <div className="px-6 pb-5 border-t border-mist pt-5">
            <p className="text-sm text-ink-soft mb-3">
              Select a reason for rejecting <strong className="text-ink">{review.title}</strong>. The landlord will be notified.
            </p>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 mb-4">
              {rejectReasons.map((r) => (
                <label key={r} className="flex items-center gap-2 text-sm cursor-pointer">
                  <input type="radio" name="prop-reject-reason" value={r} checked={rejectReason === r}
                    onChange={() => onSetRejectReason(r)} className="accent-clay w-4 h-4" />
                  {r}
                </label>
              ))}
            </div>
            {rejectReason === "Other" && (
              <textarea placeholder="Describe the reason…" rows={2}
                className="w-full border border-mist rounded-sm px-3 py-2 text-sm mb-4 focus:outline-2 focus:outline-gold" />
            )}
            <div className="flex gap-3">
              <Btn variant="danger" disabled={!rejectReason} onClick={() => rejectReason && onReject(rejectReason)}>
                Confirm rejection
              </Btn>
              <Btn variant="ghost" onClick={() => { onSetRejecting(false); onSetRejectReason(""); }}>Cancel</Btn>
            </div>
          </div>
        )}

        {/* Default footer */}
        {!approving && !rejecting && (
          <div className="flex flex-wrap justify-between items-center gap-3 px-6 py-5 border-t border-mist bg-sage/30">
            <div className="flex gap-3">
              <Btn variant="primary" onClick={() => onSetApproving(true)}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-4 h-4">
                  <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                Approve listing
              </Btn>
              <Btn variant="danger" onClick={() => onSetRejecting(true)}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-4 h-4">
                  <path d="M6 6l12 12M18 6L6 18" strokeLinecap="round" />
                </svg>
                Reject
              </Btn>
            </div>
            <Btn variant="ghost" onClick={onClose}>Close</Btn>
          </div>
        )}
      </div>
    </div>
  );
}

// ─── User detail modal ─────────────────────────────────────────────────────────
function UserDetailModal({ user, onClose }: { user: AppUser; onClose: () => void }) {
  return (
    <div className="fixed inset-0 z-[90] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4">
      <div className="bg-white rounded-lg border border-mist shadow-card-hover w-full max-w-sm">
        <div className="flex justify-between items-center px-6 py-4 border-b border-mist">
          <h3 className="font-display font-semibold text-lg text-forest-deep">User profile</h3>
          <button onClick={onClose} className="text-ink-soft hover:text-ink text-2xl leading-none">×</button>
        </div>
        <div className="p-6 flex flex-col gap-3">
          <div className="w-16 h-16 rounded-full bg-mist flex items-center justify-center text-forest font-semibold text-2xl mx-auto">{user.name[0]}</div>
          <div className="text-center">
            <div className="font-display font-semibold text-xl text-forest-deep">{user.name}</div>
            <div className="text-sm text-ink-soft capitalize">{user.role}</div>
          </div>
          <div className="flex flex-col gap-2 text-sm border-t border-mist pt-3">
            <div className="flex justify-between"><span className="text-ink-soft">Joined</span><span>{user.joinedDate}</span></div>
            <div className="flex justify-between items-center"><span className="text-ink-soft">Status</span><StatusBadge status={user.status === "suspended" ? "needs-changes" : user.status} label={user.status === "suspended" ? "Suspended" : undefined} /></div>
          </div>
        </div>
        <div className="px-6 pb-5 flex justify-end"><Btn variant="ghost" onClick={onClose}>Close</Btn></div>
      </div>
    </div>
  );
}

// ─── Reject property modal ─────────────────────────────────────────────────────
function RejectReasonModal({ title, onConfirm, onClose }: { title: string; onConfirm: (reason: string) => void; onClose: () => void }) {
  const [reason, setReason] = useState("");
  const REASONS = ["Photos do not match the property", "Price information is missing or incorrect", "Duplicate listing already exists", "Insufficient photos (minimum 4 required)", "Location details are incorrect", "Other"];
  return (
    <div className="fixed inset-0 z-[90] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4">
      <div className="bg-white rounded-lg border border-mist shadow-card-hover w-full max-w-md">
        <div className="flex justify-between items-center px-6 py-4 border-b border-mist">
          <h3 className="font-display font-semibold text-lg text-forest-deep">Reject submission</h3>
          <button onClick={onClose} className="text-ink-soft hover:text-ink text-2xl leading-none">×</button>
        </div>
        <div className="p-6">
          <p className="text-sm text-ink-soft mb-4">Select a reason for rejecting <strong className="text-ink">{title}</strong>. The landlord will be notified.</p>
          <div className="flex flex-col gap-2 mb-5">
            {REASONS.map((r) => (
              <label key={r} className="flex items-center gap-3 text-sm cursor-pointer">
                <input type="radio" name="reason" value={r} checked={reason === r} onChange={() => setReason(r)} className="accent-clay" />
                {r}
              </label>
            ))}
          </div>
          {reason === "Other" && <textarea placeholder="Describe the reason…" rows={3} className="w-full border border-mist rounded-sm px-3 py-2 text-sm mb-4 focus:outline-2 focus:outline-gold" />}
          <div className="flex gap-3 justify-end">
            <Btn variant="ghost" onClick={onClose}>Cancel</Btn>
            <Btn variant="danger" disabled={!reason} onClick={() => reason && onConfirm(reason)}>Reject listing</Btn>
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Main admin dashboard ──────────────────────────────────────────────────────
export default function AdminDashboardPage() {
  const router = useRouter();
  const { logout } = useAuth();

  const [section, setSection] = useState<Section>("overview");
  const [propReviews, setPropReviews] = useState<PropertyReview[]>([]);
  const [userList, setUserList] = useState<AppUser[]>([]);
  const [allProps, setAllProps] = useState<Property[]>([]);
  const [msgUnread, setMsgUnread] = useState(0);
  const [kycList, setKycList] = useState<KYCApplication[]>([]);
  const [stayBookings, setStayBookings] = useState<AccommodationBooking[]>([]);
  const [viewingKYC, setViewingKYC] = useState<KYCApplication | null>(null);
  const [viewingProp,   setViewingProp]   = useState<PropertyReview | null>(null);
  const [propApproving, setPropApproving] = useState(false);
  const [propRejecting, setPropRejecting] = useState(false);
  const [propRejectReason, setPropRejectReason] = useState("");

  const PROP_REJECT_REASONS = [
    "Photos do not match the property",
    "Price information is missing or incorrect",
    "Duplicate listing already exists",
    "Insufficient photos (minimum 4 required)",
    "Location details are incorrect",
    "Property description is misleading",
    "Other",
  ];

  function openPropModal(item: PropertyReview, mode: "view" | "approve" | "reject") {
    setViewingProp(item);
    setPropApproving(mode === "approve");
    setPropRejecting(mode === "reject");
    setPropRejectReason("");
  }

  function closePropModal() {
    setViewingProp(null);
    setPropApproving(false);
    setPropRejecting(false);
    setPropRejectReason("");
  }
  const [viewingUser, setViewingUser] = useState<AppUser | null>(null);

  const [searchQ,    setSearchQ]    = useState("");
  const [userSearchQ,  setUserSearchQ]  = useState("");
  const [kycSearchQ,   setKycSearchQ]   = useState("");
  const { show: showToast, node: toastNode } = useToast();
  const { confirm, node: confirmNode } = useConfirm();

  // ── Data loaders ──
  async function loadKyc() { try { const r = await clientExecute<Paginated<KYCApplication>>("kyc.list-queue", { status: "pending", limit: 100 }); setKycList(r.items); } catch { /* ignore */ } }
  async function loadPropReviews() {
    try {
      const r = await clientExecute<Paginated<Property>>("property.list-review-queue", { limit: 100 });
      const withLandlords = await Promise.all(r.items.map(async (p) => {
        let landlordName = "—", landlordPhone = "";
        try {
          const l = await clientExecute<{ name: string; phone: string }>("landlord.find-one", { id: p.landlordId });
          landlordName = l.name; landlordPhone = l.phone;
        } catch { /* landlord lookup optional */ }
        return {
          id: p.id, title: p.title, address: p.address, landlordName, landlordPhone,
          price: p.price, submitted: p.listedDate ?? "—",
          status: (p.status === "needs-changes" ? "needs-changes" : "pending") as PropertyReview["status"],
        };
      }));
      setPropReviews(withLandlords);
    } catch { /* ignore */ }
  }
  async function loadAllProps() { try { const r = await clientExecute<Paginated<Property>>("property.admin-find-all", { limit: 100 }); setAllProps(r.items); } catch { /* ignore */ } }
  async function loadUsers() { try { const r = await clientExecute<Paginated<AppUser>>("user.find-all", { limit: 100 }); setUserList(r.items); } catch { /* ignore */ } }

  useEffect(() => {
    void loadKyc(); void loadPropReviews(); void loadAllProps(); void loadUsers();
    void loadStayAccs(); void loadStayBookings(); void loadStayKyc();
    void (async () => {
      try {
        const c = await clientExecute<{ items: { unread: number }[] }>("message.list-conversations", { limit: 100 });
        setMsgUnread(c.items.filter((x) => x.unread > 0).length);
      } catch { /* ignore */ }
    })();
  }, []);

  const unreadMessages = msgUnread;
  const pendingProps   = propReviews.length;
  const pendingKYC     = kycList; // badge
  const allPendingKYC  = kycList; // full list for the KYC section

  async function handleLogout() { await logout(); router.push("/"); router.refresh(); }

  // ── KYC actions ──
  async function handleApproveKYC(app: KYCApplication) {
    try {
      await clientExecute("kyc.approve", { id: app.id });
      setKycList((l) => l.filter((a) => a.id !== app.id));
      setViewingKYC(null);
      showToast(`${app.fullName} approved — KYC verified ✓`);
    } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't approve.", "error"); }
  }

  async function handleRejectKYC(app: KYCApplication, reason: string) {
    try {
      await clientExecute("kyc.reject", { id: app.id, reason });
      setKycList((l) => l.filter((a) => a.id !== app.id));
      setViewingKYC(null);
      showToast(`${app.fullName}'s KYC rejected — they will be notified`, "info");
    } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't reject.", "error"); }
  }

  // ── Property review actions ──
  async function approveProperty(item: PropertyReview) {
    try {
      await clientExecute("property.approve", { id: item.id });
      setPropReviews((p) => p.filter((r) => r.id !== item.id));
      showToast(`"${item.title}" approved and listed`);
      void loadAllProps();
    } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't approve.", "error"); }
  }

  async function rejectProperty(item: PropertyReview, reason: string) {
    try {
      await clientExecute("property.reject", { id: item.id, reason });
      setPropReviews((p) => p.filter((r) => r.id !== item.id));
      showToast(`"${item.title}" rejected — landlord notified`, "info");
    } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't reject.", "error"); }
  }

  // ── User actions ──
  async function toggleSuspend(user: AppUser) {
    const isSuspended = user.status === "suspended";
    const ok = await confirm({
      title: isSuspended ? "Reinstate user?" : "Suspend user?",
      body: isSuspended ? `${user.name} will regain access to Villa.` : `${user.name} will lose access until reinstated.`,
      confirmLabel: isSuspended ? "Reinstate" : "Suspend",
      danger: !isSuspended,
    });
    if (ok) {
      try {
        await clientExecute(isSuspended ? "user.reinstate" : "user.suspend", { id: user.id });
        setUserList((u) => u.map((r) => r.id === user.id ? { ...r, status: isSuspended ? "active" : "suspended" } : r));
        showToast(isSuspended ? `${user.name} reinstated` : `${user.name} suspended`, isSuspended ? "success" : "info");
      } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't update.", "error"); }
    }
  }

  async function deleteUser(user: AppUser) {
    const ok = await confirm({ title: "Delete user account?", body: `This will permanently delete ${user.name}'s account. This cannot be undone.`, confirmLabel: "Yes, delete account", danger: true });
    if (ok) {
      try {
        await clientExecute("user.delete", { id: user.id });
        setUserList((u) => u.filter((r) => r.id !== user.id));
        showToast(`${user.name}'s account deleted`, "error");
      } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't delete.", "error"); }
    }
  }

  // ── All properties actions ──
  async function deleteProperty(p: Property) {
    const ok = await confirm({ title: "Delete this property?", body: `"${p.title}" will be permanently removed. This cannot be undone.`, confirmLabel: "Yes, delete", danger: true });
    if (ok) {
      try {
        await clientExecute("property.delete", { id: p.id });
        setAllProps((prev) => prev.filter((r) => r.id !== p.id));
        showToast(`"${p.title}" deleted`);
      } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't delete.", "error"); }
    }
  }

  async function togglePropertyStatus(p: Property) {
    const next = p.status === "verified" ? "unavailable" : "verified";
    const ok = await confirm({
      title: next === "unavailable" ? "Remove from search?" : "Restore listing?",
      body: next === "unavailable" ? `"${p.title}" will be hidden from tenants.` : `"${p.title}" will appear in searches again.`,
      confirmLabel: "Confirm",
    });
    if (ok) {
      try {
        const updated = await clientExecute<Property>("property.toggle-status", { id: p.id });
        setAllProps((prev) => prev.map((r) => r.id === p.id ? updated : r));
        showToast("Property status updated");
      } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't update.", "error"); }
    }
  }

  const filteredProps = allProps.filter((p) =>
    !searchQ || p.title.toLowerCase().includes(searchQ.toLowerCase()) || p.town.toLowerCase().includes(searchQ.toLowerCase())
  );

  const filteredUsers = userList.filter((u) =>
    !userSearchQ || u.name.toLowerCase().includes(userSearchQ.toLowerCase()) || u.role.includes(userSearchQ.toLowerCase())
  );

  const filteredKYC = kycList.filter((a) =>
    !kycSearchQ || a.fullName.toLowerCase().includes(kycSearchQ.toLowerCase()) || a.role.includes(kycSearchQ.toLowerCase())
  );

  // Villa Stay state
  const [staySubTab,     setStaySubTab]    = useState<"properties" | "bookings" | "kyc">("properties");
  const [staySearchQ,    setStaySearchQ]   = useState("");
  const [bookingSearchQ, setBookingSearchQ] = useState("");
  const [viewingAcc,       setViewingAcc]       = useState<Accommodation | null>(null);
  const [accApproving,     setAccApproving]     = useState(false);
  const [accRejecting,     setAccRejecting]     = useState(false);
  const [accRejectReason,  setAccRejectReason]  = useState("");
  const [quickRejectAcc,   setQuickRejectAcc]   = useState<Accommodation | null>(null);
  const [quickRejectReason, setQuickRejectReason] = useState("");

  const ACC_REJECT_REASONS = [
    "Photos do not match the property",
    "Property details are incomplete or inaccurate",
    "KYC not yet approved for this owner",
    "Duplicate listing already exists",
    "Property does not meet Villa Stay standards",
    "Insufficient room information",
    "Other",
  ];

  function openAccModal(acc: Accommodation, mode: "view" | "approve" | "reject") {
    setViewingAcc(acc);
    setAccApproving(mode === "approve");
    setAccRejecting(mode === "reject");
    setAccRejectReason("");
  }

  function closeAccModal() {
    setViewingAcc(null);
    setAccApproving(false);
    setAccRejecting(false);
    setAccRejectReason("");
  }
  const [viewingStayKYC, setViewingStayKYC] = useState<StayKYCApplication | null>(null);
  const [stayKycRejectReason, setStayKycRejectReason] = useState("");
  const [stayKycRejecting,    setStayKycRejecting]    = useState(false);
  const [stayKycApproving,    setStayKycApproving]    = useState(false);
  const [stayKycList, setStayKycList] = useState<StayKYCApplication[]>([]);
  const [stayAccList,    setStayAccList]   = useState<Accommodation[]>([]);

  async function loadStayAccs() { try { const r = await clientExecute<Paginated<Accommodation>>("accommodation.admin-find-all", { limit: 100 }); setStayAccList(r.items); } catch { /* ignore */ } }
  async function loadStayBookings() { try { const r = await clientExecute<Paginated<AccommodationBooking>>("booking.admin-find-all", { limit: 100 }); setStayBookings(r.items); } catch { /* ignore */ } }
  async function loadStayKyc() { try { const r = await clientExecute<Paginated<StayKYCApplication>>("stay-kyc.list-queue", { status: "pending", limit: 100 }); setStayKycList(r.items); } catch { /* ignore */ } }

  const filteredAccs = stayAccList.filter((a) =>
    !staySearchQ || a.name.toLowerCase().includes(staySearchQ.toLowerCase()) || a.town.toLowerCase().includes(staySearchQ.toLowerCase())
  );
  const filteredStayBookings = stayBookings.filter((b) =>
    !bookingSearchQ || b.guestName.toLowerCase().includes(bookingSearchQ.toLowerCase()) || b.accommodationName.toLowerCase().includes(bookingSearchQ.toLowerCase())
  );

  // Pagination hooks for each table
  const kycPag      = usePagination(filteredKYC, 5);
  const propRevPag  = usePagination(propReviews, 5);
  const propsPag    = usePagination(filteredProps, 5);
  const usersPag    = usePagination(filteredUsers, 5);
  const accsPag     = usePagination(filteredAccs, 5);
  const stayBookPag = usePagination(filteredStayBookings, 5);
  const stayKycPag  = usePagination(stayKycList, 5);

  const navItems: { id: Section; icon: ReactNode; label: string; badge?: number }[] = [
    { id: "overview", icon: <HomeIcon />, label: "Overview" },
    { id: "kyc", icon: <ShieldIcon />, label: "KYC verification", badge: pendingKYC.length },
    { id: "properties-review", icon: <ApproveIcon />, label: "Property review", badge: pendingProps },
    { id: "properties", icon: <BookmarkIcon />, label: "All properties" },
    { id: "stay", icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" className="w-[18px] h-[18px]"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><path d="M9 22V12h6v10" strokeLinecap="round"/></svg>, label: "Villa Stay", badge: stayBookings.filter(b => b.status === "pending").length },
    { id: "users", icon: <UserIcon />, label: "Users & landlords" },
    { id: "messages", icon: <MessageIcon />, label: "Messages", badge: unreadMessages },
  ];

  return (
    <div className="max-w-6xl mx-auto px-6 py-8">
      <div className="grid grid-cols-1 lg:grid-cols-[240px_1fr] gap-8 items-start">

        {/* Sidebar */}
        <aside className="bg-white border border-mist rounded-md p-5 lg:sticky lg:top-[96px]">
          <div className="mb-5 pb-5 border-b border-mist">
            <div className="font-display font-semibold text-lg">Villa Admin</div>
            <div className="font-mono text-xs uppercase tracking-widest text-ink-soft">Administrator</div>
          </div>
          <nav className="flex flex-col gap-1">
            {navItems.map(({ id, icon, label, badge }) => (
              <button key={id} onClick={() => setSection(id)}
                className={`flex items-center gap-3 px-3 py-2.5 rounded-sm text-sm font-medium transition-colors text-left w-full ${section === id ? "bg-forest text-white" : "text-ink-soft hover:bg-sage hover:text-forest"}`}>
                <span className="w-[18px] h-[18px] shrink-0">{icon}</span>
                <span className="flex-1">{label}</span>
                {badge !== undefined && badge > 0 && (
                  <span className={`inline-flex items-center justify-center min-w-[18px] h-[18px] rounded-full text-[11px] font-bold px-1 ${section === id ? "bg-white text-forest" : "bg-gold text-forest-deep"}`}>
                    {badge}
                  </span>
                )}
              </button>
            ))}
          </nav>
          <div className="mt-5 pt-5 border-t border-mist">
            <button onClick={handleLogout} className="text-sm text-ink-soft hover:text-clay transition-colors">Log out</button>
          </div>
        </aside>

        {/* Main */}
        <div>

          {/* ── Overview ── */}
          {section === "overview" && (
            <div>
              <div className="mb-6">
                <h1 className="font-display font-semibold text-2xl lg:text-3xl text-forest-deep">Admin overview</h1>
                <p className="text-sm text-ink-soft">Monitor and manage all Villa activity.</p>
              </div>
              <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
                {[
                  { label: "Pending KYC", value: String(pendingKYC.length), change: "Awaiting identity check", action: "kyc" as Section },
                  { label: "Pending listings", value: String(pendingProps), change: "Awaiting review", action: "properties-review" as Section },
                  { label: "Total properties", value: String(allProps.length), change: `${allProps.filter((p) => p.status === "verified").length} verified`, action: "properties" as Section },
                  { label: "Total users", value: String(userList.length), change: `${userList.filter((u) => u.role === "landlord").length} landlords`, action: "users" as Section },
                ].map(({ label, value, change, action }) => (
                  <button key={label} onClick={() => setSection(action)}
                    className="bg-white border border-mist rounded-md p-5 text-left hover:border-forest hover:shadow-card transition-all group">
                    <div className="font-mono text-xs uppercase tracking-widest text-ink-soft mb-2">{label}</div>
                    <div className="font-display text-3xl font-semibold text-forest-deep group-hover:text-forest">{value}</div>
                    <div className="text-xs mt-1 text-forest">{change}</div>
                  </button>
                ))}
              </div>

              {/* KYC queue preview */}
              {pendingKYC.length > 0 && (
                <Card className="mb-5">
                  <CardHeader title="KYC applications" sub={`${pendingKYC.length} awaiting identity verification`} action={<Btn variant="ghost" onClick={() => setSection("kyc")}>Review all</Btn>} />
                  <div className="divide-y divide-mist">
                    {pendingKYC.slice(0, 3).map((app) => (
                      <div key={app.id} className="flex flex-wrap items-center justify-between gap-3 px-5 py-4">
                        <div className="flex items-center gap-3">
                          <div className="w-9 h-9 rounded-full bg-mist flex items-center justify-center text-forest font-semibold text-sm shrink-0">
                            {app.fullName[0]}
                          </div>
                          <div>
                            <div className="font-display font-semibold text-sm text-forest-deep">{app.fullName}</div>
                            <div className="text-xs text-ink-soft capitalize">{app.role} · {app.docType} · {app.submittedDate}</div>
                          </div>
                        </div>
                        <div className="flex gap-2">
                          <Btn variant="ghost" onClick={() => setViewingKYC(app)}>Review</Btn>
                        </div>
                      </div>
                    ))}
                  </div>
                </Card>
              )}

              {/* Property review queue preview */}
              {propReviews.length > 0 && (
                <Card>
                  <CardHeader title="Property submissions" sub={`${propReviews.length} pending`} action={<Btn variant="ghost" onClick={() => setSection("properties-review")}>See all</Btn>} />
                  <div className="divide-y divide-mist">
                    {propReviews.slice(0, 3).map((item) => (
                      <div key={item.id} className="flex flex-wrap items-center justify-between gap-3 px-5 py-4">
                        <div>
                          <div className="font-display font-semibold text-sm text-forest-deep">{item.title}</div>
                          <div className="text-xs text-ink-soft">{item.landlordName} · {item.submitted}</div>
                        </div>
                        <div className="flex gap-2">
                          <Btn variant="primary" onClick={() => openPropModal(item, "approve")}>Approve</Btn>
                          <Btn variant="danger"  onClick={() => openPropModal(item, "reject")}>Reject</Btn>
                        </div>
                      </div>
                    ))}
                  </div>
                </Card>
              )}
            </div>
          )}

          {/* ── KYC Verification ── */}
          {section === "kyc" && (
            <div>
              <h2 className="font-display font-semibold text-xl text-forest-deep mb-1">KYC verification</h2>
              <p className="text-sm text-ink-soft mb-4">Review identity documents submitted by landlords and agents. Approve to grant listing access, or reject with a reason.</p>
              <div className="flex items-center gap-3 bg-white border border-mist rounded-pill pl-5 pr-2 py-2 mb-5 shadow-card">
                <SearchIcon className="w-4 h-4 text-ink-soft shrink-0" />
                <input value={kycSearchQ} onChange={(e) => { setKycSearchQ(e.target.value); kycPag.reset(); }}
                  placeholder="Search by name or role…"
                  className="flex-1 bg-transparent border-none outline-none text-sm text-ink placeholder:text-ink-soft" />
                {kycSearchQ && <button onClick={() => { setKycSearchQ(""); kycPag.reset(); }} className="text-ink-soft hover:text-ink px-2">×</button>}
              </div>

              {filteredKYC.length === 0 ? (
                <Card>
                  <div className="text-center py-16 px-5">
                    <VerificationStamp variant="property" size={72} className="mx-auto mb-5" />
                    <h3 className="font-display font-semibold text-lg text-forest-deep mb-2">
                      {kycSearchQ ? "No results found" : "All caught up"}
                    </h3>
                    <p className="text-sm text-ink-soft">
                      {kycSearchQ ? `No KYC applications match "${kycSearchQ}".` : "No KYC applications waiting for review."}
                    </p>
                  </div>
                </Card>
              ) : (
                <>
                <div className="flex flex-col gap-4">
                  {kycPag.paged.map((app) => (
                    <Card key={app.id}>
                      <div className="flex flex-wrap items-center justify-between gap-4 p-5">
                        <div className="flex items-center gap-4">
                          <div className="w-12 h-12 rounded-full bg-mist flex items-center justify-center text-forest font-semibold text-xl shrink-0">
                            {app.fullName[0]}
                          </div>
                          <div>
                            <div className="font-display font-semibold text-lg text-forest-deep">{app.fullName}</div>
                            <div className="text-sm text-ink-soft capitalize mb-1">{app.role} · {app.town}, {app.region}</div>
                            <div className="flex flex-wrap gap-2">
                              <span className="font-mono text-xs bg-sage border border-mist text-ink-soft px-2.5 py-1 rounded-pill">{app.docType}</span>
                              <span className="font-mono text-xs bg-sage border border-mist text-ink-soft px-2.5 py-1 rounded-pill">{app.docNumber}</span>
                              <span className="font-mono text-xs bg-sage border border-mist text-ink-soft px-2.5 py-1 rounded-pill">Submitted {app.submittedDate}</span>
                            </div>
                          </div>
                        </div>
                        <div className="flex items-center gap-3">
                          {app.status === "approved" ? (
                            <StatusBadge status="verified" label="KYC approved" />
                          ) : app.status === "rejected" ? (
                            <div className="text-right">
                              <StatusBadge status="needs-changes" label="Rejected" />
                              {app.rejectionReason && <p className="text-xs text-ink-soft mt-1 max-w-[180px]">{app.rejectionReason}</p>}
                            </div>
                          ) : (
                            <>
                              <StatusBadge status="pending" label="Pending review" />
                              <Btn variant="ghost" onClick={() => setViewingKYC(app)}>
                                <ViewIcon className="w-4 h-4" />
                                Review
                              </Btn>
                            </>
                          )}
                        </div>
                      </div>

                    </Card>
                  ))}
                </div>
                <TablePagination page={kycPag.page} totalPages={kycPag.totalPages} total={filteredKYC.length} perPage={5} onPage={kycPag.goTo} label="application" />
                </>
              )}
            </div>
          )}

          {/* ── Property review ── */}
          {section === "properties-review" && (
            <div>
              <h2 className="font-display font-semibold text-xl text-forest-deep mb-5">Property review</h2>
              <Card>
                <CardHeader title="Pending submissions" sub={`${propReviews.length} awaiting review`} />
                {propReviews.length === 0 ? (
                  <div className="text-center py-10 text-sm text-ink-soft">All caught up — no properties waiting for review.</div>
                ) : (
                  <>
                  <div className="overflow-x-auto">
                    <table className="w-full border-collapse">
                      <thead><tr><Th>Property</Th><Th>Landlord</Th><Th>Price</Th><Th>Submitted</Th><Th>Status</Th><th className="px-5 py-3 border-b border-mist bg-sage"></th></tr></thead>
                      <tbody>
                        {propRevPag.paged.map((item) => (
                          <tr key={item.id} className="border-b border-mist last:border-b-0 hover:bg-sage/40 transition-colors">
                            <td className="px-5 py-4 whitespace-nowrap">
                              <div className="font-display font-semibold text-forest-deep">{item.title}</div>
                              <div className="text-xs text-ink-soft">{item.address}</div>
                            </td>
                            <td className="px-5 py-4 text-sm whitespace-nowrap">{item.landlordName}</td>
                            <td className="px-5 py-4 font-mono text-sm whitespace-nowrap">{formatPrice(item.price)}</td>
                            <td className="px-5 py-4 text-sm text-ink-soft whitespace-nowrap">{item.submitted}</td>
                            <td className="px-5 py-4 whitespace-nowrap"><StatusBadge status={item.status} /></td>
                            <td className="px-5 py-4">
                              <div className="flex gap-2">
                                <IconBtn title="View details" onClick={() => openPropModal(item, "view")}><ViewIcon /></IconBtn>
                                <IconBtn title="Approve" variant="approve" onClick={() => openPropModal(item, "approve")}><ApproveIcon /></IconBtn>
                                <IconBtn title="Reject"  variant="reject"  onClick={() => openPropModal(item, "reject")}><RejectIcon /></IconBtn>
                              </div>
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                  <TablePagination page={propRevPag.page} totalPages={propRevPag.totalPages} total={propRevPag.total} perPage={5} onPage={propRevPag.goTo} label="submission" />
                  </>
                )}
              </Card>
            </div>
          )}

          {/* ── All properties ── */}
          {section === "properties" && (
            <div>
              <h2 className="font-display font-semibold text-xl text-forest-deep mb-4">All properties</h2>
              <div className="flex items-center gap-3 bg-white border border-mist rounded-pill pl-5 pr-2 py-2 mb-5 shadow-card">
                <SearchIcon className="w-4 h-4 text-ink-soft shrink-0" />
                <input value={searchQ} onChange={(e) => setSearchQ(e.target.value)} placeholder="Search by title or town…"
                  className="flex-1 bg-transparent border-none outline-none text-sm text-ink placeholder:text-ink-soft" />
                {searchQ && <button onClick={() => setSearchQ("")} className="text-ink-soft hover:text-ink px-2">×</button>}
              </div>
              <Card>
                <CardHeader title={`${filteredProps.length} properties`} />
                <>
                <div className="overflow-x-auto">
                  <table className="w-full border-collapse">
                    <thead><tr><Th>Property</Th><Th>Price</Th><Th>Status</Th><Th>Town</Th><th className="px-5 py-3 border-b border-mist bg-sage"></th></tr></thead>
                    <tbody>
                      {propsPag.paged.map((p) => (
                        <tr key={p.id} className="border-b border-mist last:border-b-0 hover:bg-sage/40 transition-colors">
                          <td className="px-5 py-4 whitespace-nowrap">
                            <div className="font-display font-semibold text-forest-deep">{p.title}</div>
                            <div className="text-xs text-ink-soft">{p.address}</div>
                          </td>
                          <td className="px-5 py-4 font-mono text-sm whitespace-nowrap">{formatPrice(p.price)}</td>
                          <td className="px-5 py-4 whitespace-nowrap"><StatusBadge status={p.status} /></td>
                          <td className="px-5 py-4 text-sm whitespace-nowrap">{p.town}</td>
                          <td className="px-5 py-4">
                            <div className="flex gap-2">
                              <IconBtn title={p.status === "verified" ? "Hide from search" : "Restore listing"} onClick={() => togglePropertyStatus(p)}>
                                {p.status === "verified" ? <SuspendIcon /> : <ApproveIcon />}
                              </IconBtn>
                              <IconBtn title="Delete" variant="reject" onClick={() => deleteProperty(p)}>
                                <span className="text-sm leading-none">✕</span>
                              </IconBtn>
                            </div>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
                <TablePagination page={propsPag.page} totalPages={propsPag.totalPages} total={propsPag.total} perPage={5} onPage={propsPag.goTo} label="property" />
                </>
              </Card>
            </div>
          )}

          {/* ── Users ── */}
          {section === "users" && (
            <div>
              <h2 className="font-display font-semibold text-xl text-forest-deep mb-2">Users &amp; landlords</h2>
              <div className="flex items-center gap-3 bg-white border border-mist rounded-pill pl-5 pr-2 py-2 mb-5 shadow-card">
                <SearchIcon className="w-4 h-4 text-ink-soft shrink-0" />
                <input value={userSearchQ} onChange={(e) => { setUserSearchQ(e.target.value); usersPag.reset(); }}
                  placeholder="Search by name or role…"
                  className="flex-1 bg-transparent border-none outline-none text-sm text-ink placeholder:text-ink-soft" />
                {userSearchQ && <button onClick={() => { setUserSearchQ(""); usersPag.reset(); }} className="text-ink-soft hover:text-ink px-2">×</button>}
              </div>
              <Card>
                <CardHeader title={`${filteredUsers.length} of ${userList.length} users`} />
                <>
                <div className="overflow-x-auto">
                  <table className="w-full border-collapse">
                    <thead><tr><Th>Name</Th><Th>Role</Th><Th>Joined</Th><Th>Status</Th><th className="px-5 py-3 border-b border-mist bg-sage"></th></tr></thead>
                    <tbody>
                      {usersPag.paged.map((user) => (
                        <tr key={user.id} className="border-b border-mist last:border-b-0 hover:bg-sage/40 transition-colors">
                          <td className="px-5 py-4 whitespace-nowrap">
                            <div className="font-display font-semibold text-forest-deep">{user.name}</div>
                          </td>
                          <td className="px-5 py-4 text-sm capitalize whitespace-nowrap">{user.role}</td>
                          <td className="px-5 py-4 text-sm text-ink-soft whitespace-nowrap">{user.joinedDate}</td>
                          <td className="px-5 py-4 whitespace-nowrap">
                            <StatusBadge status={user.status === "suspended" ? "needs-changes" : user.status} label={user.status === "suspended" ? "Suspended" : undefined} />
                          </td>
                          <td className="px-5 py-4">
                            <div className="flex gap-2">
                              <IconBtn title="View profile" onClick={() => setViewingUser(user)}><ViewIcon /></IconBtn>
                              <IconBtn title={user.status === "suspended" ? "Reinstate" : "Suspend"} variant={user.status === "suspended" ? "approve" : "reject"} onClick={() => toggleSuspend(user)}>
                                <SuspendIcon />
                              </IconBtn>
                              <IconBtn title="Delete account" variant="reject" onClick={() => deleteUser(user)}>
                                <span className="text-sm leading-none">✕</span>
                              </IconBtn>
                            </div>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
                <TablePagination page={usersPag.page} totalPages={usersPag.totalPages} total={filteredUsers.length} perPage={5} onPage={usersPag.goTo} label="user" />
                </>
              </Card>
            </div>
          )}

          {/* ── Villa Stay ── */}
          {section === "stay" && (
            <div>
              <h2 className="font-display font-semibold text-xl text-forest-deep mb-1">Villa Stay</h2>
              <p className="text-sm text-ink-soft mb-5">Manage accommodation listings, guest bookings, and owner KYC verification.</p>

              {/* Stats */}
              <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
                {[
                  { label: "Listed properties", value: String(stayAccList.length), action: () => setStaySubTab("properties") },
                  { label: "Verified stays",    value: String(stayAccList.filter(a => a.status === "verified").length), action: () => setStaySubTab("properties") },
                  { label: "Total bookings",    value: String(stayBookings.length), action: () => setStaySubTab("bookings") },
                  { label: "KYC pending",       value: String(stayKycList.filter(k => k.status === "pending").length), action: () => setStaySubTab("kyc") },
                ].map(({ label, value, action }) => (
                  <button key={label} onClick={action}
                    className="bg-white border border-mist rounded-md p-5 text-left hover:border-forest transition-colors">
                    <div className="font-mono text-xs uppercase tracking-widest text-ink-soft mb-2">{label}</div>
                    <div className="font-display text-3xl font-semibold text-forest-deep">{value}</div>
                  </button>
                ))}
              </div>

              {/* Sub-tabs */}
              <div className="flex gap-1 mb-5 bg-sage border border-mist rounded-lg p-1">
                {(["properties","bookings","kyc"] as const).map((tab) => (
                  <button key={tab} onClick={() => setStaySubTab(tab)}
                    className={`flex-1 text-center font-mono text-xs uppercase tracking-wider py-2.5 rounded-md transition-colors ${staySubTab === tab ? "bg-white text-forest font-bold shadow-card" : "text-ink-soft hover:text-forest"}`}>
                    {tab === "kyc" ? "Owner KYC" : tab.charAt(0).toUpperCase() + tab.slice(1)}
                    {tab === "kyc" && stayKycList.filter(k => k.status === "pending").length > 0 && (
                      <span className="ml-1.5 bg-gold text-forest-deep font-bold text-[10px] px-1.5 py-0.5 rounded-pill">
                        {stayKycList.filter(k => k.status === "pending").length}
                      </span>
                    )}
                  </button>
                ))}
              </div>

              {/* Properties sub-tab */}
              {staySubTab === "properties" && (
                <>
                  <div className="flex items-center gap-3 bg-white border border-mist rounded-pill pl-5 pr-2 py-2 mb-4 shadow-card">
                    <SearchIcon className="w-4 h-4 text-ink-soft shrink-0" />
                    <input value={staySearchQ} onChange={(e) => { setStaySearchQ(e.target.value); accsPag.reset(); }}
                      placeholder="Search by name or town…"
                      className="flex-1 bg-transparent border-none outline-none text-sm text-ink placeholder:text-ink-soft" />
                    {staySearchQ && <button onClick={() => { setStaySearchQ(""); accsPag.reset(); }} className="text-ink-soft hover:text-ink px-2">×</button>}
                  </div>
                  <Card>
                    <CardHeader title={`${filteredAccs.length} accommodation${filteredAccs.length !== 1 ? "s" : ""}`} />
                    <div className="overflow-x-auto">
                      <table className="w-full border-collapse">
                        <thead><tr><Th>Property</Th><Th>Type</Th><Th>Town</Th><Th>Owner</Th><Th>KYC</Th><Th>Status</Th><th className="px-5 py-3 border-b border-mist bg-sage"></th></tr></thead>
                        <tbody>
                          {accsPag.paged.map((acc) => (
                            <tr key={acc.id} className="border-b border-mist last:border-b-0 hover:bg-sage/40 transition-colors">
                              <td className="px-5 py-4">
                                <div className="font-semibold text-forest-deep">{acc.name}</div>
                                <div className="text-xs text-ink-soft">{acc.address}</div>
                              </td>
                              <td className="px-5 py-4 text-sm capitalize whitespace-nowrap">{acc.type}</td>
                              <td className="px-5 py-4 text-sm whitespace-nowrap">{acc.town}</td>
                              <td className="px-5 py-4 text-sm whitespace-nowrap">
                                <div>{acc.ownerName}</div>
                                <div className="text-xs text-ink-soft capitalize">{acc.ownerRole}</div>
                              </td>
                              <td className="px-5 py-4 whitespace-nowrap">
                                <span className={`font-mono text-[10px] uppercase tracking-wider px-2.5 py-1 rounded-pill border ${
                                  acc.kycStatus === "approved" ? "bg-[#E8F2EC] text-forest border-forest/20" :
                                  acc.kycStatus === "pending"  ? "bg-[#FBF1E1] text-gold-deep border-gold" :
                                  acc.kycStatus === "rejected" ? "bg-[#F5EAE6] text-clay border-clay" :
                                  "bg-mist text-ink-soft border-mist"
                                }`}>{acc.kycStatus}</span>
                              </td>
                              <td className="px-5 py-4 whitespace-nowrap"><StatusBadge status={acc.status} /></td>
                              <td className="px-5 py-4">
                                <div className="flex gap-2">
                                  <IconBtn title="View property" onClick={() => openAccModal(acc, "view")}><ViewIcon /></IconBtn>
                                  {acc.status === "pending" && (
                                    <>
                                      <IconBtn title="Approve" variant="approve" onClick={async () => {
                                        const ok = await confirm({
                                          title: "Approve this listing?",
                                          body: `"${acc.name}" will go live on Villa Stay and guests will be able to search and book it.`,
                                          confirmLabel: "Approve",
                                        });
                                        if (ok) {
                                          try {
                                            await clientExecute("accommodation.approve", { id: acc.id });
                                            setStayAccList((prev) => prev.map((a) => a.id === acc.id ? { ...a, status: "verified" } : a));
                                            showToast(`${acc.name} approved and live on Villa Stay`);
                                          } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't approve.", "error"); }
                                        }
                                      }}><ApproveIcon /></IconBtn>
                                      <IconBtn title="Reject" variant="reject" onClick={() => { setQuickRejectAcc(acc); setQuickRejectReason(""); }}><RejectIcon /></IconBtn>
                                    </>
                                  )}
                                </div>
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                    <TablePagination page={accsPag.page} totalPages={accsPag.totalPages} total={filteredAccs.length} perPage={5} onPage={accsPag.goTo} label="property" />
                  </Card>
                </>
              )}

              {/* Bookings sub-tab */}
              {staySubTab === "bookings" && (
                <>
                  <div className="flex items-center gap-3 bg-white border border-mist rounded-pill pl-5 pr-2 py-2 mb-4 shadow-card">
                    <SearchIcon className="w-4 h-4 text-ink-soft shrink-0" />
                    <input value={bookingSearchQ} onChange={(e) => { setBookingSearchQ(e.target.value); stayBookPag.reset(); }}
                      placeholder="Search by guest name or property…"
                      className="flex-1 bg-transparent border-none outline-none text-sm text-ink placeholder:text-ink-soft" />
                    {bookingSearchQ && <button onClick={() => { setBookingSearchQ(""); stayBookPag.reset(); }} className="text-ink-soft hover:text-ink px-2">×</button>}
                  </div>
                  <Card>
                    <CardHeader title={`${filteredStayBookings.length} booking${filteredStayBookings.length !== 1 ? "s" : ""}`} />
                    <div className="divide-y divide-mist">
                      {stayBookPag.paged.map((b) => {
                        const cfg: Record<string, { label: string; cls: string }> = {
                          pending:      { label: "Pending",    cls: "bg-[#FBF1E1] text-gold-deep border-gold" },
                          confirmed:    { label: "Confirmed",  cls: "bg-[#E8F2EC] text-forest border-forest" },
                          declined:     { label: "Declined",   cls: "bg-[#F5EAE6] text-clay border-clay" },
                          completed:    { label: "Completed",  cls: "bg-mist text-ink-soft border-mist" },
                          cancelled:    { label: "Cancelled",  cls: "bg-[#F5EAE6] text-clay border-clay" },
                          "checked-in": { label: "Checked in", cls: "bg-[#E8F2EC] text-forest border-forest" },
                        };
                        const { label, cls } = cfg[b.status] ?? cfg.pending;
                        return (
                          <div key={b.id} className="px-5 py-4 flex flex-wrap items-start justify-between gap-3 hover:bg-sage/30 transition-colors">
                            {/* Left — guest + property */}
                            <div className="min-w-0 flex-1">
                              <div className="flex items-center gap-2 flex-wrap mb-1">
                                <span className="font-semibold text-forest-deep">{b.guestName}</span>
                                <span className="text-xs text-ink-soft">{b.guestPhone}</span>
                              </div>
                              <div className="text-sm text-ink-soft">{b.accommodationName} · <span className="text-ink">{b.roomTypeName}</span></div>
                              <div className="text-xs text-ink-soft mt-0.5">{b.checkIn} → {b.checkOut} · {b.nights} night{b.nights !== 1 ? "s" : ""} · {b.guests} guest{b.guests !== 1 ? "s" : ""}</div>
                            </div>
                            {/* Right — amount + payment + status */}
                            <div className="flex flex-col items-end gap-1.5 shrink-0">
                              <span className={`inline-flex items-center gap-1 font-mono text-[10px] uppercase tracking-wider px-2.5 py-1 rounded-pill border font-medium ${cls}`}>
                                <span className="w-1.5 h-1.5 rounded-full bg-current" />{label}
                              </span>
                              <span className="font-mono font-semibold text-forest text-sm">GH₵ {b.totalPrice.toLocaleString()}</span>
                              <span className="text-[10px] text-ink-soft capitalize">{b.paymentMethod === "mobile-money" ? "Mobile money" : "Cash on arrival"}</span>
                            </div>
                          </div>
                        );
                      })}
                    </div>
                    <TablePagination page={stayBookPag.page} totalPages={stayBookPag.totalPages} total={filteredStayBookings.length} perPage={5} onPage={stayBookPag.goTo} label="booking" />
                  </Card>
                </>
              )}

              {/* KYC sub-tab */}
              {staySubTab === "kyc" && (
                <div className="flex flex-col gap-4">
                  {stayKycList.length === 0 ? (
                    <Card><div className="text-center py-12 text-sm text-ink-soft">No Stay KYC applications yet.</div></Card>
                  ) : (
                    stayKycPag.paged.map((app) => (
                      <Card key={app.id}>
                        <div className="flex flex-wrap items-center justify-between gap-4 p-5">
                          <div className="flex items-center gap-4">
                            <div className="w-12 h-12 rounded-full bg-mist flex items-center justify-center text-forest font-semibold text-xl shrink-0">{app.ownerName[0]}</div>
                            <div>
                              <div className="font-display font-semibold text-lg text-forest-deep">{app.ownerName}</div>
                              <div className="text-sm text-ink-soft capitalize mb-1">{app.ownerRole} · {app.propertyName}</div>
                              <div className="flex flex-wrap gap-2">
                                <span className="font-mono text-xs bg-sage border border-mist text-ink-soft px-2.5 py-1 rounded-pill">{app.docType}</span>
                                <span className="font-mono text-xs bg-sage border border-mist text-ink-soft px-2.5 py-1 rounded-pill">{app.propertyDocType}</span>
                                <span className="font-mono text-xs bg-sage border border-mist text-ink-soft px-2.5 py-1 rounded-pill">Submitted {app.submittedDate}</span>
                              </div>
                            </div>
                          </div>
                          <div className="flex items-center gap-3">
                            {app.status === "pending" ? (
                              <>
                                <StatusBadge status="pending" label="Pending review" />
                                <Btn variant="ghost" onClick={() => { setViewingStayKYC(app); setStayKycRejecting(false); setStayKycRejectReason(""); setStayKycApproving(false); }}>
                                  <ViewIcon className="w-4 h-4" />Review
                                </Btn>
                              </>
                            ) : app.status === "approved" ? (
                              <StatusBadge status="verified" label="KYC approved" />
                            ) : (
                              <div className="text-right">
                                <StatusBadge status="needs-changes" label="Rejected" />
                                {app.rejectionReason && <p className="text-xs text-ink-soft mt-1 max-w-[180px]">{app.rejectionReason}</p>}
                              </div>
                            )}
                          </div>
                        </div>
                      </Card>
                    ))
                  )}
                  <TablePagination page={stayKycPag.page} totalPages={stayKycPag.totalPages} total={stayKycList.length} perPage={5} onPage={stayKycPag.goTo} label="application" />
                </div>
              )}

              {/* Stay KYC Review Modal */}
              {viewingStayKYC && (
                <div className="fixed inset-0 z-[95] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4 py-6 overflow-y-auto">
                  <div className="bg-white rounded-xl border border-mist shadow-card-hover w-full max-w-2xl my-auto">
                    {/* Header */}
                    <div className="flex justify-between items-start px-6 py-5 border-b border-mist">
                      <div className="flex items-center gap-3">
                        <div className="w-12 h-12 rounded-full bg-mist flex items-center justify-center text-forest font-semibold text-lg shrink-0">
                          {viewingStayKYC.ownerName[0]}
                        </div>
                        <div>
                          <h3 className="font-display font-semibold text-xl text-forest-deep">{viewingStayKYC.ownerName}</h3>
                          <div className="text-sm text-ink-soft capitalize">{viewingStayKYC.ownerRole} · {viewingStayKYC.propertyName} · {viewingStayKYC.ownerPhone}</div>
                        </div>
                      </div>
                      <button onClick={() => setViewingStayKYC(null)} className="text-ink-soft hover:text-ink text-2xl leading-none mt-1">×</button>
                    </div>

                    <div className="p-6 grid grid-cols-1 md:grid-cols-2 gap-6">
                      {/* Personal details */}
                      <div>
                        <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-3">Personal details</div>
                        <div className="bg-sage rounded-md p-4">
                          {[
                            ["Full name",      viewingStayKYC.ownerName],
                            ["Phone",          viewingStayKYC.ownerPhone],
                            ["Role",           viewingStayKYC.ownerRole],
                            ["Property",       viewingStayKYC.propertyName],
                            ["Doc type",       viewingStayKYC.docType],
                            ["Doc number",     viewingStayKYC.docNumber],
                            ["Property doc",   viewingStayKYC.propertyDocType],
                            ["Doc file",       viewingStayKYC.propertyDocFile],
                            ["Submitted",      viewingStayKYC.submittedDate],
                          ].map(([l, v]) => (
                            <div key={l as string} className="flex justify-between py-2 border-b border-mist last:border-b-0 text-sm">
                              <span className="text-ink-soft">{l}</span>
                              <span className="font-medium text-right max-w-[55%] capitalize">{v}</span>
                            </div>
                          ))}
                        </div>
                      </div>

                      {/* Documents */}
                      <div className="flex flex-col gap-4">
                        <div>
                          <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-3">Identity documents</div>
                          <div className="flex gap-3">
                            {["Front of ID", "Back of ID"].map((label) => (
                              <div key={label} className="flex-1">
                                <div className="font-mono text-[10px] uppercase tracking-wider text-ink-soft mb-1">{label}</div>
                                <div className="h-28 bg-gradient-to-br from-mist to-sage border border-mist rounded-sm flex flex-col items-center justify-center gap-1 cursor-pointer hover:border-forest transition-colors">
                                  <svg viewBox="0 0 24 24" fill="none" stroke="#5B6B63" strokeWidth="1.6" className="w-5 h-5">
                                    <rect x="3" y="5" width="18" height="14" rx="2" /><circle cx="9" cy="10" r="2" />
                                    <path d="M21 17l-5-5-4 4-2-2-5 5" />
                                  </svg>
                                  <span className="text-[10px] text-ink-soft font-mono">ID photo</span>
                                </div>
                              </div>
                            ))}
                          </div>
                        </div>

                        <div>
                          <div className="font-mono text-[10px] uppercase tracking-wider text-ink-soft mb-1">Selfie with ID</div>
                          <div className="h-32 bg-ink rounded-sm flex flex-col items-center justify-center gap-2">
                            <svg viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="1.4" className="w-7 h-7 opacity-30">
                              <path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z" /><circle cx="12" cy="13" r="4" />
                            </svg>
                            <span className="text-xs text-white/40 font-mono">Selfie submitted</span>
                          </div>
                        </div>

                        <div>
                          <div className="font-mono text-[10px] uppercase tracking-wider text-ink-soft mb-1">Property authority document</div>
                          <div className="border border-mist rounded-sm overflow-hidden">
                            <div className="h-28 bg-gradient-to-br from-mist to-sage flex flex-col items-center justify-center gap-1.5">
                              <svg viewBox="0 0 24 24" fill="none" stroke="#5B6B63" strokeWidth="1.6" className="w-6 h-6">
                                <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" /><polyline points="14 2 14 8 20 8" />
                                <line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" />
                              </svg>
                              <span className="text-[10px] text-ink-soft font-mono">{viewingStayKYC.propertyDocFile}</span>
                            </div>
                            <div className="px-3 py-2 border-t border-mist flex items-center justify-between">
                              <span className="text-[10px] font-mono text-ink-soft capitalize">{viewingStayKYC.propertyDocType}</span>
                              <button className="text-xs font-semibold text-forest hover:underline">View document</button>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>

                    {/* Reject reason picker */}
                    {stayKycRejecting && (
                      <div className="px-6 pb-5 border-t border-mist pt-5">
                        <p className="text-sm text-ink-soft mb-3">Select a reason for rejecting <strong className="text-ink">{viewingStayKYC.ownerName}</strong>&apos;s KYC application:</p>
                        <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 mb-4">
                          {[
                            "ID document is blurry or unreadable",
                            "ID document appears expired",
                            "Selfie does not match ID document",
                            "Property authority document is invalid",
                            "Management letter is not signed",
                            "Owner phone verification failed",
                            "Suspected fraudulent documents",
                            "Other",
                          ].map((r) => (
                            <label key={r} className="flex items-center gap-2 text-sm cursor-pointer">
                              <input type="radio" name="stay-kyc-reject-reason" value={r} checked={stayKycRejectReason === r}
                                onChange={() => setStayKycRejectReason(r)} className="accent-clay w-4 h-4" />
                              {r}
                            </label>
                          ))}
                        </div>
                        <div className="flex gap-3">
                          <Btn variant="danger" disabled={!stayKycRejectReason} onClick={async () => {
                            try {
                              await clientExecute("stay-kyc.reject", { id: viewingStayKYC.id, reason: stayKycRejectReason });
                              setStayKycList((prev) => prev.filter((a) => a.id !== viewingStayKYC.id));
                              showToast(`${viewingStayKYC.ownerName}'s KYC rejected`, "info");
                              setViewingStayKYC(null); setStayKycRejecting(false); setStayKycRejectReason("");
                            } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't reject.", "error"); }
                          }}>Confirm rejection</Btn>
                          <Btn variant="ghost" onClick={() => { setStayKycRejecting(false); setStayKycRejectReason(""); }}>Cancel</Btn>
                        </div>
                      </div>
                    )}

                    {/* ── Approve confirmation panel ── */}
                    {stayKycApproving && !stayKycRejecting && (
                      <div className="px-6 pb-5 border-t border-mist pt-5 bg-[#E8F2EC]/50">
                        <div className="flex items-start gap-3 mb-5">
                          <div className="w-10 h-10 rounded-full bg-forest/10 flex items-center justify-center shrink-0 mt-0.5">
                            <svg viewBox="0 0 24 24" fill="none" stroke="#1E4A3D" strokeWidth="2" className="w-5 h-5">
                              <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                            </svg>
                          </div>
                          <div>
                            <div className="font-semibold text-forest-deep mb-1">
                              Approve KYC for {viewingStayKYC.ownerName}?
                            </div>
                            <p className="text-sm text-ink-soft">
                              This will verify them as a <strong className="capitalize">{viewingStayKYC.ownerRole}</strong> on Villa Stay. They will be notified and their property <strong>{viewingStayKYC.propertyName}</strong> will be eligible to go live.
                            </p>
                          </div>
                        </div>
                        <div className="flex gap-3">
                          <Btn onClick={async () => {
                            try {
                              await clientExecute("stay-kyc.approve", { id: viewingStayKYC.id });
                              setStayKycList((prev) => prev.filter((a) => a.id !== viewingStayKYC.id));
                              showToast(`${viewingStayKYC.ownerName} Stay KYC approved ✓`);
                              setViewingStayKYC(null); setStayKycApproving(false);
                            } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't approve.", "error"); }
                          }}>
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" className="w-4 h-4">
                              <path d="M5 12l5 5 9-11" strokeLinecap="round" strokeLinejoin="round" />
                            </svg>
                            Yes, approve KYC
                          </Btn>
                          <Btn variant="ghost" onClick={() => setStayKycApproving(false)}>Cancel</Btn>
                        </div>
                      </div>
                    )}

                    {/* Footer actions */}
                    {!stayKycRejecting && !stayKycApproving && (
                      <div className="flex flex-wrap justify-between items-center gap-3 px-6 py-5 border-t border-mist bg-sage/30">
                        <div className="flex gap-3">
                          <Btn variant="primary" onClick={() => setStayKycApproving(true)}>
                            <ApproveIcon className="w-4 h-4" />Approve KYC
                          </Btn>
                          <Btn variant="danger" onClick={() => setStayKycRejecting(true)}>
                            <RejectIcon className="w-4 h-4" />Reject
                          </Btn>
                        </div>
                        <Btn variant="ghost" onClick={() => setViewingStayKYC(null)}>Close</Btn>
                      </div>
                    )}
                  </div>
                </div>
              )}

              {/* Property view modal */}
              {viewingAcc && (
                <div className="fixed inset-0 z-[90] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4 py-6 overflow-y-auto">
                  <div className="bg-white rounded-xl border border-mist shadow-card-hover w-full max-w-2xl my-auto">
                    <div className="flex justify-between items-center px-6 py-4 border-b border-mist">
                      <div>
                        <h3 className="font-display font-semibold text-xl text-forest-deep">{viewingAcc.name}</h3>
                        <p className="text-xs text-ink-soft capitalize">{viewingAcc.type} · {viewingAcc.town}</p>
                      </div>
                      <button onClick={closeAccModal} className="text-ink-soft hover:text-ink text-2xl leading-none">×</button>
                    </div>
                    <div className="p-6 grid grid-cols-1 md:grid-cols-2 gap-6">
                      <div>
                        <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-3">Property details</div>
                        <div className="bg-sage rounded-md p-4">
                          {[
                            ["Address",    viewingAcc.address],
                            ["Owner",      viewingAcc.ownerName],
                            ["Role",       viewingAcc.ownerRole],
                            ["Phone",      viewingAcc.ownerPhone],
                            ["Check-in",   viewingAcc.checkInTime],
                            ["Check-out",  viewingAcc.checkOutTime],
                            ["Deposit",    viewingAcc.depositRequired ? `${viewingAcc.depositPercent}%` : "None"],
                            ["Rating",     `${viewingAcc.rating} / 5 (${viewingAcc.reviewCount} reviews)`],
                            ["Rooms",      String(viewingAcc.rooms.length)],
                            ["KYC status", viewingAcc.kycStatus],
                          ].map(([l, v]) => (
                            <div key={l as string} className="flex justify-between py-2 border-b border-mist last:border-b-0 text-sm">
                              <span className="text-ink-soft">{l}</span>
                              <span className="font-medium capitalize">{v}</span>
                            </div>
                          ))}
                          {viewingAcc.propertyOwnerName && (
                            <div className="mt-3 pt-3 border-t border-mist">
                              <div className="font-mono text-[10px] uppercase tracking-wider text-gold-deep mb-2">Property owner (real owner on file)</div>
                              <div className="text-sm font-semibold">{viewingAcc.propertyOwnerName}</div>
                              <div className="text-sm text-ink-soft">{viewingAcc.propertyOwnerPhone}</div>
                            </div>
                          )}
                        </div>
                      </div>
                      <div>
                        <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-3">Location</div>
                        <div className="bg-gradient-to-br from-mist to-sage border border-mist rounded-lg h-48 flex flex-col items-center justify-center gap-2 mb-3">
                          <svg viewBox="0 0 24 24" fill="none" stroke="#1E4A3D" strokeWidth="1.6" className="w-8 h-8 opacity-50">
                            <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z" /><circle cx="12" cy="10" r="3" />
                          </svg>
                          <span className="font-mono text-xs text-ink-soft">{viewingAcc.address}</span>
                          <span className="font-mono text-[10px] text-ink-soft">
                            {viewingAcc.latitude.toFixed(4)}, {viewingAcc.longitude.toFixed(4)}
                          </span>
                          <a
                            href={`https://www.google.com/maps?q=${viewingAcc.latitude},${viewingAcc.longitude}`}
                            target="_blank" rel="noopener noreferrer"
                            className="text-xs font-semibold text-forest hover:underline mt-1"
                          >
                            Open in Google Maps →
                          </a>
                        </div>
                        <div className="font-mono text-xs uppercase tracking-widest text-gold-deep mb-2">Amenities</div>
                        <div className="flex flex-wrap gap-1.5">
                          {viewingAcc.amenities.map((a) => (
                            <span key={a} className="text-[10px] font-mono bg-sage border border-mist text-ink-soft px-2 py-0.5 rounded-pill">{a}</span>
                          ))}
                        </div>
                      </div>
                    </div>
                    {/* ── Reject reason panel ── */}
                    {accRejecting && !accApproving && (
                      <div className="px-6 pb-5 border-t border-mist pt-5">
                        <p className="text-sm text-ink-soft mb-3">
                          Select a reason for rejecting <strong className="text-ink">{viewingAcc.name}</strong>. The owner will be notified.
                        </p>
                        <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 mb-4">
                          {ACC_REJECT_REASONS.map((r) => (
                            <label key={r} className="flex items-center gap-2 text-sm cursor-pointer">
                              <input type="radio" name="acc-reject-reason" value={r} checked={accRejectReason === r}
                                onChange={() => setAccRejectReason(r)} className="accent-clay w-4 h-4" />
                              {r}
                            </label>
                          ))}
                        </div>
                        {accRejectReason === "Other" && (
                          <textarea placeholder="Describe the reason…" rows={2}
                            className="w-full border border-mist rounded-sm px-3 py-2 text-sm mb-4 focus:outline-2 focus:outline-gold" />
                        )}
                        <div className="flex gap-3">
                          <Btn variant="danger" disabled={!accRejectReason} onClick={async () => {
                            try {
                              await clientExecute("accommodation.reject", { id: viewingAcc.id, reason: accRejectReason });
                              setStayAccList((prev) => prev.map((a) => a.id === viewingAcc.id ? { ...a, status: "unavailable" } : a));
                              showToast(`${viewingAcc.name} rejected — owner notified`, "info");
                              closeAccModal();
                            } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't reject.", "error"); }
                          }}>
                            Confirm rejection
                          </Btn>
                          <Btn variant="ghost" onClick={() => { setAccRejecting(false); setAccRejectReason(""); }}>Cancel</Btn>
                        </div>
                      </div>
                    )}

                    {/* ── Default footer ── */}
                    {!accApproving && !accRejecting && (
                      <div className="flex justify-between items-center px-6 pb-5 border-t border-mist pt-4">
                        <a href={`/stay/${viewingAcc.id}`} target="_blank" rel="noopener noreferrer"
                          className="text-sm font-semibold text-forest hover:underline">View public listing →</a>
                        <div className="flex items-center gap-3">
                          {viewingAcc.status === "pending" && (
                            <>
                              <Btn variant="primary" onClick={async () => {
                                const ok = await confirm({
                                  title: "Approve this listing?",
                                  body: `"${viewingAcc.name}" will go live on Villa Stay and guests will be able to search and book it.`,
                                  confirmLabel: "Approve",
                                });
                                if (ok) {
                                  try {
                                    await clientExecute("accommodation.approve", { id: viewingAcc.id });
                                    setStayAccList((prev) => prev.map((a) => a.id === viewingAcc.id ? { ...a, status: "verified" } : a));
                                    showToast(`${viewingAcc.name} approved and live on Villa Stay`);
                                    closeAccModal();
                                  } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't approve.", "error"); }
                                }
                              }}>
                                <ApproveIcon className="w-4 h-4" />Approve
                              </Btn>
                              <Btn variant="danger" onClick={() => setAccRejecting(true)}>
                                <RejectIcon className="w-4 h-4" />Reject
                              </Btn>
                            </>
                          )}
                          <Btn variant="ghost" onClick={closeAccModal}>Close</Btn>
                        </div>
                      </div>
                    )}
                  </div>
                </div>
              )}
            </div>
          )}

          {/* ── Messages ── */}
          {section === "messages" && (
            <div>
              <h2 className="font-display font-semibold text-xl text-forest-deep mb-4">Messages</h2>
              <MessageThread myName="Villa Admin" />
            </div>
          )}

        </div>
      </div>

      {/* Modals */}
      {viewingKYC && (
        <KYCReviewModal
          app={viewingKYC}
          onApprove={() => handleApproveKYC(viewingKYC)}
          onReject={(reason) => handleRejectKYC(viewingKYC, reason)}
          onClose={() => setViewingKYC(null)}
        />
      )}
      {viewingProp && (
        <PropertyDetailModal
          review={viewingProp}
          approving={propApproving}
          rejecting={propRejecting}
          rejectReason={propRejectReason}
          rejectReasons={PROP_REJECT_REASONS}
          onApprove={() => { approveProperty(viewingProp); closePropModal(); }}
          onReject={(reason) => { rejectProperty(viewingProp, reason); closePropModal(); }}
          onSetApproving={setPropApproving}
          onSetRejecting={setPropRejecting}
          onSetRejectReason={setPropRejectReason}
          onClose={closePropModal}
        />
      )}
      {viewingUser && <UserDetailModal user={viewingUser} onClose={() => setViewingUser(null)} />}

      {/* Quick reject modal for Villa Stay properties */}
      {quickRejectAcc && (
        <div className="fixed inset-0 z-[95] flex items-center justify-center bg-ink/40 backdrop-blur-sm px-4">
          <div className="bg-white rounded-xl border border-mist shadow-card-hover w-full max-w-md">
            <div className="flex justify-between items-center px-6 py-5 border-b border-mist">
              <div>
                <h3 className="font-display font-semibold text-lg text-forest-deep">Reject this listing?</h3>
                <p className="text-xs text-ink-soft mt-0.5">{quickRejectAcc.name}</p>
              </div>
              <button onClick={() => { setQuickRejectAcc(null); setQuickRejectReason(""); }} className="text-ink-soft hover:text-ink text-2xl leading-none">×</button>
            </div>
            <div className="p-6">
              <p className="text-sm text-ink-soft mb-4">Select a reason — the property owner will be notified.</p>
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 mb-5">
                {ACC_REJECT_REASONS.map((r) => (
                  <label key={r} className="flex items-center gap-2 text-sm cursor-pointer">
                    <input type="radio" name="quick-acc-reject" value={r} checked={quickRejectReason === r}
                      onChange={() => setQuickRejectReason(r)} className="accent-clay w-4 h-4" />
                    {r}
                  </label>
                ))}
              </div>
              {quickRejectReason === "Other" && (
                <textarea placeholder="Describe the reason…" rows={2}
                  className="w-full border border-mist rounded-sm px-3 py-2 text-sm mb-4 focus:outline-2 focus:outline-gold resize-none" />
              )}
            </div>
            <div className="flex justify-between items-center px-6 pb-5 border-t border-mist pt-4">
              <Btn variant="ghost" onClick={() => { setQuickRejectAcc(null); setQuickRejectReason(""); }}>Cancel</Btn>
              <Btn variant="danger" disabled={!quickRejectReason} onClick={async () => {
                try {
                  await clientExecute("accommodation.reject", { id: quickRejectAcc.id, reason: quickRejectReason });
                  setStayAccList((prev) => prev.map((a) => a.id === quickRejectAcc.id ? { ...a, status: "unavailable" } : a));
                  showToast(`${quickRejectAcc.name} rejected — owner notified`, "info");
                  setQuickRejectAcc(null); setQuickRejectReason("");
                } catch (e) { showToast(e instanceof ApiError ? e.message : "Couldn't reject.", "error"); }
              }}>
                Confirm rejection
              </Btn>
            </div>
          </div>
        </div>
      )}

      {confirmNode}
      {toastNode}
    </div>
  );
}
