import { useEffect, useState, Fragment } from "react";
import ImportSpreadsheetDialog from "@/components/ImportSpreadsheetDialog";
import { supabase } from "@/integrations/supabase/client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Checkbox } from "@/components/ui/checkbox";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Card, CardContent } from "@/components/ui/card";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, DropdownMenuLabel, DropdownMenuSeparator } from "@/components/ui/dropdown-menu";
import { useToast } from "@/hooks/use-toast";
import { Plus, Search, Edit2, Trash2, FileText, Upload, Users, Download, Eye, EyeOff, ChevronRight, ChevronDown, CheckCircle2, XCircle, Archive, ContactRound, Printer, Mail, Phone, Home, MapPin, GripVertical, Building2 } from "lucide-react";
import { DndContext, closestCenter, PointerSensor, useSensor, useSensors, type DragEndEvent } from "@dnd-kit/core";
import { SortableContext, useSortable, verticalListSortingStrategy, arrayMove } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import PrintableContactCards from "@/components/owners/PrintableContactCards";
import NotifyOwnersDialog from "@/components/NotifyOwnersDialog";
import { NotifyOwnersProvider } from "@/contexts/NotifyOwnersContext";
import { Switch } from "@/components/ui/switch";
import { Badge } from "@/components/ui/badge";
import { useAuth } from "@/contexts/AuthContext";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";

interface Owner {
  id: string;
  owner_type?: "individual" | "business";
  business_name?: string | null;
  management_company?: string | null;
  management_contact_name?: string | null;
  management_contact_title?: string | null;
  management_contact_email?: string | null;
  management_contact_phone?: string | null;
  first_name: string;
  last_name: string;
  email: string | null;
  phone: string | null;
  street_address: string | null;
  mailing_address: string | null;
  property_address: string | null;
  account_number?: string | null;
  balance: number | null;
  unit_id: string | null;
  association_id: string;
  electronic_consent: boolean;
  show_proxy_text: boolean;
  exclude_from_signin: boolean;
  is_designated_voter: boolean;
  alternate_address_1: string | null;
  alternate_address_2: string | null;
  zoho_contact_id: string | null;
  status?: string;
  designations?: string[] | null;
  units?: { unit_number: string; account_number: string | null } | null;
}

const DESIGNATION_OPTIONS = [
  "Board President",
  "Board Vice President",
  "Board Secretary",
  "Board Treasurer",
  "Board Member",
  "ARC Member",
  "Fining Committee",
  "CAM",
  "Property Manager",
  "Management Company",
] as const;

interface Association {
  id: string;
  name: string;
}

interface OwnerPermissions {
  canRead: boolean;
  canCreate: boolean;
  canEdit: boolean;
  canDelete: boolean;
}

interface ImportedOwnerPayload {
  association_id: string;
  zoho_contact_id: string | null;
  first_name: string;
  last_name: string;
  account_number?: string | null;
  street_address: string | null;
  property_address: string | null;
  mailing_address: string | null;
  alternate_address_1: string | null;
  alternate_address_2: string | null;
  phone: string | null;
  email: string | null;
  balance: number;
  unit_id: string | null;
  updated_at?: string;
}

const NO_OWNER_PERMISSIONS: OwnerPermissions = {
  canRead: false,
  canCreate: false,
  canEdit: false,
  canDelete: false,
};

const OWNER_FEATURE_AREA = "Owners & Units";

const ownerFormSchema = z.object({
  owner_type: z.enum(["individual", "business"]),
  owner_name: z.string().trim().max(150),
  business_name: z.string().trim().max(150),
  management_company: z.string().trim().max(150),
  management_contact_name: z.string().trim().max(150),
  management_contact_title: z.string().trim().max(100),
  management_contact_email: z.string().trim().email("Enter a valid management contact email.").max(255).or(z.literal("")),
  management_contact_phone: z.string().trim().max(40),
  email: z.string().trim().email("Enter a valid owner email.").max(255).or(z.literal("")),
  phone: z.string().trim().max(40),
  property_address: z.string().trim().max(255),
  street_address: z.string().trim().max(255),
  mailing_address: z.string().trim().max(1000),
  alternate_address_1: z.string().trim().max(1000),
  alternate_address_2: z.string().trim().max(1000),
  balance: z.string().trim().max(30),
  zoho_contact_id: z.string().trim().max(100),
}).superRefine((value, ctx) => {
  if (value.owner_type === "individual" && !value.owner_name.trim()) {
    ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["owner_name"], message: "Owner name is required." });
  }
  if (value.owner_type === "business" && !value.business_name.trim()) {
    ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["business_name"], message: "Business name is required." });
  }
});

const normalizeImportedOwnerValue = (value: string | null | undefined) =>
  String(value ?? "")
    .trim()
    .replace(/\s+/g, " ")
    .toLowerCase();

const toNullableImportedValue = (value: string | null | undefined) => {
  const trimmed = String(value ?? "").trim();
  return trimmed.length > 0 ? trimmed : null;
};

const splitImportedOwnerName = (value: string | null | undefined) => {
  const parts = String(value ?? "")
    .trim()
    .replace(/\s+/g, " ")
    .split(" ")
    .filter(Boolean);

  return {
    first_name: parts[0] || "Unknown",
    last_name: parts.slice(1).join(" ") || "",
  };
};

const getImportedOwnerPropertyKey = (firstName: string, lastName: string, propertyAddress: string | null) => {
  const normalizedProperty = normalizeImportedOwnerValue(propertyAddress);
  if (!normalizedProperty) return null;

  return [
    normalizeImportedOwnerValue(firstName),
    normalizeImportedOwnerValue(lastName),
    normalizedProperty,
  ].join("::");
};

const getImportedOwnerUnitKey = (unitId: string | null, firstName: string, lastName: string) => {
  const normalizedUnitId = normalizeImportedOwnerValue(unitId);
  if (!normalizedUnitId) return null;

  return [
    normalizedUnitId,
    normalizeImportedOwnerValue(firstName),
    normalizeImportedOwnerValue(lastName),
  ].join("::");
};

const getImportedOwnerAccountKey = (accountNumber: string | null, firstName: string, lastName: string) => {
  const normalizedAccountNumber = normalizeImportedOwnerValue(accountNumber);
  if (!normalizedAccountNumber) return null;

  return [
    normalizeImportedOwnerValue(firstName),
    normalizeImportedOwnerValue(lastName),
    normalizedAccountNumber,
  ].join("::");
};

const IMPORT_LOOKUP_PAGE_SIZE = 1000;

const fetchAllAssociationUnitsForImport = async (associationId: string) => {
  const allUnits: Array<{ id: string; unit_number: string | null; account_number: string | null }> = [];

  for (let from = 0; ; from += IMPORT_LOOKUP_PAGE_SIZE) {
    const { data, error } = await supabase
      .from("units")
      .select("id, unit_number, account_number")
      .eq("association_id", associationId)
      .range(from, from + IMPORT_LOOKUP_PAGE_SIZE - 1);

    if (error) throw error;
    if (!data?.length) break;

    allUnits.push(...data);

    if (data.length < IMPORT_LOOKUP_PAGE_SIZE) break;
  }

  return allUnits;
};

const fetchAllAssociationOwnersForImport = async (associationId: string) => {
  const allOwners: Array<{
    id: string;
    first_name: string;
    last_name: string;
    property_address: string | null;
    unit_id: string | null;
    account_number: string | null;
  }> = [];

  for (let from = 0; ; from += IMPORT_LOOKUP_PAGE_SIZE) {
    const { data, error } = await supabase
      .from("owners")
      .select("id, first_name, last_name, property_address, unit_id, account_number")
      .eq("association_id", associationId)
      .range(from, from + IMPORT_LOOKUP_PAGE_SIZE - 1);

    if (error) throw error;
    if (!data?.length) break;

    allOwners.push(...data);

    if (data.length < IMPORT_LOOKUP_PAGE_SIZE) break;
  }

  return allOwners;
};

// Per-owner editable slot used in the tabbed unit dialog (Owner 1 / Owner 2)
interface OwnerSlotForm {
  id: string | null; // existing owner id, or null for a new owner being added
  enabled: boolean; // whether this slot is being saved
  owner_name: string;
  email: string;
  phone: string;
  mailing_address: string;
}

// Combined form state for a single unit's editing dialog
interface UnitOwnerFormState {
  unit_id: string;
  property_address: string;
  street_address: string;
  balance: string;
  owner1: OwnerSlotForm;
  owner2: OwnerSlotForm;
  alternate_address_1: string;
  alternate_address_2: string;
  electronic_consent_1: boolean;
  electronic_consent_2: boolean;
  show_proxy_text: boolean;
  is_designated_voter_id: string | null; // owner id flagged as designated voter
  zoho_contact_id_1: string;
  zoho_contact_id_2: string;
}

const emptySlot = (): OwnerSlotForm => ({
  id: null,
  enabled: false,
  owner_name: "",
  email: "",
  phone: "",
  mailing_address: "",
});

const createEmptyUnitForm = (): UnitOwnerFormState => ({
  unit_id: "",
  property_address: "",
  street_address: "",
  balance: "0.00",
  owner1: { ...emptySlot(), enabled: true },
  owner2: emptySlot(),
  alternate_address_1: "",
  alternate_address_2: "",
  electronic_consent_1: false,
  electronic_consent_2: false,
  show_proxy_text: true,
  is_designated_voter_id: null,
  zoho_contact_id_1: "",
  zoho_contact_id_2: "",
});

const ownerToSlot = (owner: Owner): OwnerSlotForm => ({
  id: owner.id,
  enabled: true,
  owner_name: `${owner.first_name || ""} ${owner.last_name || ""}`.trim(),
  email: owner.email || "",
  phone: owner.phone || "",
  mailing_address: owner.mailing_address || "",
});

function SortableOwnerRow({ owner, index }: { owner: Owner; index: number }) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: owner.id });
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  };
  const name = owner.owner_type === "business"
    ? (owner.business_name || `${owner.first_name || ""} ${owner.last_name || ""}`.trim())
    : `${owner.first_name || ""} ${owner.last_name || ""}`.trim();
  return (
    <div ref={setNodeRef} style={style} className="flex items-center gap-2 rounded-md border border-border bg-card p-2">
      <button type="button" className="cursor-grab touch-none text-muted-foreground hover:text-foreground" {...attributes} {...listeners}>
        <GripVertical className="h-4 w-4" />
      </button>
      <span className="text-xs font-semibold text-muted-foreground w-6">#{index + 1}</span>
      <span className="text-sm font-medium truncate">{name || "(unnamed)"}</span>
      {owner.email && <span className="ml-auto text-[11px] text-muted-foreground truncate">{owner.email}</span>}
    </div>
  );
}

function OwnerPriorityList({ owners, onReorder }: { owners: Owner[]; onReorder: (next: Owner[]) => void }) {
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;
    if (!over || active.id === over.id) return;
    const oldIndex = owners.findIndex((o) => o.id === active.id);
    const newIndex = owners.findIndex((o) => o.id === over.id);
    if (oldIndex === -1 || newIndex === -1) return;
    onReorder(arrayMove(owners, oldIndex, newIndex));
  };
  return (
    <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
      <SortableContext items={owners.map((o) => o.id)} strategy={verticalListSortingStrategy}>
        <div className="space-y-1.5">
          {owners.map((o, idx) => (
            <SortableOwnerRow key={o.id} owner={o} index={idx} />
          ))}
        </div>
      </SortableContext>
    </DndContext>
  );
}

export default function OwnersPage() {
  const { user } = useAuth();
  const [owners, setOwners] = useState<Owner[]>([]);
  const [associations, setAssociations] = useState<Association[]>([]);
  const [units, setUnits] = useState<{ id: string; unit_number: string }[]>([]);
  const [selectedAssociation, setSelectedAssociation] = useState<string>("");
  const [loading, setLoading] = useState(true);
  const [permissionLoading, setPermissionLoading] = useState(true);
  const [permissions, setPermissions] = useState<OwnerPermissions>(NO_OWNER_PERMISSIONS);
  const [search, setSearch] = useState("");
  const [addDialogOpen, setAddDialogOpen] = useState(false);
  const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
  const [editingOwner, setEditingOwner] = useState<Owner | null>(null);
  const [proxyTextOn, setProxyTextOn] = useState(true);
  const [showArchived, setShowArchived] = useState(false);
  const [addTab, setAddTab] = useState("details");
  const [selectedOwnerIds, setSelectedOwnerIds] = useState<Set<string>>(new Set());
  const [bulkDeleteDialogOpen, setBulkDeleteDialogOpen] = useState(false);
  const [bulkOnboarding, setBulkOnboarding] = useState(false);
  const [composeDialogOpen, setComposeDialogOpen] = useState(false);
  const [tenantRequestOpen, setTenantRequestOpen] = useState(false);
  const [tenantRequestMessage, setTenantRequestMessage] = useState("");
  const [tenantRequestSending, setTenantRequestSending] = useState(false);
  const [contactCardsOpen, setContactCardsOpen] = useState(false);
  const [contactCardOwners, setContactCardOwners] = useState<Owner[] | null>(null);
  const [expandedUnits, setExpandedUnits] = useState<Set<string>>(new Set());
  const [unitDialogOpen, setUnitDialogOpen] = useState(false);
  const [unitDialogGroup, setUnitDialogGroup] = useState<Owner[]>([]);
  const [unitDialogTab, setUnitDialogTab] = useState("owner1");
  const [ownerOrder, setOwnerOrder] = useState<Owner[]>([]);
  const [unitForm, setUnitForm] = useState<UnitOwnerFormState>(createEmptyUnitForm());
  const { toast } = useToast();

  const handleSendTenantInfoRequests = async () => {
    const ownerIds = Array.from(selectedOwnerIds);
    if (ownerIds.length === 0) return;
    setTenantRequestSending(true);
    try {
      const { data, error } = await supabase.functions.invoke("send-tenant-info-request", {
        body: { owner_ids: ownerIds, custom_message: tenantRequestMessage.trim() || null },
      });
      if (error || data?.error) {
        toast({ variant: "destructive", title: "Could not send requests", description: error?.message || data?.error });
        return;
      }
      const sent = data?.sent ?? 0;
      const total = data?.total ?? ownerIds.length;
      const failed = total - sent;
      const resultErrors = Array.isArray(data?.results)
        ? data.results.filter((result: any) => !result.ok && result.error).map((result: any) => result.error)
        : [];
      const uniqueErrors = Array.from(new Set(resultErrors)).slice(0, 3);
      toast({
        title: sent > 0 ? "Tenant info requests sent" : "No tenant info requests sent",
        description: failed > 0
          ? `Sent ${sent} of ${total}. ${failed} could not be delivered${uniqueErrors.length ? `: ${uniqueErrors.join("; ")}` : " (missing email or send error)"}.`
          : `Sent ${sent} request${sent === 1 ? "" : "s"}.`,
        variant: sent > 0 && failed === 0 ? "default" : "destructive",
      });
      if (sent > 0) {
        setTenantRequestOpen(false);
        setSelectedOwnerIds(new Set());
      }
    } catch (err: any) {
      toast({ variant: "destructive", title: "Could not send requests", description: err?.message || "Unknown error" });
    } finally {
      setTenantRequestSending(false);
    }
  };

  const [form, setForm] = useState({
    owner_type: "individual" as "individual" | "business",
    business_name: "",
    management_company: "",
    management_contact_name: "",
    management_contact_title: "",
    management_contact_email: "",
    management_contact_phone: "",
    unit_id: "",
    owner_name: "",
    street_address: "",
    property_address: "",
    email: "",
    phone: "",
    balance: "0.00",
    electronic_consent: false,
    show_proxy_text: true,
    is_designated_voter: false,
    mailing_address: "",
    alternate_address_1: "",
    alternate_address_2: "",
    zoho_contact_id: "",
  });

  const showPermissionToast = (action: string) => {
    toast({
      title: "Permission required",
      description: `You don't have permission to ${action} in Owner Management.`,
      variant: "destructive",
    });
  };

  useEffect(() => {
    supabase.from("associations").select("id, name").eq("status", "active").order("name").then(({ data }) => {
      if (data) {
        setAssociations(data);
        if (data.length > 0) setSelectedAssociation(data[0].id);
      }
    });
  }, []);

  useEffect(() => {
    const fetchPermissions = async () => {
      if (!user) {
        setPermissions(NO_OWNER_PERMISSIONS);
        setPermissionLoading(false);
        return;
      }

      setPermissionLoading(true);

      const { data: rolesData, error: rolesError } = await supabase
        .from("user_roles")
        .select("role")
        .eq("user_id", user.id);

      if (rolesError) {
        setPermissions(NO_OWNER_PERMISSIONS);
        setPermissionLoading(false);
        toast({ title: "Error", description: rolesError.message, variant: "destructive" });
        return;
      }

      const roles = (rolesData || []).map((entry) => entry.role);

      if (roles.includes("admin") || roles.includes("manager")) {
        setPermissions({ canRead: true, canCreate: true, canEdit: true, canDelete: true });
        setPermissionLoading(false);
        return;
      }

      if (roles.length === 0) {
        setPermissions(NO_OWNER_PERMISSIONS);
        setPermissionLoading(false);
        return;
      }

      const { data: permissionRows, error: permissionsError } = await supabase
        .from("role_permissions")
        .select("can_read, can_create, can_edit, can_delete")
        .in("role", roles)
        .eq("feature_area", OWNER_FEATURE_AREA);

      if (permissionsError) {
        setPermissions(NO_OWNER_PERMISSIONS);
        toast({ title: "Error", description: permissionsError.message, variant: "destructive" });
      } else {
        setPermissions({
          canRead: (permissionRows || []).some((row) => row.can_read),
          canCreate: (permissionRows || []).some((row) => row.can_create),
          canEdit: (permissionRows || []).some((row) => row.can_edit),
          canDelete: (permissionRows || []).some((row) => row.can_delete),
        });
      }

      setPermissionLoading(false);
    };

    fetchPermissions();
  }, [user, toast]);

  useEffect(() => {
    if (!selectedAssociation || permissionLoading) return;

    if (!permissions.canRead) {
      setOwners([]);
      setUnits([]);
      setLoading(false);
      return;
    }

    fetchOwners();
    fetchUnits();
  }, [selectedAssociation, permissionLoading, permissions.canRead]);

  const fetchOwners = async () => {
    if (!permissions.canRead) return;

    setLoading(true);
    const { data } = await supabase
      .from("owners")
      .select("*, units(unit_number, account_number)")
      .eq("association_id", selectedAssociation)
      .order("last_name");
    if (data) setOwners(data as Owner[]);
    setLoading(false);
  };

  const fetchUnits = async () => {
    if (!permissions.canRead) return;

    const { data } = await supabase
      .from("units")
      .select("id, unit_number")
      .eq("association_id", selectedAssociation)
      .order("unit_number");
    if (data) setUnits(data);
  };

  const resetForm = () => {
    setForm({
      owner_type: "individual",
      business_name: "",
      management_company: "",
      management_contact_name: "",
      management_contact_title: "",
      management_contact_email: "",
      management_contact_phone: "",
      unit_id: "",
      owner_name: "",
      street_address: "",
      property_address: "",
      email: "",
      phone: "",
      balance: "0.00",
      electronic_consent: false,
      show_proxy_text: true,
      is_designated_voter: false,
      mailing_address: "",
      alternate_address_1: "",
      alternate_address_2: "",
      zoho_contact_id: "",
    });
    setAddTab("details");
    setEditingOwner(null);
  };

  const handleOpenAdd = () => {
    if (!permissions.canCreate) {
      showPermissionToast("add owners");
      return;
    }

    resetForm();
    setAddDialogOpen(true);
  };

  const handleOpenEdit = (owner: Owner, initialTab: string = "details") => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }

    setEditingOwner(owner);
    setForm({
      owner_type: owner.owner_type || "individual",
      business_name: owner.business_name || "",
      management_company: owner.management_company || "",
      management_contact_name: owner.management_contact_name || "",
      management_contact_title: owner.management_contact_title || "",
      management_contact_email: owner.management_contact_email || "",
      management_contact_phone: owner.management_contact_phone || "",
      unit_id: owner.unit_id || "",
      owner_name: owner.owner_type === "business" ? "" : `${owner.first_name} ${owner.last_name}`,
      street_address: owner.street_address || "",
      property_address: owner.property_address || "",
      email: owner.email || "",
      phone: owner.phone || "",
      balance: String(owner.balance ?? "0.00"),
      electronic_consent: owner.electronic_consent ?? false,
      show_proxy_text: owner.show_proxy_text ?? true,
      is_designated_voter: (owner as any).is_designated_voter ?? false,
      mailing_address: owner.mailing_address || "",
      alternate_address_1: owner.alternate_address_1 || "",
      alternate_address_2: owner.alternate_address_2 || "",
      zoho_contact_id: owner.zoho_contact_id || "",
    });
    setAddTab(initialTab);
    setAddDialogOpen(true);
  };

  const handleSave = async () => {
    if (editingOwner && !permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }

    if (!editingOwner && !permissions.canCreate) {
      showPermissionToast("add owners");
      return;
    }

    const validation = ownerFormSchema.safeParse(form);
    if (!validation.success) {
      toast({ title: "Check owner details", description: validation.error.issues[0]?.message, variant: "destructive" });
      return;
    }

    const isBusiness = form.owner_type === "business";
    const nameParts = form.owner_name.trim().split(" ").filter(Boolean);
    const first_name = isBusiness ? form.business_name.trim() : (nameParts[0] || "");
    const last_name = isBusiness ? "" : (nameParts.slice(1).join(" ") || "");

    const payload: any = {
      owner_type: form.owner_type,
      business_name: isBusiness ? form.business_name.trim() : null,
      management_company: isBusiness ? form.management_company.trim() || null : null,
      management_contact_name: isBusiness ? form.management_contact_name.trim() || null : null,
      management_contact_title: isBusiness ? form.management_contact_title.trim() || null : null,
      management_contact_email: isBusiness ? form.management_contact_email.trim() || null : null,
      management_contact_phone: isBusiness ? form.management_contact_phone.trim() || null : null,
      first_name,
      last_name,
      unit_id: form.unit_id || null,
      street_address: form.street_address || null,
      property_address: form.property_address || null,
      email: (isBusiness ? form.management_contact_email : form.email) || null,
      phone: (isBusiness ? form.management_contact_phone : form.phone) || null,
      balance: parseFloat(form.balance) || 0,
      electronic_consent: form.electronic_consent,
      show_proxy_text: form.show_proxy_text,
      is_designated_voter: form.is_designated_voter,
      mailing_address: form.mailing_address || null,
      alternate_address_1: form.alternate_address_1 || null,
      alternate_address_2: form.alternate_address_2 || null,
      zoho_contact_id: form.zoho_contact_id || null,
    };

    if (editingOwner) {
      const { error } = await supabase
        .from("owners")
        .update({ ...payload, updated_at: new Date().toISOString() })
        .eq("id", editingOwner.id);

      if (error) {
        toast({ title: "Error", description: error.message, variant: "destructive" });
        return;
      }

      toast({ title: "Owner updated" });
    } else {
      payload.association_id = selectedAssociation;
      const { data: insertData, error } = await supabase.from("owners").insert(payload).select();
      if (error) {
        toast({ title: "Error", description: error.message, variant: "destructive" });
        return;
      }
      toast({ title: "Owner added" });
    }

    setAddDialogOpen(false);
    resetForm();
    fetchOwners();
  };

  const handleDelete = async (id: string) => {
    if (!permissions.canDelete) {
      showPermissionToast("delete owners");
      return;
    }

    const { error } = await supabase.from("owners").delete().eq("id", id);
    if (error) toast({ title: "Error", description: error.message, variant: "destructive" });
    else {
      toast({ title: "Owner deleted" });
      fetchOwners();
    }
  };

  const handleBulkDelete = async () => {
    if (!permissions.canDelete) {
      showPermissionToast("delete owners");
      return;
    }
    const ids = Array.from(selectedOwnerIds);
    if (ids.length === 0) return;

    try {
      // Delete owners in smaller batches to avoid issues
      for (const id of ids) {
        const { error } = await supabase.from("owners").delete().eq("id", id);
        if (error) {
          console.error("Error deleting owner", id, error);
          throw error;
        }
      }
      toast({ title: `${ids.length} owner(s) deleted` });
      setSelectedOwnerIds(new Set());
      setBulkDeleteDialogOpen(false);
      fetchOwners();
    } catch (err: any) {
      console.error("Bulk delete error:", err);
      toast({ title: "Error deleting owners", description: err.message, variant: "destructive" });
    }
  };

  const handleBulkOnboardOwners = async () => {
    if (!permissions.canCreate) {
      showPermissionToast("invite owners");
      return;
    }
    const ids = Array.from(selectedOwnerIds);
    if (ids.length === 0) return;

    setBulkOnboarding(true);
    try {
      const { data, error } = await supabase.functions.invoke("admin-user-management", {
        body: { action: "bulk_onboard_owners", owner_ids: ids },
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      toast({
        title: "Owner invitations sent",
        description: `${data.sent || 0} email(s) sent, ${data.linked || 0} owner(s) linked.${data.errors?.length ? ` ${data.errors.length} issue(s).` : ""}`,
        variant: data.errors?.length ? "destructive" : "default",
      });
      setSelectedOwnerIds(new Set());
      fetchOwners();
    } catch (err: any) {
      toast({ title: "Error inviting owners", description: err.message, variant: "destructive" });
    } finally {
      setBulkOnboarding(false);
    }
  };

  const toggleOwnerSelection = (id: string) => {
    setSelectedOwnerIds(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  const toggleSelectAll = () => {
    if (selectedOwnerIds.size === filtered.length) {
      setSelectedOwnerIds(new Set());
    } else {
      setSelectedOwnerIds(new Set(filtered.map(o => o.id)));
    }
  };

  const handleToggleExcludeProxy = async (owner: Owner) => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }

    await supabase.from("owners").update({ show_proxy_text: !owner.show_proxy_text }).eq("id", owner.id);
    fetchOwners();
  };

  const toggleUnitExpansion = (key: string) => {
    setExpandedUnits((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key); else next.add(key);
      return next;
    });
  };

  const handleOpenEditUnit = (group: Owner[]) => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }
    const sorted = [...group].sort((a, b) => {
      // Designated voter first, otherwise by created order (assume current order)
      if (a.is_designated_voter && !b.is_designated_voter) return -1;
      if (!a.is_designated_voter && b.is_designated_voter) return 1;
      return 0;
    });
    const o1 = sorted[0];
    const o2 = sorted[1];

    // Collect alt addresses across the group, dedupe vs. primary mailing
    const primaryMailing = (o1?.mailing_address || o1?.property_address || "").trim().toLowerCase();
    const altSet: string[] = [];
    const seen = new Set<string>([primaryMailing].filter(Boolean));
    for (const o of sorted) {
      for (const cand of [o.alternate_address_1, o.alternate_address_2]) {
        const t = (cand || "").trim();
        if (t && !seen.has(t.toLowerCase())) {
          seen.add(t.toLowerCase());
          altSet.push(t);
          if (altSet.length >= 2) break;
        }
      }
      if (altSet.length >= 2) break;
    }

    setUnitDialogGroup(sorted);
    setOwnerOrder(sorted);
    setUnitForm({
      unit_id: o1?.unit_id || "",
      property_address: o1?.property_address || "",
      street_address: o1?.street_address || "",
      balance: String(o1?.balance ?? "0.00"),
      owner1: o1 ? ownerToSlot(o1) : { ...emptySlot(), enabled: true },
      owner2: o2 ? ownerToSlot(o2) : emptySlot(),
      alternate_address_1: altSet[0] || "",
      alternate_address_2: altSet[1] || "",
      electronic_consent_1: o1?.electronic_consent ?? false,
      electronic_consent_2: o2?.electronic_consent ?? false,
      show_proxy_text: o1?.show_proxy_text ?? true,
      is_designated_voter_id: sorted.find((o) => o.is_designated_voter)?.id || null,
      zoho_contact_id_1: o1?.zoho_contact_id || "",
      zoho_contact_id_2: o2?.zoho_contact_id || "",
    });
    setUnitDialogTab("owner1");
    setUnitDialogOpen(true);
  };

  const handleSaveUnit = async () => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }
    if (!unitForm.owner1.enabled || !unitForm.owner1.owner_name.trim()) {
      toast({ title: "Owner 1 name is required", variant: "destructive" });
      return;
    }

    const splitName = (full: string) => {
      const parts = full.trim().split(/\s+/);
      return { first_name: parts[0] || "", last_name: parts.slice(1).join(" ") || "" };
    };

    const buildOwnerPayload = (slot: OwnerSlotForm, isPrimary: boolean, consent: boolean, zoho: string) => {
      const { first_name, last_name } = splitName(slot.owner_name);
      return {
        first_name,
        last_name,
        unit_id: unitForm.unit_id || null,
        street_address: unitForm.street_address || null,
        property_address: unitForm.property_address || null,
        balance: parseFloat(unitForm.balance) || 0,
        show_proxy_text: unitForm.show_proxy_text,
        is_designated_voter: unitForm.is_designated_voter_id === slot.id || (slot.id === null && unitForm.is_designated_voter_id === "__new__"),
        email: slot.email || null,
        phone: slot.phone || null,
        mailing_address: slot.mailing_address || null,
        electronic_consent: consent,
        zoho_contact_id: zoho || null,
        // Alternate addresses live on the primary owner so notice generators can find them
        alternate_address_1: isPrimary ? (unitForm.alternate_address_1 || null) : null,
        alternate_address_2: isPrimary ? (unitForm.alternate_address_2 || null) : null,
      };
    };

    try {
      // Owner 1: update or insert
      const o1Payload = buildOwnerPayload(unitForm.owner1, true, unitForm.electronic_consent_1, unitForm.zoho_contact_id_1);
      if (unitForm.owner1.id) {
        const { error } = await supabase
          .from("owners")
          .update({ ...o1Payload, updated_at: new Date().toISOString() })
          .eq("id", unitForm.owner1.id);
        if (error) throw error;
      } else {
        const { error } = await supabase
          .from("owners")
          .insert({ ...o1Payload, association_id: selectedAssociation });
        if (error) throw error;
      }

      // Owner 2: update if existing & enabled, insert if newly enabled, delete if was existing & disabled
      if (unitForm.owner2.enabled && unitForm.owner2.owner_name.trim()) {
        const o2Payload = buildOwnerPayload(unitForm.owner2, false, unitForm.electronic_consent_2, unitForm.zoho_contact_id_2);
        if (unitForm.owner2.id) {
          const { error } = await supabase
            .from("owners")
            .update({ ...o2Payload, updated_at: new Date().toISOString() })
            .eq("id", unitForm.owner2.id);
          if (error) throw error;
        } else {
          const { error } = await supabase
            .from("owners")
            .insert({ ...o2Payload, association_id: selectedAssociation });
          if (error) throw error;
        }
      } else if (unitForm.owner2.id) {
        // Owner 2 was disabled — leave the record alone (don't auto-delete to avoid surprises)
      }

      // Persist owner display order for this unit
      if (ownerOrder.length > 0) {
        await Promise.all(
          ownerOrder.map((o, idx) =>
            supabase.from("owners").update({ display_order: idx } as any).eq("id", o.id)
          )
        );
      }

      toast({ title: "Unit saved" });
      setUnitDialogOpen(false);
      setUnitDialogGroup([]);
      setUnitForm(createEmptyUnitForm());
      fetchOwners();
    } catch (err: any) {
      toast({ title: "Error saving unit", description: err.message, variant: "destructive" });
    }
  };

  const handleSetDesignatedVoter = async (owner: Owner, group: Owner[]) => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }

    // If already designated, unset it
    if (owner.is_designated_voter) {
      await supabase.from("owners").update({ is_designated_voter: false }).eq("id", owner.id);
    } else {
      // Unset all others in the group, set this one
      const groupIds = group.map(o => o.id);
      await supabase.from("owners").update({ is_designated_voter: false }).in("id", groupIds);
      await supabase.from("owners").update({ is_designated_voter: true }).eq("id", owner.id);
    }
    fetchOwners();
  };

  const handleToggleDesignation = async (owner: Owner, designation: string) => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }
    const current = Array.isArray(owner.designations) ? owner.designations : [];
    const next = current.includes(designation)
      ? current.filter((d) => d !== designation)
      : [...current, designation];
    const { error } = await supabase.from("owners").update({ designations: next } as any).eq("id", owner.id);
    if (error) {
      toast({ title: "Error updating designations", description: error.message, variant: "destructive" });
      return;
    }
    fetchOwners();
  };

  const handleToggleConsent = async (owner: Owner) => {
    if (!permissions.canEdit) {
      showPermissionToast("edit owners");
      return;
    }

    const newConsent = !owner.electronic_consent;
    const { error } = await supabase.from("owners").update({ electronic_consent: newConsent }).eq("id", owner.id);
    if (error) {
      toast({ title: "Error updating consent", variant: "destructive" });
      return;
    }

    const hash = uuidv4();
    const assocName = associations.find((a) => a.id === owner.association_id)?.name || "Association";
    await supabase.from("document_validation_proofs").insert({
      document_type: "electronic_consent",
      document_title: `E-Consent ${newConsent ? "Granted" : "Revoked"} — ${owner.first_name} ${owner.last_name}`,
      association_id: owner.association_id,
      generated_by: user?.id || null,
      verification_hash: hash,
      metadata: {
        owner_id: owner.id,
        owner_name: `${owner.first_name} ${owner.last_name}`,
        owner_email: owner.email,
        consent_granted: newConsent,
        timestamp: new Date().toISOString(),
        association_name: assocName,
      },
    });

    toast({
      title: newConsent ? "Electronic consent granted" : "Electronic consent revoked",
      description: `Validation proof generated (${hash.substring(0, 8)}...)`,
    });
    fetchOwners();
  };

  const handleSpreadsheetImport = async (rows: Record<string, string>[]) => {
    if (!permissions.canCreate) {
      showPermissionToast("import owners");
      return;
    }

    const importTimestamp = new Date().toISOString();

    const [assocUnits, existingOwners] = await Promise.all([
      fetchAllAssociationUnitsForImport(selectedAssociation),
      fetchAllAssociationOwnersForImport(selectedAssociation),
    ]);

    const unitMap = new Map<string, string>();
    assocUnits.forEach((u) => {
      if (u.unit_number != null) {
        unitMap.set(String(u.unit_number).trim().toLowerCase(), u.id);
      }

      if (u.account_number != null) {
        unitMap.set(String(u.account_number).trim().toLowerCase(), u.id);
      }

      unitMap.set(String(u.id).toLowerCase(), u.id);
    });

    const existingByProperty = new Map<string, string>();
    const existingByUnit = new Map<string, string>();
    const existingByAccount = new Map<string, string>();

    existingOwners.forEach((owner) => {
      const propertyKey = getImportedOwnerPropertyKey(owner.first_name, owner.last_name, owner.property_address);
      const unitKey = getImportedOwnerUnitKey(owner.unit_id, owner.first_name, owner.last_name);
      const accountKey = getImportedOwnerAccountKey(owner.account_number, owner.first_name, owner.last_name);

      if (propertyKey && !existingByProperty.has(propertyKey)) {
        existingByProperty.set(propertyKey, owner.id);
      }

      if (unitKey && !existingByUnit.has(unitKey)) {
        existingByUnit.set(unitKey, owner.id);
      }

      if (accountKey && !existingByAccount.has(accountKey)) {
        existingByAccount.set(accountKey, owner.id);
      }
    });

    const ownersToInsert: ImportedOwnerPayload[] = [];
    const ownersToUpdate: Array<{ id: string; updates: ImportedOwnerPayload }> = [];
    const seenImportKeys = new Set<string>();

    rows.forEach((row) => {
      const unitReference = toNullableImportedValue(row.unit_id);
      const accountReference = toNullableImportedValue(row.account_number);
      const { first_name, last_name } = splitImportedOwnerName(row.owner_name);
      const importedPropertyAddress = toNullableImportedValue(row.property_address);
      const propertyKey = getImportedOwnerPropertyKey(first_name, last_name, importedPropertyAddress);
      const accountKey = getImportedOwnerAccountKey(accountReference, first_name, last_name);
      const resolvedUnitId =
        (unitReference && (unitMap.get(unitReference.toLowerCase()) || (unitReference.match(/^[0-9a-f-]{36}$/i) ? unitReference : null))) ||
        (accountReference && unitMap.get(accountReference.toLowerCase())) ||
        null;
      const unitKey = getImportedOwnerUnitKey(resolvedUnitId, first_name, last_name);
      const fallbackImportKey = [
        normalizeImportedOwnerValue(first_name),
        normalizeImportedOwnerValue(last_name),
        normalizeImportedOwnerValue(accountReference),
        normalizeImportedOwnerValue(unitReference),
      ].join("::");
      const importKeys = [propertyKey, unitKey, accountKey, fallbackImportKey].filter(
        (value, index, array): value is string => Boolean(value) && array.indexOf(value) === index
      );

      if (importKeys.some((key) => seenImportKeys.has(key))) return;
      importKeys.forEach((key) => seenImportKeys.add(key));

      const matchedOwnerId =
        (propertyKey ? existingByProperty.get(propertyKey) : null) ||
        (unitKey ? existingByUnit.get(unitKey) : null) ||
        (accountKey ? existingByAccount.get(accountKey) : null) ||
        null;

      const ownerPayload: ImportedOwnerPayload = {
        association_id: selectedAssociation,
        zoho_contact_id: toNullableImportedValue(row.zoho_contact_id),
        first_name,
        last_name,
        ...(accountReference !== null ? { account_number: accountReference } : {}),
        street_address: toNullableImportedValue(row.street_address),
        property_address: importedPropertyAddress,
        mailing_address: toNullableImportedValue(row.mailing_address),
        alternate_address_1: toNullableImportedValue(row.alternate_address_1),
        alternate_address_2: toNullableImportedValue(row.alternate_address_2),
        phone: toNullableImportedValue(row.phone),
        email: toNullableImportedValue(row.email),
        balance: row.balance ? Number(row.balance) || 0 : 0,
        unit_id: resolvedUnitId,
      };

      if (matchedOwnerId) {
        ownersToUpdate.push({
          id: matchedOwnerId,
          updates: {
            ...ownerPayload,
            updated_at: importTimestamp,
          },
        });
        return;
      }

      ownersToInsert.push(ownerPayload);
    });

    if (ownersToInsert.length === 0 && ownersToUpdate.length === 0) {
      throw new Error("No valid owner rows found to import.");
    }

    if (ownersToUpdate.length > 0) {
      const chunkSize = 25;
      for (let i = 0; i < ownersToUpdate.length; i += chunkSize) {
        const chunk = ownersToUpdate.slice(i, i + chunkSize);
        const results = await Promise.all(
          chunk.map(({ id, updates }) =>
            supabase
              .from("owners")
              .update(updates)
              .eq("id", id)
          )
        );

        const failedResult = results.find((result) => result.error);
        if (failedResult?.error) throw failedResult.error;
      }
    }

    if (ownersToInsert.length > 0) {
      const chunkSize = 100;
      for (let i = 0; i < ownersToInsert.length; i += chunkSize) {
        const chunk = ownersToInsert.slice(i, i + chunkSize);
        const { error } = await supabase.from("owners").insert(chunk);
        if (error) throw error;
      }
    }

    toast({
      title: "Owner roster imported",
      description: `${ownersToUpdate.length} updated, ${ownersToInsert.length} added.`,
    });
    await fetchOwners();
  };

  const handleExportCsv = async () => {
    if (!permissions.canRead) {
      showPermissionToast("export owners");
      return;
    }

    const escapeCsv = (val: string) => {
      if (!val) return "";
      if (val.includes(",") || val.includes('"') || val.includes("\n")) {
        return `"${val.replace(/"/g, '""')}"`;
      }
      return val;
    };
    const csv = [
      "Account Number,Unit Number,Owner Name,Property Address,Mailing Address,Alternate Address 1,Alternate Address 2,Email,Phone,Balance",
      ...filtered.map((o) => [
        escapeCsv(o.account_number || o.units?.account_number || ""),
        escapeCsv(o.units?.unit_number || ""),
        escapeCsv(`${o.first_name || ""} ${o.last_name || ""}`.trim()),
        escapeCsv(o.property_address || ""),
        escapeCsv(o.mailing_address || ""),
        escapeCsv(o.alternate_address_1 || ""),
        escapeCsv(o.alternate_address_2 || ""),
        escapeCsv(o.email || ""),
        escapeCsv(o.phone || ""),
        o.balance ?? 0
      ].join(",")),
    ].join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const { saveFile } = await import("@/lib/saveFile");
    await saveFile(blob, { suggestedName: "owner_roster.csv", mimeType: "text/csv", description: "CSV file" });
  };

  const handleExportSignInPdf = async () => {
    if (!permissions.canRead) {
      showPermissionToast("export owners");
      return;
    }

    const { default: jsPDF } = await import("jspdf");
    const assocName = associations.find((a) => a.id === selectedAssociation)?.name || "Association";
    const doc = new jsPDF();
    doc.setFontSize(16);
    doc.text(`${assocName} - Sign-in Sheet`, 20, 20);
    doc.setFontSize(10);
    doc.text(`Generated on ${new Date().toLocaleDateString()}`, 20, 28);

    // Columns: Address(55), Name(55), Signature(60)
    const colX = [20, 75, 130, 190];
    const startY = 38;

    // Header
    doc.setFillColor(30, 41, 59);
    doc.rect(colX[0], startY, colX[3] - colX[0], 10, "F");
    doc.setTextColor(255, 255, 255);
    doc.setFontSize(10);
    doc.text("Property Address", colX[0] + 3, startY + 7);
    doc.text("Owner Name", colX[1] + 3, startY + 7);
    doc.text("Signature", colX[2] + 3, startY + 7);
    doc.setTextColor(0, 0, 0);

    let y = startY + 10;
    const includedOwners = filtered.filter((o) => !o.exclude_from_signin);
    const signInGroups = includedOwners.reduce<Record<string, typeof includedOwners>>((acc, owner) => {
      const key = owner.unit_id || `no-unit-${owner.id}`;
      if (!acc[key]) acc[key] = [];
      acc[key].push(owner);
      return acc;
    }, {});

    // Sort groups alphanumerically by street address
    const sortedGroups = Object.values(signInGroups).sort((a, b) => {
      const addrA = (a[0].property_address || "").split(",")[0].trim();
      const addrB = (b[0].property_address || "").split(",")[0].trim();
      return addrA.localeCompare(addrB, undefined, { numeric: true, sensitivity: 'base' });
    });

    sortedGroups.forEach((groupOwners) => {
      const designated = groupOwners.find((o) => (o as any).is_designated_voter);
      const displayOwners = designated ? [designated] : groupOwners;
      const names = displayOwners.map((o) => `${o.first_name} ${o.last_name}`).join(" & ");
      const fullAddr = groupOwners[0].property_address || groupOwners[0].mailing_address || "—";
      const streetAddress = fullAddr.split(",")[0].trim();
      const hasProxy = groupOwners.some((o) => o.show_proxy_text) && proxyTextOn;
      const rowHeight = hasProxy ? 26 : 14;

      if (y + rowHeight > 275) {
        doc.addPage();
        y = 20;
      }

      // Draw column borders
      doc.rect(colX[0], y, colX[1] - colX[0], rowHeight); // Address col
      doc.rect(colX[1], y, colX[2] - colX[1], rowHeight); // Name col
      doc.rect(colX[2], y, colX[3] - colX[2], rowHeight); // Signature col

      doc.setFontSize(10);
      doc.text(streetAddress, colX[0] + 3, y + 7, { maxWidth: colX[1] - colX[0] - 6 });
      doc.text(names, colX[1] + 3, y + 7, { maxWidth: colX[2] - colX[1] - 6 });

      if (hasProxy) {
        doc.setTextColor(220, 38, 38);
        doc.setFontSize(7);
        const proxyLabel = "FOR MGMT ONLY. PROXY REC'D:";
        const proxyLabelX = colX[0] + 3;
        doc.text(proxyLabel, proxyLabelX, y + 16);
        const cbSize = 4;
        const cbGap = 1.5;
        const cbX = proxyLabelX + doc.getTextWidth(proxyLabel) + cbGap;
        doc.rect(cbX, y + 13, cbSize, cbSize);
        doc.setTextColor(0, 0, 0);
        doc.setFontSize(10);
      }
      y += rowHeight;
    });
    doc.save(`${assocName.replace(/[^a-zA-Z0-9]/g, "_")}_Signin_Sheet.pdf`);
    toast({ title: "Sign-in sheet exported" });
  };

  const filtered = owners.filter((o) => {
    const statusMatch = showArchived ? (o.status === "archived") : (o.status !== "archived");
    const searchMatch = `${o.first_name} ${o.last_name} ${o.business_name || ""} ${o.management_company || ""} ${o.management_contact_name || ""} ${o.property_address || ""}`.toLowerCase().includes(search.toLowerCase());
    return statusMatch && searchMatch;
  });
  const archivedCount = owners.filter((o) => o.status === "archived").length;
  const isReadOnly = permissions.canRead && !permissions.canCreate && !permissions.canEdit && !permissions.canDelete;

  // Group owners by property address (falling back to mailing address, then unit_id)
  const groupedByAddress = filtered.reduce<Record<string, Owner[]>>((acc, owner) => {
    const addr = (owner.property_address || owner.mailing_address || "").trim().toLowerCase();
    const key = addr || owner.unit_id || `no-addr-${owner.id}`;
    if (!acc[key]) acc[key] = [];
    acc[key].push(owner);
    return acc;
  }, {});
  const unitGroups = Object.entries(groupedByAddress)
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([, owners]) => [...owners].sort((a: any, b: any) => {
      const ao = a.display_order ?? 9999;
      const bo = b.display_order ?? 9999;
      if (ao !== bo) return ao - bo;
      return (a.last_name || "").localeCompare(b.last_name || "");
    }));

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold">Owner Management</h1>
        <p className="text-sm text-muted-foreground">Upload and manage property owner data per association.</p>
      </div>

      <Card>
        <CardContent className="pt-4 space-y-3">
          <div className="flex flex-wrap items-end gap-3">
            <div className="space-y-1.5 min-w-[260px] flex-1 max-w-md">
              <Label className="text-xs text-muted-foreground">Association</Label>
              <Select value={selectedAssociation} onValueChange={setSelectedAssociation}>
                <SelectTrigger><SelectValue placeholder="Select association" /></SelectTrigger>
                <SelectContent>
                  {associations.map((a) => (
                    <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="ml-auto flex flex-wrap items-center gap-2">
              {archivedCount > 0 && (
                <div className="flex items-center gap-2 mr-2">
                  <Switch checked={showArchived} onCheckedChange={setShowArchived} id="show-archived-owners" />
                  <Label htmlFor="show-archived-owners" className="text-xs text-muted-foreground flex items-center gap-1 cursor-pointer">
                    <Archive className="h-3.5 w-3.5" /> Archived ({archivedCount})
                  </Label>
                </div>
              )}

              <Button size="sm" variant="outline" className="gap-1.5" onClick={handleOpenAdd} disabled={!permissions.canCreate}>
                <Plus className="h-4 w-4" /> Add Owner
              </Button>
              <Button size="sm" className="gap-1.5" onClick={() => { handleOpenAdd(); setForm((prev) => ({ ...prev, owner_type: "business" })); }} disabled={!permissions.canCreate}>
                <Plus className="h-4 w-4" /> Add Business
              </Button>

              <DropdownMenu>
                <DropdownMenuTrigger asChild>
                  <Button size="sm" variant="outline" className="gap-1.5" disabled={!permissions.canRead}>
                    <Download className="h-4 w-4" /> Export
                  </Button>
                </DropdownMenuTrigger>
                <DropdownMenuContent align="end" className="w-56">
                  <DropdownMenuLabel className="text-xs">Export &amp; print</DropdownMenuLabel>
                  <DropdownMenuSeparator />
                  <button className="flex w-full items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent rounded-sm disabled:opacity-50" onClick={handleExportCsv} disabled={filtered.length === 0}>
                    <Download className="h-4 w-4" /> Roster CSV
                  </button>
                  <button className="flex w-full items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent rounded-sm disabled:opacity-50" onClick={handleExportSignInPdf} disabled={filtered.length === 0}>
                    <FileText className="h-4 w-4" /> Roster PDF
                  </button>
                  <button className="flex w-full items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent rounded-sm disabled:opacity-50" onClick={handleExportSignInPdf} disabled={filtered.length === 0}>
                    <Upload className="h-4 w-4" /> Sign-in Sheet
                  </button>
                  <button className="flex w-full items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent rounded-sm disabled:opacity-50" onClick={() => { setContactCardOwners(null); setContactCardsOpen(true); }} disabled={filtered.length === 0}>
                    <ContactRound className="h-4 w-4" /> Contact Cards
                  </button>
                  <DropdownMenuSeparator />
                  <button className="flex w-full items-center gap-2 px-2 py-1.5 text-sm hover:bg-accent rounded-sm disabled:opacity-50" onClick={() => setUploadDialogOpen(true)} disabled={!permissions.canCreate}>
                    <Users className="h-4 w-4" /> Bulk Upload Owners
                  </button>
                </DropdownMenuContent>
              </DropdownMenu>
            </div>
          </div>

          {!permissionLoading && !permissions.canRead && (
            <div className="rounded-lg border border-border bg-muted/40 p-4 text-sm text-muted-foreground">
              This account does not have access to <span className="font-medium text-foreground">Owners &amp; Units</span>, so owner actions are blocked before they reach the backend.
            </div>
          )}

          {!permissionLoading && isReadOnly && (
            <div className="rounded-lg border border-border bg-muted/40 p-4 text-sm text-muted-foreground">
              This account has read-only access to owner data.
            </div>
          )}
        </CardContent>
      </Card>

      <Card>
        <CardContent className="pt-6">
          <div className="flex flex-wrap items-center justify-between gap-4 mb-4">
            <div>
              <h2 className="text-lg font-semibold">Owner Roster ({filtered.length} owners across {unitGroups.length} units)</h2>
              <p className="text-sm text-muted-foreground">Use checkboxes to exclude from sign-in sheet. Use pencil to edit details.</p>
            </div>
            <div className="flex items-center gap-3">
              {selectedOwnerIds.size > 0 && (
                <>
                  <Button
                    variant="outline"
                    size="sm"
                    className="gap-2"
                    onClick={() => setComposeDialogOpen(true)}
                  >
                    <Mail className="h-4 w-4" />
                    Compose Email ({selectedOwnerIds.size})
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    className="gap-2"
                    onClick={handleBulkOnboardOwners}
                    disabled={!permissions.canCreate || bulkOnboarding}
                  >
                    <Mail className="h-4 w-4" />
                    {bulkOnboarding ? "Sending..." : `Invite to Website (${selectedOwnerIds.size})`}
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    className="gap-2"
                    onClick={() => { setTenantRequestMessage(""); setTenantRequestOpen(true); }}
                  >
                    <Home className="h-4 w-4" />
                    Request Tenant Info ({selectedOwnerIds.size})
                  </Button>
                  <Button
                    variant="destructive"
                    size="sm"
                    className="gap-2"
                    onClick={() => setBulkDeleteDialogOpen(true)}
                    disabled={!permissions.canDelete}
                  >
                    <Trash2 className="h-4 w-4" />
                    Delete Selected ({selectedOwnerIds.size})
                  </Button>
                </>
              )}
              <Button
                variant="outline"
                size="sm"
                className="gap-2"
                onClick={() => setProxyTextOn(!proxyTextOn)}
                disabled={!permissions.canRead}
              >
                {proxyTextOn ? <Eye className="h-4 w-4" /> : <EyeOff className="h-4 w-4" />}
                Proxy Text: {proxyTextOn ? "ON" : "OFF"}
              </Button>
              <div className="relative w-64">
                <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                <Input
                  placeholder="Search name, address or account..."
                  value={search}
                  onChange={(e) => setSearch(e.target.value)}
                  className="pl-10"
                  disabled={!permissions.canRead}
                />
              </div>
            </div>
          </div>

          {permissionLoading || loading ? (
            <div className="flex justify-center py-12">
              <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
            </div>
          ) : !permissions.canRead ? (
            <div className="py-12 text-center text-muted-foreground">
              <Users className="mx-auto h-12 w-12 mb-4 opacity-50" />
              <p>You don&apos;t have permission to view the owner roster.</p>
            </div>
          ) : filtered.length === 0 ? (
            <div className="py-12 text-center text-muted-foreground">
              <Users className="mx-auto h-12 w-12 mb-4 opacity-50" />
              <p>{search ? "No owners match your search." : "No owners yet. Add your first owner!"}</p>
            </div>
          ) : (
            <div className="rounded-lg border bg-card overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="w-8 text-center">
                      <Checkbox
                        checked={filtered.length > 0 && selectedOwnerIds.size === filtered.length}
                        onCheckedChange={toggleSelectAll}
                        disabled={!permissions.canDelete}
                      />
                    </TableHead>
                    <TableHead className="w-8"></TableHead>
                    <TableHead className="w-20">Account</TableHead>
                    <TableHead className="w-16">Unit</TableHead>
                    <TableHead>Owner(s) &amp; Address</TableHead>
                    <TableHead className="w-28 text-center text-xs">Status</TableHead>
                    <TableHead className="w-20 text-right">Actions</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {unitGroups.map((group) => {
                    const primary = group[0];
                    const unitLabel = primary.units?.unit_number || "—";
                    const groupKey = group.map((o) => o.id).join("-");
                    const isExpanded = expandedUnits.has(groupKey);
                    const designated = group.find((o) => o.is_designated_voter);
                    const allConsent = group.every((o) => o.electronic_consent);
                    const someConsent = group.some((o) => o.electronic_consent);
                    const groupSelected = group.every((o) => selectedOwnerIds.has(o.id));
                    const ownerNames = group.map((o) => o.owner_type === "business" ? (o.business_name || o.first_name) : `${o.first_name} ${o.last_name}`.trim()).filter(Boolean);
                    return (
                      <Fragment key={groupKey}>
                        <TableRow
                          className="border-t border-border cursor-pointer"
                          onClick={() => {
                            setExpandedUnits((prev) => {
                              const next = new Set(prev);
                              if (next.has(groupKey)) next.delete(groupKey); else next.add(groupKey);
                              return next;
                            });
                          }}
                        >
                          <TableCell className="text-center" onClick={(e) => e.stopPropagation()}>
                            <Checkbox
                              checked={groupSelected}
                              onCheckedChange={(v) => {
                                setSelectedOwnerIds((prev) => {
                                  const next = new Set(prev);
                                  group.forEach((o) => { if (v) next.add(o.id); else next.delete(o.id); });
                                  return next;
                                });
                              }}
                              disabled={!permissions.canDelete}
                            />
                          </TableCell>
                          <TableCell>
                            {isExpanded ? <ChevronDown className="h-4 w-4 text-muted-foreground" /> : <ChevronRight className="h-4 w-4 text-muted-foreground" />}
                          </TableCell>
                          <TableCell className="text-sm font-mono text-muted-foreground">{primary.units?.account_number || "—"}</TableCell>
                          <TableCell className="text-sm font-medium">{unitLabel}</TableCell>
                          <TableCell>
                            <div className="font-medium text-sm flex items-center gap-1.5 flex-wrap">
                              {(designated ? [designated.owner_type === "business" ? (designated.business_name || designated.first_name) : `${designated.first_name} ${designated.last_name}`.trim()] : ownerNames.slice(0, 2)).join(" • ")}
                              {group.length > (designated ? 1 : 2) && (
                                <span className="text-[10px] text-muted-foreground">+{group.length - (designated ? 1 : 2)}</span>
                              )}
                              {designated && <Badge variant="outline" className="text-[9px] px-1 py-0 text-primary border-primary">Voter</Badge>}
                            </div>
                            <div className="text-xs text-muted-foreground truncate mt-0.5">{primary.property_address || primary.mailing_address || "—"}</div>
                          </TableCell>
                          <TableCell className="text-center">
                            <div className="flex items-center justify-center gap-1.5" title={allConsent ? "All owners have e-consent" : someConsent ? "Some owners have e-consent" : "No e-consent"}>
                              {allConsent
                                ? <CheckCircle2 className="h-4 w-4 text-primary" />
                                : someConsent
                                  ? <CheckCircle2 className="h-4 w-4 text-primary/40" />
                                  : <XCircle className="h-4 w-4 text-muted-foreground/40" />}
                              <span className="text-[10px] text-muted-foreground">{group.length}</span>
                            </div>
                          </TableCell>
                          <TableCell className="text-right" onClick={(e) => e.stopPropagation()}>
                            <div className="flex items-center justify-end gap-0.5">
                              <Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => { setContactCardOwners(group); setContactCardsOpen(true); }} title="Print contact cards">
                                <Printer className="h-3.5 w-3.5 text-muted-foreground" />
                              </Button>
                              <Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => handleOpenEditUnit(group)} disabled={!permissions.canEdit} title="Edit unit & owners">
                                <Edit2 className="h-3.5 w-3.5 text-muted-foreground" />
                              </Button>
                            </div>
                          </TableCell>
                        </TableRow>
                        {isExpanded && (
                          <TableRow key={`${groupKey}-detail`} className="hover:bg-transparent bg-muted/20">
                            <TableCell colSpan={7} className="py-3 px-4">
                              <div className="space-y-2">
                                {group.map((o, idx) => (
                                  <div key={o.id} className="flex flex-col gap-2 rounded-md border border-border bg-card p-3 sm:flex-row sm:items-start sm:justify-between">
                                    <div className="pt-1">
                                      <Checkbox checked={selectedOwnerIds.has(o.id)} onCheckedChange={() => toggleOwnerSelection(o.id)} disabled={!permissions.canDelete} />
                                    </div>
                                    <div className="flex-1 space-y-1">
                                      <div className="flex flex-wrap items-center gap-2">
                                        <Badge variant="secondary" className="text-[10px]">Owner {idx + 1}</Badge>
                                        <span className="font-semibold text-foreground">{o.owner_type === "business" ? (o.business_name || o.first_name) : `${o.first_name} ${o.last_name}`}</span>
                                        {o.owner_type === "business" && <Badge variant="secondary" className="text-[10px]">Business</Badge>}
                                        {o.is_designated_voter && <Badge variant="outline" className="text-[9px] text-primary border-primary">Designated Voter</Badge>}
                                        <button
                                          type="button"
                                          onClick={() => handleSetDesignatedVoter(o, group)}
                                          className="text-[10px] text-muted-foreground hover:text-primary transition-colors disabled:opacity-50"
                                          disabled={!permissions.canEdit || group.length < 2}
                                        >
                                          {o.is_designated_voter ? "Remove voter status" : "Set as voter"}
                                        </button>
                                        <button
                                          type="button"
                                          onClick={() => handleToggleConsent(o)}
                                          className="text-[10px] text-muted-foreground hover:text-primary transition-colors flex items-center gap-1 disabled:opacity-50"
                                          disabled={!permissions.canEdit}
                                          title={o.electronic_consent ? "Revoke e-consent" : "Grant e-consent"}
                                        >
                                          {o.electronic_consent ? <CheckCircle2 className="h-3 w-3 text-primary" /> : <XCircle className="h-3 w-3" />}
                                          E-Consent
                                        </button>
                                        <button
                                          type="button"
                                          onClick={() => handleToggleExcludeProxy(o)}
                                          className="text-[10px] text-muted-foreground hover:text-primary transition-colors disabled:opacity-50"
                                          disabled={!permissions.canEdit}
                                          title="Toggle proxy text on sign-in sheet"
                                        >
                                          {o.show_proxy_text ? "Proxy: shown" : "Proxy: excluded"}
                                        </button>
                                        {(o.designations || []).map((d) => (
                                          <Badge key={d} variant="outline" className="text-[9px] text-primary border-primary">{d}</Badge>
                                        ))}
                                        <DropdownMenu>
                                          <DropdownMenuTrigger asChild>
                                            <button
                                              type="button"
                                              className="text-[10px] text-muted-foreground hover:text-primary transition-colors disabled:opacity-50"
                                              disabled={!permissions.canEdit}
                                            >
                                              + Designation
                                            </button>
                                          </DropdownMenuTrigger>
                                          <DropdownMenuContent align="start" className="w-56">
                                            <DropdownMenuLabel className="text-xs">Designate as</DropdownMenuLabel>
                                            <DropdownMenuSeparator />
                                            {DESIGNATION_OPTIONS.map((opt) => (
                                              <DropdownMenuCheckboxItem
                                                key={opt}
                                                checked={(o.designations || []).includes(opt)}
                                                onCheckedChange={() => handleToggleDesignation(o, opt)}
                                              >
                                                {opt}
                                              </DropdownMenuCheckboxItem>
                                            ))}
                                          </DropdownMenuContent>
                                        </DropdownMenu>
                                      </div>
                                      <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-1 text-xs text-muted-foreground">
                                        <div className="flex items-center gap-1.5"><Mail className="h-3 w-3" /> {o.email || <span className="italic">No email</span>}</div>
                                        <div className="flex items-center gap-1.5"><Phone className="h-3 w-3" /> {o.phone || <span className="italic">No phone</span>}</div>
                                        {o.owner_type === "business" && o.management_contact_name && <div className="flex items-center gap-1.5 sm:col-span-2"><ContactRound className="h-3 w-3" /> Manager: {o.management_contact_name}{o.management_contact_title ? `, ${o.management_contact_title}` : ""}</div>}
                                        {o.owner_type === "business" && o.management_company && <div className="flex items-center gap-1.5 sm:col-span-2"><Users className="h-3 w-3" /> Management Company: {o.management_company}</div>}
                                        <div className="flex items-start gap-1.5 sm:col-span-2"><Home className="h-3 w-3 mt-0.5 shrink-0" /> Mailing: {o.mailing_address || <span className="italic">Uses property address</span>}</div>
                                        {o.alternate_address_1 && <div className="flex items-start gap-1.5 sm:col-span-2"><MapPin className="h-3 w-3 mt-0.5 shrink-0" /> Alt 1: {o.alternate_address_1}</div>}
                                        {o.alternate_address_2 && <div className="flex items-start gap-1.5 sm:col-span-2"><MapPin className="h-3 w-3 mt-0.5 shrink-0" /> Alt 2: {o.alternate_address_2}</div>}
                                      </div>
                                    </div>
                                    <div className="flex items-center gap-1 shrink-0">
                                      {o.owner_type === "business" && (
                                        <Button variant="ghost" size="icon" onClick={() => handleOpenEdit(o, "management")} disabled={!permissions.canEdit} title="Edit management company info">
                                          <Building2 className="h-4 w-4 text-muted-foreground" />
                                        </Button>
                                      )}
                                      <Button variant="ghost" size="icon" onClick={() => { setContactCardOwners([o]); setContactCardsOpen(true); }} title="Print contact card">
                                        <Printer className="h-4 w-4 text-muted-foreground" />
                                      </Button>
                                      <Button variant="ghost" size="icon" onClick={() => handleOpenEdit(o)} disabled={!permissions.canEdit} title="Edit this owner">
                                        <Edit2 className="h-4 w-4 text-muted-foreground" />
                                      </Button>
                                      <Button variant="ghost" size="icon" onClick={() => handleDelete(o.id)} disabled={!permissions.canDelete} title="Delete this owner">
                                        <Trash2 className="h-4 w-4 text-destructive" />
                                      </Button>
                                    </div>
                                  </div>
                                ))}
                              </div>
                            </TableCell>
                          </TableRow>
                        )}
                       </Fragment>
                    );
                  })}
                </TableBody>
              </Table>
            </div>
          )}
        </CardContent>
      </Card>

      <Dialog
        open={addDialogOpen}
        onOpenChange={(v) => {
          if (!v) resetForm();
          setAddDialogOpen(v);
        }}
      >
        <DialogContent className="max-w-lg max-h-[85vh] flex flex-col">
          <DialogHeader>
            <DialogTitle>{editingOwner ? "Edit Owner" : form.owner_type === "business" ? "Add Business Owner" : "Add New Owner"}</DialogTitle>
            <DialogDescription>
              Enter the details for the {form.owner_type === "business" ? "business/corporate owner and management contact" : `${editingOwner ? "" : "new "}property owner`}.
            </DialogDescription>
          </DialogHeader>

          <Tabs value={addTab} onValueChange={setAddTab} className="flex min-h-0 flex-1 flex-col">
            <TabsList className="w-full shrink-0">
              <TabsTrigger value="details" className="flex-1">
                Owner Details
              </TabsTrigger>
              <TabsTrigger value="management" className="flex-1" disabled={form.owner_type !== "business"}>
                Management
              </TabsTrigger>
              <TabsTrigger value="addresses" className="flex-1">
                Addresses
              </TabsTrigger>
            </TabsList>

            <div className="mt-4 flex-1 min-h-0 overflow-y-auto pr-2">
              <div>
                <TabsContent value="details" className="space-y-4 mt-0 pb-2">
                  <div className="space-y-2">
                    <Label>Owner Type</Label>
                    <Select value={form.owner_type} onValueChange={(v: "individual" | "business") => setForm({ ...form, owner_type: v, owner_name: v === "business" ? "" : form.owner_name })}>
                      <SelectTrigger>
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="individual">Individual</SelectItem>
                        <SelectItem value="business">Business / Corporation</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label>Unit</Label>
                      <Select value={form.unit_id || "none"} onValueChange={(v) => setForm({ ...form, unit_id: v === "none" ? "" : v })}>
                        <SelectTrigger>
                          <SelectValue placeholder="Select unit" />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="none">— No unit —</SelectItem>
                          {units.map((u) => (
                            <SelectItem key={u.id} value={u.id}>
                              {u.unit_number}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>
                  </div>
                  {form.owner_type === "business" ? (
                    <div className="space-y-2">
                      <Label>Business / Corporation Name *</Label>
                      <Input maxLength={150} placeholder="Acme Holdings LLC" value={form.business_name} onChange={(e) => setForm({ ...form, business_name: e.target.value })} />
                    </div>
                  ) : (
                    <div className="space-y-2">
                      <Label>Owner Name *</Label>
                      <Input maxLength={150} placeholder="John Doe" value={form.owner_name} onChange={(e) => setForm({ ...form, owner_name: e.target.value })} />
                    </div>
                  )}
                  <div className="space-y-2">
                    <Label>Street Address</Label>
                    <Input placeholder="1005 Cady Circle" value={form.street_address} onChange={(e) => setForm({ ...form, street_address: e.target.value })} />
                  </div>
                  <div className="space-y-2">
                    <Label>Property Address *</Label>
                    <Input placeholder="1005 Cady Cir." value={form.property_address} onChange={(e) => setForm({ ...form, property_address: e.target.value })} />
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label>Email Address</Label>
                      <Input maxLength={255} placeholder="email@example.com" type="email" value={form.email} onChange={(e) => setForm({ ...form, email: e.target.value })} />
                    </div>
                    <div className="space-y-2">
                      <Label>Phone Number</Label>
                      <Input maxLength={40} placeholder="(555) 123-4567" value={form.phone} onChange={(e) => setForm({ ...form, phone: e.target.value })} />
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label>Current Balance ($)</Label>
                      <Input type="number" step="0.01" value={form.balance} onChange={(e) => setForm({ ...form, balance: e.target.value })} />
                    </div>
                    <div className="space-y-2">
                      <Label>Zoho Customer ID</Label>
                      <Input placeholder="e.g. 460000000012345" value={form.zoho_contact_id} onChange={(e) => setForm({ ...form, zoho_contact_id: e.target.value })} />
                    </div>
                  </div>
                  <div className="space-y-3">
                    <div className="flex items-center gap-2">
                      <Checkbox checked={form.electronic_consent} onCheckedChange={(v) => setForm({ ...form, electronic_consent: !!v })} />
                      <Label className="cursor-pointer">Electronic Consent Received</Label>
                    </div>
                    <div className="flex items-center gap-2">
                      <Checkbox checked={form.show_proxy_text} onCheckedChange={(v) => setForm({ ...form, show_proxy_text: !!v })} />
                      <Label className="cursor-pointer">Include Proxy Text on Sign-in Sheet</Label>
                    </div>
                    <div className="flex items-center gap-2">
                      <Checkbox checked={form.is_designated_voter} onCheckedChange={(v) => setForm({ ...form, is_designated_voter: !!v })} />
                      <Label className="cursor-pointer">Designated Voter</Label>
                    </div>
                  </div>
                </TabsContent>

                <TabsContent value="management" className="space-y-4 mt-0 pb-2">
                  <div className="space-y-2">
                    <Label>Management Company</Label>
                    <Input maxLength={150} placeholder="Management company name" value={form.management_company} onChange={(e) => setForm({ ...form, management_company: e.target.value })} />
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label>Management Contact</Label>
                      <Input maxLength={150} placeholder="Contact name" value={form.management_contact_name} onChange={(e) => setForm({ ...form, management_contact_name: e.target.value })} />
                    </div>
                    <div className="space-y-2">
                      <Label>Title</Label>
                      <Input maxLength={100} placeholder="Property manager, agent, etc." value={form.management_contact_title} onChange={(e) => setForm({ ...form, management_contact_title: e.target.value })} />
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label>Contact Email</Label>
                      <Input maxLength={255} type="email" placeholder="manager@example.com" value={form.management_contact_email} onChange={(e) => setForm({ ...form, management_contact_email: e.target.value })} />
                    </div>
                    <div className="space-y-2">
                      <Label>Contact Phone</Label>
                      <Input maxLength={40} placeholder="(555) 123-4567" value={form.management_contact_phone} onChange={(e) => setForm({ ...form, management_contact_phone: e.target.value })} />
                    </div>
                  </div>
                </TabsContent>

                <TabsContent value="addresses" className="space-y-4 mt-0 pb-2">
                  <div className="space-y-2">
                    <Label>Mailing Address (Primary)</Label>
                    <Textarea placeholder={"123 Main St\nCity, State Zip"} rows={3} value={form.mailing_address} onChange={(e) => setForm({ ...form, mailing_address: e.target.value })} />
                  </div>
                  <div className="space-y-2">
                    <Label>Alternate Address 1</Label>
                    <Textarea placeholder={"123 Vacation Ln\nBeach City, FL 33139"} rows={3} value={form.alternate_address_1} onChange={(e) => setForm({ ...form, alternate_address_1: e.target.value })} />
                  </div>
                  <div className="space-y-2">
                    <Label>Alternate Address 2</Label>
                    <Textarea placeholder="Another Address..." rows={3} value={form.alternate_address_2} onChange={(e) => setForm({ ...form, alternate_address_2: e.target.value })} />
                  </div>
                </TabsContent>
              </div>
            </div>
          </Tabs>

          <div className="flex justify-end gap-3 mt-4 border-t pt-4">
            <Button variant="outline" onClick={() => { setAddDialogOpen(false); resetForm(); }}>
              Cancel
            </Button>
            <Button onClick={handleSave} disabled={editingOwner ? !permissions.canEdit : !permissions.canCreate}>
              <FileText className="h-4 w-4 mr-2" />
              {editingOwner ? "Save Changes" : "Add Owner"}
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      {/* Unit-level edit dialog: tabs for Owner 1, Owner 2, Alt Address 1, Alt Address 2 */}
      <Dialog
        open={unitDialogOpen}
        onOpenChange={(v) => {
          if (!v) {
            setUnitDialogGroup([]);
            setUnitForm(createEmptyUnitForm());
            setUnitDialogTab("owner1");
          }
          setUnitDialogOpen(v);
        }}
      >
        <DialogContent className="max-w-2xl max-h-[90vh] flex flex-col">
          <DialogHeader>
            <DialogTitle>
              Edit Unit {unitDialogGroup[0]?.units?.unit_number ? `— ${unitDialogGroup[0].units.unit_number}` : ""}
            </DialogTitle>
            <DialogDescription>
              Manage all owners and mailing addresses for this unit. Additional mailings only go out to alternate addresses that differ from the primary.
            </DialogDescription>
          </DialogHeader>

          <Tabs value={unitDialogTab} onValueChange={setUnitDialogTab} className="flex min-h-0 flex-1 flex-col">
            <TabsList className="w-full shrink-0 grid grid-cols-4">
              <TabsTrigger value="owner1">Owner 1</TabsTrigger>
              <TabsTrigger value="owner2">
                Owner 2{unitForm.owner2.enabled && unitForm.owner2.owner_name ? "" : <span className="ml-1 text-muted-foreground text-[10px]">(empty)</span>}
              </TabsTrigger>
              <TabsTrigger value="alt1">Alt. Address 1</TabsTrigger>
              <TabsTrigger value="alt2">Alt. Address 2</TabsTrigger>
            </TabsList>

            <div className="mt-4 flex-1 min-h-0 overflow-y-auto pr-2">
              <div className="pb-2 space-y-4">
                {/* Shared unit-level fields */}
                <div className="rounded-md border border-border bg-muted/30 p-3 space-y-3">
                  <div className="text-xs font-semibold uppercase text-muted-foreground">Unit (shared)</div>
                  <div className="grid grid-cols-2 gap-3">
                    <div className="space-y-1.5">
                      <Label className="text-xs">Unit</Label>
                      <Select value={unitForm.unit_id || "none"} onValueChange={(v) => setUnitForm({ ...unitForm, unit_id: v === "none" ? "" : v })}>
                        <SelectTrigger><SelectValue placeholder="Select unit" /></SelectTrigger>
                        <SelectContent>
                          <SelectItem value="none">— No unit —</SelectItem>
                          {units.map((u) => (<SelectItem key={u.id} value={u.id}>{u.unit_number}</SelectItem>))}
                        </SelectContent>
                      </Select>
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-xs">Property Address</Label>
                      <Input value={unitForm.property_address} onChange={(e) => setUnitForm({ ...unitForm, property_address: e.target.value })} />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-xs">Street Address</Label>
                      <Input value={unitForm.street_address} onChange={(e) => setUnitForm({ ...unitForm, street_address: e.target.value })} />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-xs">Current Balance ($)</Label>
                      <Input type="number" step="0.01" value={unitForm.balance} onChange={(e) => setUnitForm({ ...unitForm, balance: e.target.value })} />
                    </div>
                  </div>
                  <div className="flex items-center gap-2">
                    <Checkbox checked={unitForm.show_proxy_text} onCheckedChange={(v) => setUnitForm({ ...unitForm, show_proxy_text: !!v })} />
                    <Label className="text-xs cursor-pointer">Include Proxy Text on Sign-in Sheet</Label>
                  </div>
                </div>

                {ownerOrder.length > 1 && (
                  <div className="rounded-md border border-border bg-muted/30 p-3 space-y-2">
                    <div className="text-xs font-semibold uppercase text-muted-foreground">Owner Priority</div>
                    <p className="text-[11px] text-muted-foreground">Drag to reorder. The first owner is treated as the primary contact for this unit.</p>
                    <OwnerPriorityList
                      owners={ownerOrder}
                      onReorder={(next) => setOwnerOrder(next)}
                    />
                  </div>
                )}

                <TabsContent value="owner1" className="space-y-3 mt-0">


                  <div className="space-y-1.5">
                    <Label>Owner Name *</Label>
                    <Input
                      placeholder="John Doe"
                      value={unitForm.owner1.owner_name}
                      onChange={(e) => setUnitForm({ ...unitForm, owner1: { ...unitForm.owner1, owner_name: e.target.value } })}
                    />
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div className="space-y-1.5">
                      <Label>Email</Label>
                      <Input type="email" value={unitForm.owner1.email} onChange={(e) => setUnitForm({ ...unitForm, owner1: { ...unitForm.owner1, email: e.target.value } })} />
                    </div>
                    <div className="space-y-1.5">
                      <Label>Phone</Label>
                      <Input value={unitForm.owner1.phone} onChange={(e) => setUnitForm({ ...unitForm, owner1: { ...unitForm.owner1, phone: e.target.value } })} />
                    </div>
                  </div>
                  <div className="space-y-1.5">
                    <Label>Mailing Address (Primary)</Label>
                    <Textarea rows={3} placeholder={"123 Main St\nCity, State Zip"} value={unitForm.owner1.mailing_address} onChange={(e) => setUnitForm({ ...unitForm, owner1: { ...unitForm.owner1, mailing_address: e.target.value } })} />
                    <p className="text-[11px] text-muted-foreground">If left blank, the property address is used.</p>
                  </div>
                  <div className="space-y-1.5">
                    <Label>Zoho Customer ID</Label>
                    <Input value={unitForm.zoho_contact_id_1} onChange={(e) => setUnitForm({ ...unitForm, zoho_contact_id_1: e.target.value })} />
                  </div>
                  <div className="flex items-center gap-2">
                    <Checkbox checked={unitForm.electronic_consent_1} onCheckedChange={(v) => setUnitForm({ ...unitForm, electronic_consent_1: !!v })} />
                    <Label className="text-xs cursor-pointer">Electronic Consent Received</Label>
                  </div>
                  <div className="flex items-center gap-2">
                    <Checkbox
                      checked={unitForm.is_designated_voter_id === unitForm.owner1.id || (unitForm.owner1.id === null && unitForm.is_designated_voter_id === "__new__")}
                      onCheckedChange={(v) => setUnitForm({ ...unitForm, is_designated_voter_id: v ? (unitForm.owner1.id || "__new__") : null })}
                    />
                    <Label className="text-xs cursor-pointer">Designated Voter</Label>
                  </div>
                </TabsContent>

                <TabsContent value="owner2" className="space-y-3 mt-0">
                  <label className="flex items-center gap-2 cursor-pointer select-none rounded-md border border-border bg-muted/30 p-2.5">
                    <input
                      type="checkbox"
                      className="h-4 w-4 rounded border-input accent-primary"
                      checked={unitForm.owner2.enabled}
                      onChange={(e) => setUnitForm({ ...unitForm, owner2: { ...unitForm.owner2, enabled: e.target.checked } })}
                    />
                    <span className="text-sm font-medium">Add a second owner to this unit</span>
                  </label>
                  {unitForm.owner2.enabled && (
                    <>
                      <div className="space-y-1.5">
                        <Label>Owner Name</Label>
                        <Input placeholder="Jane Doe" value={unitForm.owner2.owner_name} onChange={(e) => setUnitForm({ ...unitForm, owner2: { ...unitForm.owner2, owner_name: e.target.value } })} />
                      </div>
                      <div className="grid grid-cols-2 gap-3">
                        <div className="space-y-1.5">
                          <Label>Owner 2 Email</Label>
                          <Input type="email" placeholder="secondary@example.com" value={unitForm.owner2.email} onChange={(e) => setUnitForm({ ...unitForm, owner2: { ...unitForm.owner2, email: e.target.value } })} />
                        </div>
                        <div className="space-y-1.5">
                          <Label>Phone</Label>
                          <Input value={unitForm.owner2.phone} onChange={(e) => setUnitForm({ ...unitForm, owner2: { ...unitForm.owner2, phone: e.target.value } })} />
                        </div>
                      </div>
                      <div className="space-y-1.5">
                        <Label>Mailing Address</Label>
                        <Textarea rows={3} placeholder={"Leave blank if same as Owner 1"} value={unitForm.owner2.mailing_address} onChange={(e) => setUnitForm({ ...unitForm, owner2: { ...unitForm.owner2, mailing_address: e.target.value } })} />
                        <p className="text-[11px] text-muted-foreground">A separate copy of mailings is only sent if this differs from Owner 1's mailing address.</p>
                      </div>
                      <div className="space-y-1.5">
                        <Label>Zoho Customer ID</Label>
                        <Input value={unitForm.zoho_contact_id_2} onChange={(e) => setUnitForm({ ...unitForm, zoho_contact_id_2: e.target.value })} />
                      </div>
                      <div className="flex items-center gap-2">
                        <Checkbox checked={unitForm.electronic_consent_2} onCheckedChange={(v) => setUnitForm({ ...unitForm, electronic_consent_2: !!v })} />
                        <Label className="text-xs cursor-pointer">Electronic Consent Received</Label>
                      </div>
                      <div className="flex items-center gap-2">
                        <Checkbox
                          checked={unitForm.is_designated_voter_id === unitForm.owner2.id}
                          onCheckedChange={(v) => setUnitForm({ ...unitForm, is_designated_voter_id: v ? (unitForm.owner2.id || null) : null })}
                          disabled={!unitForm.owner2.id}
                        />
                        <Label className="text-xs cursor-pointer">Designated Voter {!unitForm.owner2.id && <span className="text-[10px] text-muted-foreground">(save first)</span>}</Label>
                      </div>
                    </>
                  )}
                </TabsContent>

                <TabsContent value="alt1" className="space-y-3 mt-0">
                  <div className="space-y-1.5">
                    <Label>Alternate Mailing Address 1</Label>
                    <Textarea
                      rows={4}
                      placeholder={"123 Vacation Ln\nBeach City, FL 33139"}
                      value={unitForm.alternate_address_1}
                      onChange={(e) => setUnitForm({ ...unitForm, alternate_address_1: e.target.value })}
                    />
                    <p className="text-[11px] text-muted-foreground">A copy of every mailing is sent to this address as well as the primary mailing address (only if it differs).</p>
                  </div>
                </TabsContent>

                <TabsContent value="alt2" className="space-y-3 mt-0">
                  <div className="space-y-1.5">
                    <Label>Alternate Mailing Address 2</Label>
                    <Textarea
                      rows={4}
                      placeholder={"Another address..."}
                      value={unitForm.alternate_address_2}
                      onChange={(e) => setUnitForm({ ...unitForm, alternate_address_2: e.target.value })}
                    />
                    <p className="text-[11px] text-muted-foreground">A copy of every mailing is sent to this address as well as the primary mailing address (only if it differs).</p>
                  </div>
                </TabsContent>
              </div>
            </div>
          </Tabs>

          <div className="flex justify-end gap-3 mt-4 border-t pt-4">
            <Button variant="outline" onClick={() => setUnitDialogOpen(false)}>Cancel</Button>
            <Button onClick={handleSaveUnit} disabled={!permissions.canEdit}>
              <FileText className="h-4 w-4 mr-2" />
              Save Unit
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <ImportSpreadsheetDialog
        open={uploadDialogOpen}
        onOpenChange={setUploadDialogOpen}
        title="Import Owners"
        description="Upload a CSV or Excel file to add new owners and update existing owners for the selected association."
        templateFileName="owners_import_template.xlsx"
        expectedColumns={[
          { key: "owner_name", label: "Owner Name", required: true, aliases: ["Owners (Name)", "Owner", "Name"] },
          { key: "account_number", label: "Account Number", aliases: ["Account"] },
          { key: "unit_id", label: "Unit # or Unit ID", aliases: ["Unit Number", "Unit #", "Unit", "Unit ID"] },
          { key: "zoho_contact_id", label: "Zoho Contact ID" },
          { key: "street_address", label: "Street Address" },
          { key: "property_address", label: "Property Address" },
          { key: "mailing_address", label: "Mailing Address" },
          { key: "alternate_address_1", label: "Alternate Address 1", aliases: ["Alt Address 1"] },
          { key: "alternate_address_2", label: "Alternate Address 2", aliases: ["Alt Address 2"] },
          { key: "email", label: "Email" },
          { key: "phone", label: "Phone", aliases: ["Phone Number"] },
          { key: "balance", label: "Balance" },
        ]}
        onImport={handleSpreadsheetImport}
      />

      {/* Bulk Delete Confirmation */}
      <AlertDialog open={bulkDeleteDialogOpen} onOpenChange={setBulkDeleteDialogOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete {selectedOwnerIds.size} Owner(s)</AlertDialogTitle>
            <AlertDialogDescription>
              Are you sure you want to permanently delete {selectedOwnerIds.size} selected owner(s)?
              This will also remove their linked records. This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleBulkDelete} className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
              Delete All Selected
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <PrintableContactCards
        open={contactCardsOpen}
        onOpenChange={(v) => { setContactCardsOpen(v); if (!v) setContactCardOwners(null); }}
        owners={contactCardOwners || filtered}
        associationName={associations.find(a => a.id === selectedAssociation)?.name || ""}
      />

      <NotifyOwnersProvider>
        <NotifyOwnersDialog
          open={composeDialogOpen}
          onOpenChange={setComposeDialogOpen}
          selectedOwners={owners.filter((owner) => selectedOwnerIds.has(owner.id))}
        />
      </NotifyOwnersProvider>

      <Dialog open={tenantRequestOpen} onOpenChange={setTenantRequestOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>Request Tenant Information</DialogTitle>
            <DialogDescription>
              Email {selectedOwnerIds.size} selected owner{selectedOwnerIds.size === 1 ? "" : "s"} a secure
              link to submit tenant details — contact info, vehicles, pets, lease length, and a copy of the
              lease. Submitted info is saved to the unit's tenant roster automatically.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-2">
            <Label htmlFor="tenant-msg">Custom Message (optional)</Label>
            <Textarea
              id="tenant-msg"
              rows={4}
              placeholder="Add a personal note that will appear in the email…"
              value={tenantRequestMessage}
              onChange={(e) => setTenantRequestMessage(e.target.value)}
            />
            <p className="text-xs text-muted-foreground">
              Owners without an email on file will be skipped — you'll see a summary after sending.
            </p>
          </div>
          <div className="flex justify-end gap-2 pt-2">
            <Button variant="outline" onClick={() => setTenantRequestOpen(false)} disabled={tenantRequestSending}>
              Cancel
            </Button>
            <Button onClick={handleSendTenantInfoRequests} disabled={tenantRequestSending || selectedOwnerIds.size === 0}>
              {tenantRequestSending ? "Sending…" : `Send Request${selectedOwnerIds.size === 1 ? "" : "s"}`}
            </Button>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
