import { useEffect, useState, useMemo, useCallback } from "react";
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 { Badge } from "@/components/ui/badge";
import { Textarea } from "@/components/ui/textarea";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from "@/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Combobox } from "@/components/Combobox";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Sheet, SheetContent } from "@/components/ui/sheet";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Separator } from "@/components/ui/separator";
import { Checkbox } from "@/components/ui/checkbox";
import { useToast } from "@/hooks/use-toast";
import { useDropzone } from "react-dropzone";
import {
  Plus, Search, Gavel, Filter, FileText, Calendar, Building2, User,
  Home, Clock, ChevronRight, CheckCircle2, XCircle, AlertCircle,
  MessageSquare, Image, Paperclip, RefreshCw, Download, UploadCloud, X, File,
} from "lucide-react";
import type { Tables } from "@/integrations/supabase/types";
import { format } from "date-fns";
import VotingAndComments from "@/components/shared/VotingAndComments";
import RecordArcMemberVote from "@/components/arc/RecordArcMemberVote";
import { generateArcDecisionLetterPdf } from "@/lib/arcDecisionLetterPdf";
import { Mail } from "lucide-react";
import { useAuth } from "@/contexts/AuthContext";
import { useNavigate } from "react-router-dom";

/* ── Status config ─────────────────────── */
const STATUS_CONFIG: Record<string, { label: string; cls: string; icon: React.ElementType }> = {
  submitted:        { label: "Submitted",        cls: "bg-blue-100 text-blue-700 border-blue-200",           icon: FileText },
  under_review:     { label: "Under Review",     cls: "bg-amber-100 text-amber-700 border-amber-200",       icon: Clock },
  awaiting_changes: { label: "Awaiting Changes", cls: "bg-orange-100 text-orange-700 border-orange-200",    icon: AlertCircle },
  approved:         { label: "Approved",          cls: "bg-emerald-100 text-emerald-700 border-emerald-200", icon: CheckCircle2 },
  denied:           { label: "Denied",            cls: "bg-red-100 text-red-700 border-red-200",             icon: XCircle },
  withdrawn:        { label: "Withdrawn",         cls: "bg-muted text-muted-foreground border-border",       icon: XCircle },
};

const getStatus = (s: string | null) => STATUS_CONFIG[s || "submitted"] || STATUS_CONFIG.submitted;

type AppRow = Tables<"arc_applications"> & {
  units?: { unit_number: string; address?: string | null } | null;
  associations?: { name: string } | null;
  owners?: { first_name: string; last_name: string; property_address?: string | null } | null;
};

export default function ARCApplicationsPage({ boardAssociationIds }: { boardAssociationIds?: string[] } = {}) {
  const [applications, setApplications] = useState<AppRow[]>([]);
  const [associations, setAssociations] = useState<Tables<"associations">[]>([]);
  const [units, setUnits] = useState<Tables<"units">[]>([]);
  const [owners, setOwners] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState("");
  const [statusFilter, setStatusFilter] = useState("all");
  const [assocFilter, setAssocFilter] = useState("all");
  const [dialogOpen, setDialogOpen] = useState(false);
  const [selectedApp, setSelectedApp] = useState<AppRow | null>(null);
  const [arcFiles, setArcFiles] = useState<File[]>([]);
  const [arcUploading, setArcUploading] = useState(false);
  const [notifyStaff, setNotifyStaff] = useState(true);
  const [notifyOwners, setNotifyOwners] = useState(true);
  const [createAssocId, setCreateAssocId] = useState<string>("");
  const [createOwnerId, setCreateOwnerId] = useState<string>("");
  const { toast } = useToast();
  const { isAdmin } = useAuth();
  const navigate = useNavigate();
  const [importing, setImporting] = useState(false);
  const [exportOpen, setExportOpen] = useState(false);
  const [exportStart, setExportStart] = useState("");
  const [exportEnd, setExportEnd] = useState("");
  const [exporting, setExporting] = useState(false);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [bulkType, setBulkType] = useState("");
  const [bulkOwnerId, setBulkOwnerId] = useState("");
  const [bulkAddress, setBulkAddress] = useState("");
  const [bulkSaving, setBulkSaving] = useState(false);

  const isBoardView = !!boardAssociationIds?.length;

  const toggleSelect = (id: string) => {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };

  const handleBulkUpdateType = async () => {
    if (!selectedIds.size) return;
    setBulkSaving(true);
    try {
      const { error } = await supabase
        .from("arc_applications")
        .update({ project_type: bulkType.trim() || null })
        .in("id", Array.from(selectedIds));
      if (error) throw error;
      toast({ title: "Updated", description: `${selectedIds.size} application(s) updated.` });
      setSelectedIds(new Set());
      setBulkType("");
      fetchData();
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    } finally {
      setBulkSaving(false);
    }
  };

  const handleBulkUpdateOwner = async () => {
    if (!selectedIds.size || !bulkOwnerId) return;
    setBulkSaving(true);
    try {
      const owner = owners.find((o) => o.id === bulkOwnerId);
      const update: any = { owner_id: bulkOwnerId };
      if (owner?.unit_id) update.unit_id = owner.unit_id;
      const { error } = await supabase
        .from("arc_applications")
        .update(update)
        .in("id", Array.from(selectedIds));
      if (error) throw error;
      toast({ title: "Owner updated", description: `${selectedIds.size} application(s) reassigned.` });
      setSelectedIds(new Set());
      setBulkOwnerId("");
      fetchData();
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    } finally {
      setBulkSaving(false);
    }
  };

  const handleBulkUpdateAddress = async () => {
    if (!selectedIds.size || !bulkAddress.trim()) return;
    setBulkSaving(true);
    try {
      const ids = Array.from(selectedIds);
      const { data: apps, error: fetchErr } = await supabase
        .from("arc_applications")
        .select("id, owner_id, unit_id")
        .in("id", ids);
      if (fetchErr) throw fetchErr;
      const ownerIds = Array.from(new Set((apps || []).map((a: any) => a.owner_id).filter(Boolean)));
      const unitIds = Array.from(new Set((apps || []).map((a: any) => a.unit_id).filter(Boolean)));
      if (ownerIds.length) {
        await supabase.from("owners").update({ property_address: bulkAddress.trim() }).in("id", ownerIds);
      }
      if (unitIds.length) {
        await supabase.from("units").update({ address: bulkAddress.trim() }).in("id", unitIds);
      }
      toast({ title: "Address updated", description: `Updated address for ${selectedIds.size} application(s).` });
      setSelectedIds(new Set());
      setBulkAddress("");
      fetchData();
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    } finally {
      setBulkSaving(false);
    }
  };

  const handleExportPdf = async () => {
    setExporting(true);
    try {
      const { jsPDF } = await import("jspdf");
      const autoTable = (await import("jspdf-autotable")).default;
      const start = exportStart ? new Date(exportStart + "T00:00:00") : null;
      const end = exportEnd ? new Date(exportEnd + "T23:59:59") : null;
      const rows = filtered.filter((a) => {
        const d = a.submitted_date ? new Date(a.submitted_date) : a.created_at ? new Date(a.created_at) : null;
        if (!d) return !start && !end;
        if (start && d < start) return false;
        if (end && d > end) return false;
        return true;
      });
      const doc = new jsPDF({ orientation: "landscape", unit: "pt", format: "letter" });
      doc.setFontSize(16);
      doc.text("ARC Applications Report", 40, 40);
      doc.setFontSize(10);
      const rangeTxt = start || end
        ? `${start ? format(start, "MMM d, yyyy") : "—"} to ${end ? format(end, "MMM d, yyyy") : "—"}`
        : "All dates";
      doc.text(`Date range: ${rangeTxt}`, 40, 58);
      doc.text(`Generated: ${format(new Date(), "MMM d, yyyy h:mm a")}`, 40, 72);
      autoTable(doc, {
        startY: 90,
        head: [["Date", "Owner", "Address", "Project", "Type", "Association", "Status"]],
        body: rows.map((a) => [
          a.submitted_date ? format(new Date(a.submitted_date), "MMM d, yyyy") : a.created_at ? format(new Date(a.created_at), "MMM d, yyyy") : "—",
          ownerName(a),
          propertyAddr(a),
          a.title || "—",
          a.project_type || "—",
          a.associations?.name || "—",
          getStatus(a.status).label,
        ]),
        styles: { fontSize: 9, cellPadding: 5 },
        headStyles: { fillColor: [59, 130, 246] },
      });
      doc.save(`ARC_Applications_${format(new Date(), "yyyy-MM-dd")}.pdf`);
      setExportOpen(false);
    } catch (err: any) {
      toast({ title: "Export failed", description: err.message, variant: "destructive" });
    } finally {
      setExporting(false);
    }
  };

  const fetchData = async () => {
    setLoading(true);
    let appQuery = supabase
      .from("arc_applications")
      .select("*, units(unit_number, address), associations(name), owners(first_name, last_name, property_address)")
      .order("created_at", { ascending: false });
    let assocQuery = supabase.from("associations").select("*").eq("status", "active").order("name");
    let unitsQuery = supabase.from("units").select("*").order("unit_number");
    let ownersQuery = supabase.from("owners").select("id, first_name, last_name, property_address, unit_id, association_id, units(unit_number)").eq("status", "active").order("last_name");

    if (isBoardView) {
      appQuery = appQuery.in("association_id", boardAssociationIds!);
      assocQuery = assocQuery.in("id", boardAssociationIds!);
      unitsQuery = unitsQuery.in("association_id", boardAssociationIds!);
      ownersQuery = ownersQuery.in("association_id", boardAssociationIds!);
    }

    const [appRes, assocRes, unitsRes, ownersRes] = await Promise.all([appQuery, assocQuery, unitsQuery, ownersQuery]);
    if (appRes.data) setApplications(appRes.data as AppRow[]);
    if (assocRes.data) setAssociations(assocRes.data);
    if (unitsRes.data) setUnits(unitsRes.data);
    if (ownersRes.data) setOwners(ownersRes.data);
    setLoading(false);
  };

  useEffect(() => { fetchData(); }, []);

  // Dropzone for ARC file uploads
  const onArcDrop = useCallback((acceptedFiles: File[]) => {
    const maxFiles = 15;
    const maxSize = 20 * 1024 * 1024; // 20MB
    const valid = acceptedFiles.filter(f => f.size <= maxSize);
    setArcFiles(prev => [...prev, ...valid].slice(0, maxFiles));
  }, []);

  const { getRootProps: getArcRootProps, getInputProps: getArcInputProps, isDragActive: isArcDragActive } = useDropzone({
    onDrop: onArcDrop,
    maxSize: 20 * 1024 * 1024,
    maxFiles: 15,
  });

  /* ── Counts per status ─── */
  const statusCounts = useMemo(() => {
    const c: Record<string, number> = { all: applications.length };
    for (const a of applications) {
      const s = a.status || "submitted";
      c[s] = (c[s] || 0) + 1;
    }
    return c;
  }, [applications]);

  /* ── Filter ─── */
  const filtered = useMemo(() => {
    let result = applications;
    if (statusFilter !== "all") result = result.filter((a) => (a.status || "submitted") === statusFilter);
    if (assocFilter !== "all") result = result.filter((a) => a.association_id === assocFilter);
    if (search) {
      const q = search.toLowerCase();
      result = result.filter((a) =>
        a.title.toLowerCase().includes(q) ||
        (a.project_type || "").toLowerCase().includes(q) ||
        (a.owners ? `${a.owners.first_name} ${a.owners.last_name}`.toLowerCase().includes(q) : false) ||
        (a.units?.unit_number || "").toLowerCase().includes(q)
      );
    }
    return result;
  }, [applications, statusFilter, assocFilter, search]);

  /* ── Create handler ─── */
  const handleCreate = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setArcUploading(true);
    const form = new FormData(e.currentTarget);
    const assocId = createAssocId;
    const ownerId = createOwnerId || null;
    if (!assocId) {
      toast({ title: "Association required", variant: "destructive" });
      setArcUploading(false);
      return;
    }
    const selectedOwner = owners.find(o => o.id === ownerId);
    const unitId = selectedOwner?.unit_id || (form.get("unit_id") as string) || null;

    try {
      const { data: inserted, error } = await supabase.from("arc_applications").insert({
        association_id: assocId,
        unit_id: unitId,
        owner_id: ownerId,
        title: form.get("title") as string,
        description: (form.get("description") as string) || null,
        project_type: (form.get("project_type") as string) || null,
        status: "submitted",
        submitted_date: new Date().toISOString().split("T")[0],
      }).select("id").single();

      if (error) throw error;

      // Upload attached files
      if (arcFiles.length > 0 && inserted) {
        for (const file of arcFiles) {
          const storagePath = `${assocId}/${inserted.id}/${Date.now()}-${file.name}`;
          await supabase.storage.from("arc-files").upload(storagePath, file, { contentType: file.type });
        }
      }

      // Notify staff + ARC committee members for this association
      try {
        const { notifyStaffOfArcSubmission } = await import("@/lib/arcSubmissionEmail");
        const assocName = associations.find((a) => a.id === assocId)?.name;
        notifyStaffOfArcSubmission({
          applicationId: inserted!.id,
          applicationTitle: (form.get("title") as string) || "Architectural review request",
          associationId: assocId,
          associationName: assocName,
          homeownerName: selectedOwner ? `${selectedOwner.first_name || ""} ${selectedOwner.last_name || ""}`.trim() : undefined,
          propertyAddress: selectedOwner?.property_address || undefined,
          projectType: (form.get("project_type") as string) || null,
          description: (form.get("description") as string) || null,
          fileCount: arcFiles.length,
        });
      } catch (e) {
        console.error("ARC notification failed", e);
      }

      toast({ title: "Application submitted" });
      setDialogOpen(false);
      setArcFiles([]);
      setCreateAssocId("");
      setCreateOwnerId("");
      fetchData();
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    } finally {
      setArcUploading(false);
    }
  };

  /* ── Status update ─── */
  const handleStatusChange = async (id: string, newStatus: string, decisionNotes?: string) => {
    const update: any = { status: newStatus, updated_at: new Date().toISOString() };
    if (newStatus === "approved" || newStatus === "denied") {
      update.review_date = new Date().toISOString().split("T")[0];
    }
    if (decisionNotes !== undefined) update.decision_notes = decisionNotes;

    const { error } = await supabase.from("arc_applications").update(update).eq("id", id);
    if (error) {
      toast({ title: "Error", description: error.message, variant: "destructive" });
    } else {
      toast({ title: `Application ${getStatus(newStatus).label.toLowerCase()}` });
      fetchData();
      // Update selected app in panel
      setSelectedApp((prev) => prev && prev.id === id ? { ...prev, ...update } : prev);
    }
  };

  const ownerName = (app: AppRow) =>
    app.owners ? `${app.owners.first_name} ${app.owners.last_name}` : "—";

  const propertyAddr = (app: AppRow) =>
    app.units?.address || app.owners?.property_address || app.units?.unit_number || "—";

  return (
    <div className="space-y-5">
      {/* ── Header ── */}
      <div className="flex items-start justify-between">
        <div className="flex items-center gap-3">
          <div className="flex h-10 w-10 items-center justify-center rounded-xl bg-primary/10">
            <Gavel className="h-5 w-5 text-primary" />
          </div>
          <div>
            <h1 className="text-[22px] font-bold tracking-tight text-foreground">ARC Applications</h1>
            <p className="text-[13px] text-muted-foreground">Manage architectural review requests and committee decisions</p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <Button variant="outline" size="sm" className="gap-1.5 h-8 text-[12px]" onClick={fetchData}>
            <RefreshCw className="h-3.5 w-3.5" /> Refresh
          </Button>
          <Button variant="outline" size="sm" className="gap-1.5 h-8 text-[12px]" onClick={() => setExportOpen(true)}>
            <Download className="h-3.5 w-3.5" /> Export PDF
          </Button>
          {isAdmin && !isBoardView && (
            <Button
              variant="outline"
              size="sm"
              className="gap-1.5 h-8 text-[12px]"
              disabled={importing}
              onClick={async () => {
                const assocIds = (assocFilter !== "all" ? [assocFilter] : associations.map(a => a.id));
                if (assocIds.length === 0) {
                  toast({ variant: "destructive", title: "No associations available" });
                  return;
                }
                setImporting(true);
                try {
                  const { data, error } = await supabase.functions.invoke("buildium-import-stage", {
                    body: { kinds: ["arc_application"], selectedAssociationIds: assocIds },
                  });
                  if (error) throw error;
                  toast({
                    title: "ARC pulled for review",
                    description: `${data?.inserted ?? 0} items staged. Review them before applying.`,
                  });
                  navigate(`/dashboard/settings/buildium/review?batch_id=${data?.batch_id || ""}`);
                } catch (err: any) {
                  toast({ variant: "destructive", title: "Import failed", description: err?.message || String(err) });
                } finally {
                  setImporting(false);
                }
              }}
            >
              <Download className="h-3.5 w-3.5" /> {importing ? "Importing…" : "Import from Buildium"}
            </Button>
          )}
          {!isBoardView && (
            <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
              <DialogTrigger asChild>
                <Button size="sm" className="gap-1.5 h-8 text-[12px]">
                  <Plus className="h-3.5 w-3.5" /> New Application
                </Button>
              </DialogTrigger>
              <DialogContent className="sm:max-w-[540px] max-h-[90vh] overflow-y-auto">
                <DialogHeader><DialogTitle>Submit ARC Application</DialogTitle></DialogHeader>
                <form onSubmit={handleCreate} className="space-y-5">
                   {/* Association */}
                   <div className="space-y-2">
                     <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Association *</Label>
                     <Select value={createAssocId} onValueChange={(v) => { setCreateAssocId(v); setCreateOwnerId(""); }}>
                       <SelectTrigger><SelectValue placeholder="Select association" /></SelectTrigger>
                       <SelectContent>{associations.map((a) => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}</SelectContent>
                     </Select>
                   </div>

                   {/* Ownership Account — searchable, scoped to association */}
                   <div className="space-y-2">
                     <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Ownership Account *</Label>
                     {!createAssocId ? (
                       <p className="text-xs text-muted-foreground">Select an association first to choose an owner.</p>
                     ) : (
                       <Combobox
                         options={owners
                           .filter((o) => o.association_id === createAssocId)
                           .map((o) => ({
                             value: o.id,
                             label: `${o.property_address || o.units?.unit_number || "—"} — ${o.first_name || ""} ${o.last_name || ""}`.trim(),
                           }))}
                         value={createOwnerId}
                         onChange={(v) => setCreateOwnerId(v)}
                         placeholder="Search owner by name or address..."
                       />
                     )}
                   </div>

                  {/* Date & Time */}
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Date of Request *</Label>
                      <Input name="request_date" type="date" defaultValue={format(new Date(), "yyyy-MM-dd")} required />
                    </div>
                    <div className="space-y-2">
                      <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Time *</Label>
                      <Input name="request_time" type="time" defaultValue={format(new Date(), "HH:mm")} required />
                      <p className="text-[11px] text-muted-foreground">Eastern Time (US and Canada)</p>
                    </div>
                  </div>

                  {/* File Upload */}
                  <div className="space-y-2">
                    <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">File Upload (Optional)</Label>
                    <p className="text-xs text-muted-foreground">Each file must be 20 MB or less. Attach up to 15 files.</p>
                    <div
                      {...getArcRootProps()}
                      className={`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${
                        isArcDragActive ? "border-primary bg-primary/5" : "border-border hover:border-primary/50"
                      }`}
                    >
                      <input {...getArcInputProps()} />
                      <div className="flex flex-col items-center gap-2">
                        <UploadCloud className="h-8 w-8 text-muted-foreground/40" />
                        <p className="text-sm text-muted-foreground">
                          Drag & drop files here or <span className="text-primary font-medium cursor-pointer">browse</span>
                        </p>
                      </div>
                    </div>
                    {arcFiles.length > 0 && (
                      <div className="space-y-1 mt-2 max-h-[120px] overflow-y-auto">
                        {arcFiles.map((f, i) => (
                          <div key={i} className="flex items-center justify-between text-sm py-1.5 px-2 rounded border bg-muted/30">
                            <div className="flex items-center gap-2 min-w-0">
                              <File className="h-4 w-4 text-muted-foreground shrink-0" />
                              <span className="truncate text-xs">{f.name}</span>
                            </div>
                            <Button type="button" variant="ghost" size="icon" className="h-6 w-6 shrink-0" onClick={() => setArcFiles(prev => prev.filter((_, idx) => idx !== i))}>
                              <X className="h-3 w-3" />
                            </Button>
                          </div>
                        ))}
                      </div>
                    )}
                  </div>

                  {/* Project Name */}
                  <div className="space-y-2">
                    <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Project Name *</Label>
                    <Input name="title" required maxLength={30} placeholder="e.g. Fence Replacement" />
                    <p className="text-[11px] text-muted-foreground text-right">30 character limit</p>
                  </div>

                  {/* Description */}
                  <div className="space-y-2">
                    <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Description</Label>
                    <Textarea name="description" placeholder="Describe the project details..." />
                  </div>

                  {/* Project Type */}
                  <div className="space-y-2">
                    <Label className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Project Type</Label>
                    <Input name="project_type" placeholder="e.g. Fence, Roof, Paint" />
                  </div>

                  <Separator />

                  {/* Sharing / Notifications */}
                  <div className="space-y-3">
                    <div>
                      <h3 className="text-sm font-semibold text-foreground">Sharing</h3>
                      <p className="text-xs text-muted-foreground">These people will be notified of this new request.</p>
                    </div>
                    <div className="space-y-2">
                      <label className="flex items-start gap-3 p-3 rounded-lg border cursor-pointer hover:bg-muted/30 transition-colors">
                        <Checkbox checked={notifyStaff} onCheckedChange={(v) => setNotifyStaff(!!v)} className="mt-0.5" />
                        <div>
                          <p className="text-sm font-medium">Staff</p>
                          <p className="text-xs text-muted-foreground">Email staff members with access to architectural requests.</p>
                        </div>
                      </label>
                      <label className="flex items-start gap-3 p-3 rounded-lg border cursor-pointer hover:bg-muted/30 transition-colors">
                        <Checkbox checked={notifyOwners} onCheckedChange={(v) => setNotifyOwners(!!v)} className="mt-0.5" />
                        <div>
                          <p className="text-sm font-medium">Association owner(s)</p>
                          <p className="text-xs text-muted-foreground">Email homeowner(s) and share to Resident Center.</p>
                        </div>
                      </label>
                    </div>
                  </div>

                  <DialogFooter>
                    <Button type="button" variant="outline" onClick={() => { setDialogOpen(false); setArcFiles([]); }}>Cancel</Button>
                    <Button type="submit" disabled={arcUploading}>
                      {arcUploading ? "Saving..." : "Save"}
                    </Button>
                  </DialogFooter>
                </form>
              </DialogContent>
            </Dialog>
          )}
        </div>
      </div>

      {/* ── Filters Bar ── */}
      <div className="flex flex-wrap items-center gap-3">
        <div className="relative flex-1 min-w-[200px] max-w-sm">
          <Search className="absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
          <Input
            placeholder="Search owner, address, project..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="pl-9 h-9 text-[13px]"
          />
        </div>
        <Select value={assocFilter} onValueChange={setAssocFilter}>
          <SelectTrigger className="w-[200px] h-9 text-[13px]">
            <Filter className="h-3.5 w-3.5 mr-1.5 text-muted-foreground" />
            <SelectValue placeholder="All Associations" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All Associations</SelectItem>
            {associations.map((a) => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}
          </SelectContent>
        </Select>
      </div>

      {/* ── Status Tabs ── */}
      <Tabs value={statusFilter} onValueChange={setStatusFilter}>
        <TabsList className="bg-muted/50 h-9">
          {[
            { value: "all", label: "All" },
            { value: "submitted", label: "Submitted" },
            { value: "under_review", label: "Under Review" },
            { value: "awaiting_changes", label: "Awaiting Changes" },
            { value: "approved", label: "Approved" },
            { value: "denied", label: "Denied" },
          ].map((tab) => (
            <TabsTrigger key={tab.value} value={tab.value} className="text-[12px] gap-1.5 data-[state=active]:shadow-sm">
              {tab.label}
              {(statusCounts[tab.value] ?? 0) > 0 && (
                <span className="ml-1 rounded-full bg-foreground/10 px-1.5 py-0.5 text-[10px] font-semibold leading-none">
                  {statusCounts[tab.value]}
                </span>
              )}
            </TabsTrigger>
          ))}
        </TabsList>
      </Tabs>

      {/* ── Bulk Actions Bar ── */}
      {selectedIds.size > 0 && (
        <div className="flex flex-col gap-2 rounded-lg border bg-muted/30 px-3 py-2">
          <div className="flex items-center gap-3 flex-wrap">
            <span className="text-[12px] font-medium">{selectedIds.size} selected</span>
            <Input
              placeholder="New project type (blank to clear)"
              value={bulkType}
              onChange={(e) => setBulkType(e.target.value)}
              className="h-8 max-w-xs text-[12px]"
            />
            <Button size="sm" className="h-8 text-[12px]" disabled={bulkSaving} onClick={handleBulkUpdateType}>
              {bulkSaving ? "Updating…" : "Update Project Type"}
            </Button>
            <Button size="sm" variant="ghost" className="h-8 text-[12px]" onClick={() => setSelectedIds(new Set())}>
              Clear
            </Button>
          </div>
          <div className="flex items-center gap-3 flex-wrap">
            <Select value={bulkOwnerId} onValueChange={setBulkOwnerId}>
              <SelectTrigger className="h-8 max-w-xs text-[12px]"><SelectValue placeholder="Reassign to owner..." /></SelectTrigger>
              <SelectContent>
                {owners.map((o) => (
                  <SelectItem key={o.id} value={o.id}>
                    {o.first_name} {o.last_name} {o.property_address ? `— ${o.property_address}` : ""}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Button size="sm" className="h-8 text-[12px]" disabled={bulkSaving || !bulkOwnerId} onClick={handleBulkUpdateOwner}>
              {bulkSaving ? "Updating…" : "Reassign Owner"}
            </Button>
            <Input
              placeholder="New address (applies to owner & unit)"
              value={bulkAddress}
              onChange={(e) => setBulkAddress(e.target.value)}
              className="h-8 max-w-xs text-[12px]"
            />
            <Button size="sm" className="h-8 text-[12px]" disabled={bulkSaving || !bulkAddress.trim()} onClick={handleBulkUpdateAddress}>
              {bulkSaving ? "Updating…" : "Update Address"}
            </Button>
          </div>
        </div>
      )}

      {/* ── Export Dialog ── */}
      <Dialog open={exportOpen} onOpenChange={setExportOpen}>
        <DialogContent className="sm:max-w-[425px]">
          <DialogHeader>
            <DialogTitle>Export ARC Report</DialogTitle>
          </DialogHeader>
          <p className="text-xs text-muted-foreground">
            Filter by submitted date range. Leave blank to include all. Current filters (status, association, search) also apply.
          </p>
          <div className="grid grid-cols-2 gap-4 py-2">
            <div className="space-y-2">
              <Label>Start Date</Label>
              <Input type="date" value={exportStart} onChange={(e) => setExportStart(e.target.value)} />
            </div>
            <div className="space-y-2">
              <Label>End Date</Label>
              <Input type="date" value={exportEnd} onChange={(e) => setExportEnd(e.target.value)} />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setExportOpen(false)} disabled={exporting}>Cancel</Button>
            <Button onClick={handleExportPdf} disabled={exporting}>
              {exporting ? "Generating…" : "Export PDF"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* ── Application Table ── */}
      {loading ? (
        <div className="flex justify-center py-16">
          <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
        </div>
      ) : filtered.length === 0 ? (
        <Card>
          <CardContent className="py-16 text-center text-muted-foreground">
            <Gavel className="mx-auto h-10 w-10 mb-3 opacity-30" />
            <p className="font-medium">{search || statusFilter !== "all" ? "No applications match your filters." : "No ARC applications yet."}</p>
            <p className="text-[12px] mt-1">Submit a new application to get started.</p>
          </CardContent>
        </Card>
      ) : (
        <div className="rounded-lg border bg-card overflow-hidden">
          <Table>
            <TableHeader>
              <TableRow className="bg-muted/30">
                <TableHead className="w-[36px]">
                  <Checkbox
                    checked={filtered.length > 0 && filtered.every((a) => selectedIds.has(a.id))}
                    onCheckedChange={(v) => {
                      if (v) setSelectedIds(new Set(filtered.map((a) => a.id)));
                      else setSelectedIds(new Set());
                    }}
                  />
                </TableHead>
                <TableHead className="text-[11px] font-semibold uppercase tracking-wide">Owner</TableHead>
                <TableHead className="text-[11px] font-semibold uppercase tracking-wide">Address</TableHead>
                <TableHead className="text-[11px] font-semibold uppercase tracking-wide">Project Type</TableHead>
                <TableHead className="text-[11px] font-semibold uppercase tracking-wide">Association</TableHead>
                <TableHead className="text-[11px] font-semibold uppercase tracking-wide">Date Submitted</TableHead>
                <TableHead className="text-[11px] font-semibold uppercase tracking-wide">Status</TableHead>
                <TableHead className="w-[40px]" />
              </TableRow>
            </TableHeader>
            <TableBody>
              {filtered.map((app) => {
                const st = getStatus(app.status);
                return (
                  <TableRow
                    key={app.id}
                    className="cursor-pointer hover:bg-muted/40 transition-colors"
                    onClick={() => setSelectedApp(app)}
                  >
                    <TableCell onClick={(e) => e.stopPropagation()}>
                      <Checkbox
                        checked={selectedIds.has(app.id)}
                        onCheckedChange={() => toggleSelect(app.id)}
                      />
                    </TableCell>
                    <TableCell>
                      <div className="flex items-center gap-2">
                        <div className="h-7 w-7 rounded-full bg-muted flex items-center justify-center shrink-0">
                          <User className="h-3.5 w-3.5 text-muted-foreground" />
                        </div>
                        <div>
                          <p className="text-[13px] font-medium text-foreground leading-tight">{ownerName(app)}</p>
                          <p className="text-[11px] text-muted-foreground">{app.title}</p>
                        </div>
                      </div>
                    </TableCell>
                    <TableCell className="text-[13px] text-muted-foreground">{propertyAddr(app)}</TableCell>
                    <TableCell className="text-[13px] text-foreground">{app.project_type || "—"}</TableCell>
                    <TableCell className="text-[13px] text-muted-foreground">{app.associations?.name || "—"}</TableCell>
                    <TableCell className="text-[13px] text-muted-foreground">
                      {app.submitted_date ? format(new Date(app.submitted_date), "MMM d, yyyy") : app.created_at ? format(new Date(app.created_at), "MMM d, yyyy") : "—"}
                    </TableCell>
                    <TableCell>
                      <Badge variant="outline" className={`text-[11px] font-medium border ${st.cls}`}>
                        {st.label}
                      </Badge>
                    </TableCell>
                    <TableCell>
                      <ChevronRight className="h-4 w-4 text-muted-foreground/40" />
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </div>
      )}

      {/* ── Slide-out Detail Panel ── */}
      <Sheet open={!!selectedApp} onOpenChange={(open) => !open && setSelectedApp(null)}>
        <SheetContent className="sm:max-w-xl w-full overflow-y-auto p-0">
          {selectedApp && (
            <ARCDetailPanel
              app={selectedApp}
              onStatusChange={handleStatusChange}
              onClose={() => setSelectedApp(null)}
              onRefresh={fetchData}
            />
          )}
        </SheetContent>
      </Sheet>
    </div>
  );
}

/* ════════════════════════════════════════════════════════════
   Detail Panel
   ════════════════════════════════════════════════════════════ */

function ARCDetailPanel({
  app,
  onStatusChange,
  onClose,
  onRefresh,
}: {
  app: AppRow;
  onStatusChange: (id: string, status: string, notes?: string) => void;
  onClose: () => void;
  onRefresh: () => void;
}) {
  const st = getStatus(app.status);
  const StIcon = st.icon;
  const [decisionNotes, setDecisionNotes] = useState(app.decision_notes || "");
  const [activeSection, setActiveSection] = useState<"details" | "review" | "timeline">("details");
  const [voteRefreshKey, setVoteRefreshKey] = useState(0);
  const { isAdmin } = useAuth();
  const { toast } = useToast();
  const [editing, setEditing] = useState(false);
  const [savingEdit, setSavingEdit] = useState(false);
  const [editForm, setEditForm] = useState({
    title: app.title || "",
    project_type: app.project_type || "",
    description: app.description || "",
    submitted_date: app.submitted_date || "",
    owner_id: app.owner_id || "",
    address_override: app.units?.address || app.owners?.property_address || "",
  });
  const [ownerOptions, setOwnerOptions] = useState<any[]>([]);

  useEffect(() => {
    setEditForm({
      title: app.title || "",
      project_type: app.project_type || "",
      description: app.description || "",
      submitted_date: app.submitted_date || "",
      owner_id: app.owner_id || "",
      address_override: app.units?.address || app.owners?.property_address || "",
    });
    setEditing(false);
  }, [app.id]);

  useEffect(() => {
    if (!editing || !app.association_id) return;
    (async () => {
      const { data } = await supabase
        .from("owners")
        .select("id, first_name, last_name, property_address, unit_id")
        .eq("association_id", app.association_id)
        .neq("status", "archived")
        .order("last_name");
      setOwnerOptions(data ?? []);
    })();
  }, [editing, app.association_id]);

  const saveEdit = async () => {
    setSavingEdit(true);
    try {
      const selectedOwner = ownerOptions.find((o) => o.id === editForm.owner_id);
      const updates: any = {
        title: editForm.title.trim() || "Untitled",
        project_type: editForm.project_type.trim() || null,
        description: editForm.description,
        submitted_date: editForm.submitted_date || null,
        owner_id: editForm.owner_id || null,
      };
      if (selectedOwner) {
        updates.unit_id = selectedOwner.unit_id || null;
      }
      const { error } = await supabase
        .from("arc_applications")
        .update(updates)
        .eq("id", app.id);
      if (error) throw error;

      const newAddress = editForm.address_override.trim();
      if (selectedOwner && newAddress && newAddress !== (selectedOwner.property_address || "")) {
        await supabase.from("owners").update({ property_address: newAddress }).eq("id", selectedOwner.id);
      }

      toast({ title: "Saved", description: "Application updated." });
      setEditing(false);
      onRefresh();
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    } finally {
      setSavingEdit(false);
    }
  };


  const ownerName = app.owners ? `${app.owners.first_name} ${app.owners.last_name}` : "—";
  const address = app.units?.address || app.owners?.property_address || app.units?.unit_number || "—";

  const timelineEvents = [
    { date: app.submitted_date || app.created_at, label: "Application Submitted", icon: FileText, color: "text-blue-600 bg-blue-100" },
    ...(app.status === "under_review" || app.status === "approved" || app.status === "denied" || app.status === "awaiting_changes"
      ? [{ date: app.updated_at, label: "Review Started", icon: Clock, color: "text-amber-600 bg-amber-100" }]
      : []),
    ...(app.status === "awaiting_changes"
      ? [{ date: app.updated_at, label: "Changes Requested", icon: AlertCircle, color: "text-orange-600 bg-orange-100" }]
      : []),
    ...(app.review_date
      ? [{ date: app.review_date, label: app.status === "approved" ? "Application Approved" : app.status === "denied" ? "Application Denied" : "Decision Made", icon: app.status === "approved" ? CheckCircle2 : XCircle, color: app.status === "approved" ? "text-emerald-600 bg-emerald-100" : "text-red-600 bg-red-100" }]
      : []),
  ].filter(Boolean);

  return (
    <div className="flex flex-col h-full">
      {/* Panel Header */}
      <div className="p-5 border-b bg-muted/20">
        <div className="flex items-start justify-between mb-3 gap-2">
          <Badge variant="outline" className={`text-[11px] font-medium border ${st.cls} gap-1`}>
            <StIcon className="h-3 w-3" /> {st.label}
          </Badge>
          <div className="flex items-center gap-2">
            <Button
              size="sm"
              variant="outline"
              className="h-7 text-[11px] gap-1"
              onClick={async () => {
                try {
                  const { generateArcApplicationRecord } = await import("@/lib/arcApplicationRecordPdf");
                  await generateArcApplicationRecord(app);
                  toast({ title: "Record exported", description: "PDF downloaded." });
                } catch (e: any) {
                  toast({ title: "Export failed", description: e.message, variant: "destructive" });
                }
              }}
            >
              <Download className="h-3 w-3" /> Export Record
            </Button>
            <span className="text-[11px] text-muted-foreground">
              {app.submitted_date ? format(new Date(app.submitted_date), "MMMM d, yyyy") : "—"}
            </span>
          </div>
        </div>
        <h2 className="text-[18px] font-semibold text-foreground leading-tight">{app.title}</h2>
        <div className="flex items-center gap-4 mt-2 text-[12px] text-muted-foreground">
          <span className="flex items-center gap-1"><User className="h-3 w-3" /> {ownerName}</span>
          <span className="flex items-center gap-1"><Home className="h-3 w-3" /> {address}</span>
          {app.project_type && (
            <span className="flex items-center gap-1"><Gavel className="h-3 w-3" /> {app.project_type}</span>
          )}
        </div>
      </div>

      {/* Section Tabs */}
      <div className="border-b bg-background">
        <div className="flex">
          {(["details", "review", "timeline"] as const).map((section) => (
            <button
              key={section}
              onClick={() => setActiveSection(section)}
              className={`px-4 py-2.5 text-[12px] font-medium capitalize transition-colors border-b-2 ${
                activeSection === section
                  ? "border-primary text-primary"
                  : "border-transparent text-muted-foreground hover:text-foreground"
              }`}
            >
              {section === "details" ? "Application Details" : section === "review" ? "Review & Decision" : "Timeline"}
            </button>
          ))}
        </div>
      </div>

      {/* Section Content */}
      <div className="flex-1 overflow-y-auto p-5 space-y-5">
        {activeSection === "details" && (
          <>
            {isAdmin && (
              <div className="flex justify-end">
                {!editing ? (
                  <Button size="sm" variant="outline" onClick={() => setEditing(true)}>Edit Submission</Button>
                ) : (
                  <div className="flex gap-2">
                    <Button size="sm" variant="ghost" onClick={() => setEditing(false)} disabled={savingEdit}>Cancel</Button>
                    <Button size="sm" onClick={saveEdit} disabled={savingEdit}>{savingEdit ? "Saving…" : "Save"}</Button>
                  </div>
                )}
              </div>
            )}

            {/* Project Info */}
            <div>
              <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-3">Project Information</h3>
              {editing ? (
                <div className="grid grid-cols-2 gap-3">
                  <div className="col-span-2 space-y-1">
                    <Label className="text-[12px]">Title</Label>
                    <Input value={editForm.title} maxLength={200} onChange={(e) => setEditForm((f) => ({ ...f, title: e.target.value }))} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-[12px]">Project Type</Label>
                    <Input value={editForm.project_type} maxLength={100} onChange={(e) => setEditForm((f) => ({ ...f, project_type: e.target.value }))} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-[12px]">Submitted Date</Label>
                    <Input type="date" value={editForm.submitted_date || ""} onChange={(e) => setEditForm((f) => ({ ...f, submitted_date: e.target.value }))} />
                  </div>
                  <div className="col-span-2 space-y-1">
                    <Label className="text-[12px]">Homeowner</Label>
                    <Combobox
                      options={ownerOptions.map((o) => ({
                        value: o.id,
                        label: `${o.first_name} ${o.last_name}${o.property_address ? ` — ${o.property_address}` : ""}`,
                      }))}
                      value={editForm.owner_id || ""}
                      onChange={(v) => {
                        const o = ownerOptions.find((x) => x.id === v);
                        setEditForm((f) => ({
                          ...f,
                          owner_id: v,
                          address_override: o?.property_address || f.address_override,
                        }));
                      }}
                      placeholder="Search homeowner..."
                      emptyText="No homeowners found."
                      className="w-full"
                    />
                  </div>
                  <div className="col-span-2 space-y-1">
                    <Label className="text-[12px]">Property Address</Label>
                    <Input
                      value={editForm.address_override}
                      onChange={(e) => setEditForm((f) => ({ ...f, address_override: e.target.value }))}
                      placeholder="123 Main St"
                    />
                    <p className="text-[10px] text-muted-foreground">Updates the selected homeowner's property address.</p>
                  </div>
                </div>
              ) : (
                <div className="grid grid-cols-2 gap-4">
                  <InfoField label="Project Type" value={app.project_type || "—"} />
                  <InfoField label="Association" value={app.associations?.name || "—"} />
                  <InfoField label="Unit" value={app.units?.unit_number || "—"} />
                </div>
              )}
            </div>

            <Separator />

            {/* Description */}
            <div>
              <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-2">Project Description</h3>
              {editing ? (
                <Textarea
                  value={editForm.description}
                  maxLength={5000}
                  onChange={(e) => setEditForm((f) => ({ ...f, description: e.target.value }))}
                  className="min-h-[120px] text-[13px]"
                />
              ) : app.description ? (
                <div className="bg-muted/40 border rounded-lg p-3 text-[13px] text-foreground whitespace-pre-wrap leading-relaxed">
                  {app.description}
                </div>
              ) : (
                <p className="text-[13px] text-muted-foreground italic">No description provided.</p>
              )}
            </div>

            <Separator />

            {/* Documents & Photos */}
            <div>
              <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-3">Documents & Photos</h3>
              <ARCAttachments associationId={app.association_id} appId={app.id} />
            </div>

            <Separator />

            {/* Decision Notes (if any) */}
            {app.decision_notes && (
              <div>
                <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-2">Decision Notes</h3>
                <div className="bg-muted/40 border rounded-lg p-3 text-[13px] text-foreground whitespace-pre-wrap">
                  {app.decision_notes}
                </div>
              </div>
            )}
          </>
        )}

        {activeSection === "review" && (() => {
          const isFinalizedRaw = ["approved", "denied"].includes((app.status || "").toLowerCase());
          const isFinalized = isFinalizedRaw && !isAdmin;
          return (
          <>
            {/* Committee Voting & Comments */}
            <div>
              <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-3 flex items-center gap-1.5">
                <MessageSquare className="h-3.5 w-3.5" /> Committee Review
              </h3>
              <VotingAndComments
                key={voteRefreshKey}
                entityType="arc_application"
                entityId={app.id}
                locked={isFinalized}
                lockedMessage={`This application was ${app.status} and is locked. Votes and comments are read-only.`}
              />
              {!isFinalized && (
                <div className="mt-3">
                  <RecordArcMemberVote
                    entityType="arc_application"
                    entityId={app.id}
                    associationId={app.association_id}
                    onRecorded={() => setVoteRefreshKey((k) => k + 1)}
                  />
                </div>
              )}
            </div>

            <Separator />

            {/* Decision Actions */}
            <div>
              <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-3">Decision</h3>
              {isFinalizedRaw && !isAdmin ? (
                <p className="text-[12px] text-muted-foreground">
                  This application has been <strong>{app.status}</strong> and is locked from further changes.
                </p>
              ) : !isAdmin ? (
                <p className="text-[12px] text-muted-foreground">
                  Only administrators can finalize this application (approve, deny, or request changes).
                </p>
              ) : (
                <div className="space-y-3">
                  <div className="space-y-2">
                    <Label className="text-[12px]">Decision Notes</Label>
                    <Textarea
                      value={decisionNotes}
                      onChange={(e) => setDecisionNotes(e.target.value)}
                      placeholder="Add notes about this decision..."
                      className="min-h-[80px] text-[13px]"
                    />
                  </div>
                  <div className="flex gap-2">
                    <Button
                      size="sm"
                      className="flex-1 gap-1.5 bg-emerald-600 hover:bg-emerald-700 text-white"
                      onClick={() => onStatusChange(app.id, "approved", decisionNotes)}
                    >
                      <CheckCircle2 className="h-3.5 w-3.5" /> Approve
                    </Button>
                    <Button
                      size="sm"
                      variant="outline"
                      className="flex-1 gap-1.5 text-orange-600 border-orange-300 hover:bg-orange-50"
                      onClick={() => onStatusChange(app.id, "awaiting_changes", decisionNotes)}
                    >
                      <AlertCircle className="h-3.5 w-3.5" /> Request Changes
                    </Button>
                    <Button
                      size="sm"
                      variant="outline"
                      className="flex-1 gap-1.5 text-destructive border-destructive/30 hover:bg-destructive/5"
                      onClick={() => onStatusChange(app.id, "denied", decisionNotes)}
                    >
                      <XCircle className="h-3.5 w-3.5" /> Deny
                    </Button>
                  </div>
                  {app.status === "submitted" && (
                    <Button
                      size="sm"
                      variant="secondary"
                      className="w-full gap-1.5"
                      onClick={() => onStatusChange(app.id, "under_review")}
                    >
                      <Clock className="h-3.5 w-3.5" /> Mark as Under Review
                    </Button>
                  )}
                  {isFinalizedRaw && isAdmin && (
                    <DecisionFollowUpActions app={app} decision={app.status as 'approved' | 'denied'} />
                  )}
                </div>
              )}
            </div>
          </>
          );
        })()}

        {activeSection === "timeline" && (
          <div>
            <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground mb-4">Decision History</h3>
            <div className="relative space-y-0">
              {timelineEvents.map((event, idx) => {
                const EvIcon = event.icon;
                return (
                  <div key={idx} className="flex gap-3 pb-6 last:pb-0 relative">
                    {/* vertical line */}
                    {idx < timelineEvents.length - 1 && (
                      <div className="absolute left-[13px] top-[28px] bottom-0 w-px bg-border" />
                    )}
                    <div className={`h-7 w-7 rounded-full flex items-center justify-center shrink-0 ${event.color}`}>
                      <EvIcon className="h-3.5 w-3.5" />
                    </div>
                    <div className="pt-0.5">
                      <p className="text-[13px] font-medium text-foreground">{event.label}</p>
                      <p className="text-[11px] text-muted-foreground">
                        {event.date ? format(new Date(event.date), "MMMM d, yyyy 'at' h:mm a") : "—"}
                      </p>
                    </div>
                  </div>
                );
              })}
              {timelineEvents.length === 0 && (
                <p className="text-[13px] text-muted-foreground text-center py-8">No timeline events yet.</p>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

/* ── Helpers ── */

function InfoField({ label, value }: { label: string; value: string }) {
  return (
    <div>
      <p className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide">{label}</p>
      <p className="text-[13px] font-medium text-foreground mt-0.5">{value}</p>
    </div>
  );
}

function DecisionFollowUpActions({ app, decision }: { app: AppRow; decision: 'approved' | 'denied' }) {
  const { toast } = useToast();
  const [sending, setSending] = useState(false);

  const handleEmail = async () => {
    setSending(true);
    try {
      let ownerEmail: string | null = null;
      let ownerName: string | null = null;
      if (app.owner_id) {
        const { data } = await supabase
          .from('owners')
          .select('email, first_name, last_name')
          .eq('id', app.owner_id)
          .maybeSingle();
        ownerEmail = data?.email || null;
        ownerName = data ? `${data.first_name || ''} ${data.last_name || ''}`.trim() : null;
      }
      if (!ownerEmail) {
        toast({ title: 'No email on file', description: 'Add an email to the homeowner record to send this letter.', variant: 'destructive' });
        return;
      }
      const propertyAddress =
        app.units?.address || app.owners?.property_address || app.units?.unit_number || '';
      const reviewDate = app.review_date
        ? format(new Date(app.review_date), 'MMMM d, yyyy')
        : format(new Date(), 'MMMM d, yyyy');
      const { error } = await supabase.functions.invoke('send-transactional-email', {
        body: {
          templateName: 'arc-application-decision',
          recipientEmail: ownerEmail,
          idempotencyKey: `arc-decision-${app.id}-${decision}`,
          templateData: {
            decision,
            homeownerName: ownerName || undefined,
            associationName: app.associations?.name || undefined,
            propertyAddress: propertyAddress || undefined,
            applicationTitle: app.title || undefined,
            projectType: app.project_type || undefined,
            decisionNotes: app.decision_notes || undefined,
            reviewDate,
          },
        },
      });
      if (error) throw error;
      toast({ title: 'Email sent', description: `${decision === 'approved' ? 'Approval' : 'Denial'} notice emailed to ${ownerEmail}.` });
    } catch (err: any) {
      toast({ title: 'Email failed', description: err?.message || 'Unable to send email.', variant: 'destructive' });
    } finally {
      setSending(false);
    }
  };

  const handleLetter = () => {
    try {
      generateArcDecisionLetterPdf({
        decision,
        application: app,
        decisionNotes: app.decision_notes || '',
      });
    } catch (err: any) {
      toast({ title: 'Letter failed', description: err?.message || 'Unable to generate letter.', variant: 'destructive' });
    }
  };

  return (
    <div className="flex flex-wrap gap-2 pt-1">
      <Button size="sm" variant="outline" className="gap-1.5" onClick={handleEmail} disabled={sending}>
        <Mail className="h-3.5 w-3.5" />
        {sending ? 'Sending…' : `Email ${decision === 'approved' ? 'Approval' : 'Denial'}`}
      </Button>
      <Button size="sm" variant="outline" className="gap-1.5" onClick={handleLetter}>
        <FileText className="h-3.5 w-3.5" />
        Generate {decision === 'approved' ? 'Approval' : 'Denial'} Letter
      </Button>
    </div>
  );
}

function ARCAttachments({ associationId, appId }: { associationId: string; appId: string }) {
  const [files, setFiles] = useState<Array<{ name: string; url: string; isImage: boolean }>>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setLoading(true);
      const prefix = `${associationId}/${appId}`;
      const { data, error } = await supabase.storage.from("arc-files").list(prefix, { limit: 200 });
      if (cancelled) return;
      if (error || !data) {
        setFiles([]);
        setLoading(false);
        return;
      }
      const mapped = data
        .filter((f) => f.name && !f.name.endsWith("/"))
        .map((f) => {
          const path = `${prefix}/${f.name}`;
          const { data: pub } = supabase.storage.from("arc-files").getPublicUrl(path);
          const display = f.name.replace(/^buildium-\d+-/, "");
          return {
            name: display,
            url: pub.publicUrl,
            isImage: /\.(jpe?g|png|gif|webp|heic)$/i.test(f.name),
          };
        });
      setFiles(mapped);
      setLoading(false);
    })();
    return () => { cancelled = true; };
  }, [associationId, appId]);

  if (loading) {
    return <p className="text-[12px] text-muted-foreground">Loading attachments…</p>;
  }
  if (files.length === 0) {
    return (
      <Card className="border-dashed">
        <CardContent className="p-4 text-center">
          <Paperclip className="h-6 w-6 text-muted-foreground/30 mx-auto mb-1.5" />
          <p className="text-[12px] text-muted-foreground">No attachments uploaded</p>
        </CardContent>
      </Card>
    );
  }
  return (
    <div className="grid grid-cols-2 gap-2">
      {files.map((f) => (
        <a
          key={f.url}
          href={f.url}
          target="_blank"
          rel="noopener noreferrer"
          className="flex items-center gap-2 p-2 rounded border hover:bg-muted/40 transition-colors group"
        >
          {f.isImage ? (
            <img src={f.url} alt={f.name} className="h-10 w-10 object-cover rounded shrink-0" loading="lazy" />
          ) : (
            <div className="h-10 w-10 rounded bg-muted flex items-center justify-center shrink-0">
              <File className="h-4 w-4 text-muted-foreground" />
            </div>
          )}
          <div className="flex-1 min-w-0">
            <p className="text-[12px] font-medium text-foreground truncate group-hover:text-primary">{f.name}</p>
          </div>
          <Download className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
        </a>
      ))}
    </div>
  );
}
