"use client";

import { useMemo, useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import {
  Search,
  Plus,
  Upload,
  Trash2,
  Pencil,
  Mail,
  Users,
  ListPlus,
  X,
  Send,
  FolderPlus,
  UserPlus,
} from "lucide-react";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { Select } from "@/components/ui/Select";
import { Modal } from "@/components/ui/Modal";
import { Field, Label } from "@/components/ui/Card";
import { cn } from "@/lib/utils/cn";
import { swalConfirm, swalAlert } from "@/lib/utils/swal";
import {
  createContact,
  updateContact,
  deleteContact,
  bulkDeleteContacts,
  importContacts,
  createContactList,
  deleteContactList,
  addContactsToList,
  removeContactFromList,
  sendSurveyToList,
} from "@/lib/actions/audience";
import type { ContactRow, ContactListRow } from "@/lib/queries/audience-queries";

interface AudienceManagerProps {
  initialContacts: ContactRow[];
  initialLists: ContactListRow[];
  invitableSurveys: { id: string; title: string }[];
}

type Tab = "contacts" | "lists";

function initialsOf(name: string): string {
  return name
    .split(" ")
    .map((n) => n[0])
    .join("")
    .slice(0, 2)
    .toUpperCase();
}

function timeAgo(date: Date | string | null): string {
  if (!date) return "Never";
  const diff = Math.floor((Date.now() - new Date(date).getTime()) / 1000);
  if (diff < 60) return "just now";
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
  if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
  if (diff < 604800) return `${Math.floor(diff / 86400)}d ago`;
  return new Date(date).toLocaleDateString();
}

export function AudienceManager({
  initialContacts,
  initialLists,
  invitableSurveys,
}: AudienceManagerProps) {
  const router = useRouter();
  const [tab, setTab] = useState<Tab>("contacts");
  const [search, setSearch] = useState("");
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [isPending, startTransition] = useTransition();

  // Modal states
  const [showAddContact, setShowAddContact] = useState(false);
  const [editingContact, setEditingContact] = useState<ContactRow | null>(null);
  const [showImport, setShowImport] = useState(false);
  const [showCreateList, setShowCreateList] = useState(false);
  const [showAddToList, setShowAddToList] = useState(false);
  const [viewingList, setViewingList] = useState<ContactListRow | null>(null);
  const [invitingList, setInvitingList] = useState<ContactListRow | null>(null);

  const contacts = initialContacts;
  const lists = initialLists;

  const filteredContacts = useMemo(() => {
    if (!search.trim()) return contacts;
    const term = search.trim().toLowerCase();
    return contacts.filter(
      (c) =>
        c.name.toLowerCase().includes(term) ||
        c.email.toLowerCase().includes(term)
    );
  }, [contacts, search]);

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

  function toggleSelectAll() {
    setSelectedIds((prev) =>
      prev.size === filteredContacts.length
        ? new Set()
        : new Set(filteredContacts.map((c) => c.id))
    );
  }

  async function handleDeleteContact(contact: ContactRow) {
    const ok = await swalConfirm({
      title: `Delete "${contact.name}"?`,
      text: "This will remove the contact from all lists as well.",
      confirmText: "Delete",
      danger: true,
    });
    if (!ok) return;
    startTransition(async () => {
      const result = await deleteContact(contact.id);
      if (result.success) router.refresh();
      else void swalAlert("Failed", result.error, "error");
    });
  }

  async function handleBulkDelete() {
    const ok = await swalConfirm({
      title: `Delete ${selectedIds.size} contact(s)?`,
      text: "This action cannot be undone.",
      confirmText: "Delete All",
      danger: true,
    });
    if (!ok) return;
    startTransition(async () => {
      const result = await bulkDeleteContacts(Array.from(selectedIds));
      if (result.success) {
        setSelectedIds(new Set());
        router.refresh();
      } else {
        void swalAlert("Failed", result.error, "error");
      }
    });
  }

  async function handleDeleteList(list: ContactListRow) {
    const ok = await swalConfirm({
      title: `Delete list "${list.name}"?`,
      text: "Contacts will not be deleted, only the list.",
      confirmText: "Delete List",
      danger: true,
    });
    if (!ok) return;
    startTransition(async () => {
      const result = await deleteContactList(list.id);
      if (result.success) router.refresh();
      else void swalAlert("Failed", result.error, "error");
    });
  }

  return (
    <div className="space-y-5">
      {/* Stats */}
      <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
        <div className="rounded border border-border bg-card p-[18px_20px] shadow">
          <div className="mb-2.5 flex items-center justify-between">
            <span className="text-xs font-semibold text-muted">Total Contacts</span>
            <div className="flex h-[30px] w-[30px] items-center justify-center rounded-sm bg-[#EFF6FF] text-primary">
              <Users className="h-[15px] w-[15px]" />
            </div>
          </div>
          <div className="font-mono text-[26px] font-extrabold tracking-tight">
            {contacts.length}
          </div>
        </div>
        <div className="rounded border border-border bg-card p-[18px_20px] shadow">
          <div className="mb-2.5 flex items-center justify-between">
            <span className="text-xs font-semibold text-muted">Contact Lists</span>
            <div className="flex h-[30px] w-[30px] items-center justify-center rounded-sm bg-[#F0FDF4] text-success">
              <ListPlus className="h-[15px] w-[15px]" />
            </div>
          </div>
          <div className="font-mono text-[26px] font-extrabold tracking-tight">
            {lists.length}
          </div>
        </div>
        <div className="rounded border border-border bg-card p-[18px_20px] shadow">
          <div className="mb-2.5 flex items-center justify-between">
            <span className="text-xs font-semibold text-muted">Invites Sent</span>
            <div className="flex h-[30px] w-[30px] items-center justify-center rounded-sm bg-[#FDF4FF] text-[#A21CAF]">
              <Send className="h-[15px] w-[15px]" />
            </div>
          </div>
          <div className="font-mono text-[26px] font-extrabold tracking-tight">
            {contacts.reduce((sum, c) => sum + c.inviteCount, 0)}
          </div>
        </div>
      </div>

      {/* Tabs */}
      <div className="flex items-center justify-between gap-3 border-b border-border">
        <div className="flex gap-1">
          <button
            type="button"
            onClick={() => setTab("contacts")}
            className={cn(
              "border-b-2 px-4 py-2.5 text-[13px] font-semibold transition-colors",
              tab === "contacts"
                ? "border-primary text-primary"
                : "border-transparent text-muted hover:text-navy"
            )}
          >
            All Contacts
          </button>
          <button
            type="button"
            onClick={() => setTab("lists")}
            className={cn(
              "border-b-2 px-4 py-2.5 text-[13px] font-semibold transition-colors",
              tab === "lists"
                ? "border-primary text-primary"
                : "border-transparent text-muted hover:text-navy"
            )}
          >
            Lists
          </button>
        </div>
      </div>

      {tab === "contacts" && (
        <div className="rounded-lg border border-border bg-card shadow">
          {/* Toolbar */}
          <div className="flex flex-wrap items-center justify-between gap-3 border-b border-border p-4">
            <div className="relative w-full max-w-xs">
              <Search className="pointer-events-none absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted" />
              <Input
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                placeholder="Search contacts…"
                className="pl-8"
              />
            </div>
            <div className="flex flex-wrap items-center gap-2">
              {selectedIds.size > 0 && (
                <>
                  <Button
                    variant="outline"
                    size="sm"
                    type="button"
                    onClick={() => setShowAddToList(true)}
                  >
                    <ListPlus className="mr-1 h-3.5 w-3.5" />
                    Add to list ({selectedIds.size})
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    type="button"
                    className="border-danger/30 text-danger hover:bg-danger-bg"
                    onClick={handleBulkDelete}
                    loading={isPending}
                  >
                    <Trash2 className="mr-1 h-3.5 w-3.5" />
                    Delete
                  </Button>
                </>
              )}
              <Button
                variant="outline"
                size="sm"
                type="button"
                onClick={() => setShowImport(true)}
              >
                <Upload className="mr-1 h-3.5 w-3.5" />
                Import
              </Button>
              <Button size="sm" type="button" onClick={() => setShowAddContact(true)}>
                <Plus className="mr-1 h-3.5 w-3.5" />
                Add Contact
              </Button>
            </div>
          </div>

          {/* Table */}
          {filteredContacts.length === 0 ? (
            <div className="flex flex-col items-center justify-center px-5 py-16 text-center">
              <div className="mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary">
                <Users className="h-6 w-6" />
              </div>
              <h3 className="text-base font-bold text-text">
                {contacts.length === 0 ? "No contacts yet" : "No matches found"}
              </h3>
              <p className="mt-2 max-w-sm text-sm text-muted">
                {contacts.length === 0
                  ? "Add contacts manually or import a list to start building your audience."
                  : "Try a different search term."}
              </p>
              {contacts.length === 0 && (
                <Button
                  size="sm"
                  type="button"
                  className="mt-5"
                  onClick={() => setShowAddContact(true)}
                >
                  <Plus className="mr-1 h-3.5 w-3.5" />
                  Add your first contact
                </Button>
              )}
            </div>
          ) : (
            <div className="overflow-x-auto">
              <table className="w-full text-left text-[13px]">
                <thead>
                  <tr className="border-b border-border bg-[#F8FAFC] text-[11px] font-bold uppercase tracking-wider text-muted">
                    <th className="w-10 px-4 py-3">
                      <input
                        type="checkbox"
                        checked={
                          selectedIds.size === filteredContacts.length &&
                          filteredContacts.length > 0
                        }
                        onChange={toggleSelectAll}
                        className="h-4 w-4 rounded border-border accent-primary"
                      />
                    </th>
                    <th className="px-4 py-3">Contact</th>
                    <th className="hidden px-4 py-3 sm:table-cell">Phone</th>
                    <th className="hidden px-4 py-3 md:table-cell">Lists</th>
                    <th className="hidden px-4 py-3 md:table-cell">Last Invited</th>
                    <th className="px-4 py-3 text-right">Actions</th>
                  </tr>
                </thead>
                <tbody>
                  {filteredContacts.map((c) => (
                    <tr
                      key={c.id}
                      className="border-b border-border last:border-b-0 hover:bg-[#F8FAFC]"
                    >
                      <td className="px-4 py-3">
                        <input
                          type="checkbox"
                          checked={selectedIds.has(c.id)}
                          onChange={() => toggleSelect(c.id)}
                          className="h-4 w-4 rounded border-border accent-primary"
                        />
                      </td>
                      <td className="px-4 py-3">
                        <div className="flex items-center gap-2.5">
                          <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent/15 text-[11px] font-bold text-accent">
                            {initialsOf(c.name)}
                          </div>
                          <div className="min-w-0">
                            <div className="truncate font-semibold text-navy">{c.name}</div>
                            <div className="truncate text-[11.5px] text-muted">{c.email}</div>
                          </div>
                        </div>
                      </td>
                      <td className="hidden px-4 py-3 text-muted sm:table-cell">
                        {c.phone || "—"}
                      </td>
                      <td className="hidden px-4 py-3 md:table-cell">
                        <span className="rounded-full bg-[#F1F5F9] px-2 py-0.5 text-[11px] font-semibold text-navy">
                          {c.listIds.length}
                        </span>
                      </td>
                      <td className="hidden px-4 py-3 text-muted md:table-cell">
                        {timeAgo(c.lastInvitedAt)}
                      </td>
                      <td className="px-4 py-3 text-right">
                        <div className="flex justify-end gap-1">
                          <button
                            type="button"
                            onClick={() => setEditingContact(c)}
                            className="rounded-[6px] p-1.5 text-muted transition-colors hover:bg-[#EFF6FF] hover:text-primary"
                            title="Edit"
                          >
                            <Pencil className="h-3.5 w-3.5" />
                          </button>
                          <button
                            type="button"
                            onClick={() => handleDeleteContact(c)}
                            className="rounded-[6px] p-1.5 text-muted transition-colors hover:bg-danger-bg hover:text-danger"
                            title="Delete"
                          >
                            <Trash2 className="h-3.5 w-3.5" />
                          </button>
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}

      {tab === "lists" && (
        <div>
          <div className="mb-4 flex justify-end">
            <Button size="sm" type="button" onClick={() => setShowCreateList(true)}>
              <FolderPlus className="mr-1 h-3.5 w-3.5" />
              Create List
            </Button>
          </div>

          {lists.length === 0 ? (
            <div className="rounded-lg border border-border bg-card shadow">
              <div className="flex flex-col items-center justify-center px-5 py-16 text-center">
                <div className="mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-success-bg text-success">
                  <ListPlus className="h-6 w-6" />
                </div>
                <h3 className="text-base font-bold text-text">No lists yet</h3>
                <p className="mt-2 max-w-sm text-sm text-muted">
                  Create a list to segment your contacts and send targeted survey invites.
                </p>
                <Button
                  size="sm"
                  type="button"
                  className="mt-5"
                  onClick={() => setShowCreateList(true)}
                >
                  <FolderPlus className="mr-1 h-3.5 w-3.5" />
                  Create your first list
                </Button>
              </div>
            </div>
          ) : (
            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
              {lists.map((list) => (
                <div
                  key={list.id}
                  className="rounded-lg border border-border bg-card p-4 shadow transition-shadow hover:shadow-lg"
                >
                  <div className="mb-1 flex items-start justify-between gap-2">
                    <h3 className="truncate text-[14px] font-bold text-navy">{list.name}</h3>
                    <button
                      type="button"
                      onClick={() => handleDeleteList(list)}
                      className="shrink-0 rounded-[6px] p-1 text-muted hover:bg-danger-bg hover:text-danger"
                      title="Delete list"
                    >
                      <Trash2 className="h-3.5 w-3.5" />
                    </button>
                  </div>
                  {list.description && (
                    <p className="mb-3 line-clamp-2 text-[12px] text-muted">{list.description}</p>
                  )}
                  <div className="mb-3 flex items-center gap-1.5 text-[12px] text-muted">
                    <Users className="h-3.5 w-3.5" />
                    <span>
                      {list.contactCount} contact{list.contactCount !== 1 ? "s" : ""}
                    </span>
                  </div>
                  <div className="flex gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      type="button"
                      className="flex-1"
                      onClick={() => setViewingList(list)}
                    >
                      View
                    </Button>
                    <Button
                      size="sm"
                      type="button"
                      className="flex-1"
                      disabled={list.contactCount === 0 || invitableSurveys.length === 0}
                      onClick={() => setInvitingList(list)}
                      title={
                        list.contactCount === 0
                          ? "Add contacts to this list first"
                          : invitableSurveys.length === 0
                            ? "Publish a survey first to unlock invites"
                            : undefined
                      }
                    >
                      <Mail className="mr-1 h-3.5 w-3.5" />
                      Invite
                    </Button>
                  </div>
                  {list.contactCount > 0 && invitableSurveys.length === 0 && (
                    <p className="mt-2 text-[11px] text-muted">
                      Publish a survey to unlock invites for this list.
                    </p>
                  )}
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* --- Modals --- */}
      <AddContactModal
        open={showAddContact}
        onClose={() => setShowAddContact(false)}
        onSaved={() => {
          setShowAddContact(false);
          router.refresh();
        }}
      />

      <EditContactModal
        contact={editingContact}
        onClose={() => setEditingContact(null)}
        onSaved={() => {
          setEditingContact(null);
          router.refresh();
        }}
      />

      <ImportContactsModal
        open={showImport}
        lists={lists}
        onClose={() => setShowImport(false)}
        onImported={() => {
          setShowImport(false);
          router.refresh();
        }}
      />

      <CreateListModal
        open={showCreateList}
        onClose={() => setShowCreateList(false)}
        onCreated={() => {
          setShowCreateList(false);
          router.refresh();
        }}
      />

      <AddToListModal
        open={showAddToList}
        lists={lists}
        selectedCount={selectedIds.size}
        onClose={() => setShowAddToList(false)}
        onAdded={() => {
          setShowAddToList(false);
          setSelectedIds(new Set());
          router.refresh();
        }}
        getSelectedIds={() => Array.from(selectedIds)}
      />

      <ViewListModal
        list={viewingList}
        contacts={
          viewingList ? contacts.filter((c) => c.listIds.includes(viewingList.id)) : []
        }
        onClose={() => setViewingList(null)}
        onChanged={() => router.refresh()}
      />

      <SendInviteModal
        list={invitingList}
        surveys={invitableSurveys}
        onClose={() => setInvitingList(null)}
        onSent={() => {
          setInvitingList(null);
          router.refresh();
        }}
      />
    </div>
  );
}

/* ───────────────────────── Add Contact Modal ───────────────────────── */

function AddContactModal({
  open,
  onClose,
  onSaved,
}: {
  open: boolean;
  onClose: () => void;
  onSaved: () => void;
}) {
  const [form, setForm] = useState({ name: "", email: "", phone: "", notes: "" });
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();

  function handleClose() {
    setForm({ name: "", email: "", phone: "", notes: "" });
    setError(null);
    onClose();
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    startTransition(async () => {
      const result = await createContact({
        name: form.name,
        email: form.email,
        phone: form.phone || null,
        notes: form.notes || null,
      });
      if (result.success) {
        setForm({ name: "", email: "", phone: "", notes: "" });
        onSaved();
      } else {
        setError(result.error ?? "Failed to add contact");
      }
    });
  }

  return (
    <Modal open={open} onClose={handleClose} title="Add Contact" description="Add a single respondent to your audience.">
      <form onSubmit={handleSubmit} className="space-y-4">
        <Field>
          <Label>Full Name *</Label>
          <Input
            value={form.name}
            onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
            placeholder="Jane Doe"
            required
          />
        </Field>
        <Field>
          <Label>Email *</Label>
          <Input
            type="email"
            value={form.email}
            onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
            placeholder="jane@company.com"
            required
          />
        </Field>
        <Field>
          <Label>Phone</Label>
          <Input
            value={form.phone}
            onChange={(e) => setForm((f) => ({ ...f, phone: e.target.value }))}
            placeholder="+1 555 000 0000"
          />
        </Field>
        <Field className="mb-2">
          <Label>Notes</Label>
          <textarea
            value={form.notes}
            onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
            className="min-h-[70px] w-full rounded-sm border border-border p-3 text-sm focus:border-primary focus:outline-none"
            placeholder="Optional notes about this contact"
          />
        </Field>
        {error && <p className="rounded-[8px] bg-danger-bg px-3 py-2 text-[12.5px] text-danger">{error}</p>}
        <div className="flex justify-end gap-2 pt-1">
          <Button type="button" variant="outline" onClick={handleClose}>
            Cancel
          </Button>
          <Button type="submit" loading={isPending}>
            Add Contact
          </Button>
        </div>
      </form>
    </Modal>
  );
}

/* ───────────────────────── Edit Contact Modal ───────────────────────── */

function EditContactModal({
  contact,
  onClose,
  onSaved,
}: {
  contact: ContactRow | null;
  onClose: () => void;
  onSaved: () => void;
}) {
  const [form, setForm] = useState({ name: "", email: "", phone: "", notes: "" });
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();

  useMemo(() => {
    if (contact) {
      setForm({
        name: contact.name,
        email: contact.email,
        phone: contact.phone ?? "",
        notes: contact.notes ?? "",
      });
      setError(null);
    }
  }, [contact]);

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!contact) return;
    setError(null);
    startTransition(async () => {
      const result = await updateContact({
        contactId: contact.id,
        name: form.name,
        email: form.email,
        phone: form.phone || null,
        notes: form.notes || null,
      });
      if (result.success) onSaved();
      else setError(result.error ?? "Failed to update contact");
    });
  }

  return (
    <Modal open={!!contact} onClose={onClose} title="Edit Contact" description="Update contact details.">
      <form onSubmit={handleSubmit} className="space-y-4">
        <Field>
          <Label>Full Name *</Label>
          <Input
            value={form.name}
            onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
            required
          />
        </Field>
        <Field>
          <Label>Email *</Label>
          <Input
            type="email"
            value={form.email}
            onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
            required
          />
        </Field>
        <Field>
          <Label>Phone</Label>
          <Input
            value={form.phone}
            onChange={(e) => setForm((f) => ({ ...f, phone: e.target.value }))}
          />
        </Field>
        <Field className="mb-2">
          <Label>Notes</Label>
          <textarea
            value={form.notes}
            onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
            className="min-h-[70px] w-full rounded-sm border border-border p-3 text-sm focus:border-primary focus:outline-none"
          />
        </Field>
        {error && <p className="rounded-[8px] bg-danger-bg px-3 py-2 text-[12.5px] text-danger">{error}</p>}
        <div className="flex justify-end gap-2 pt-1">
          <Button type="button" variant="outline" onClick={onClose}>
            Cancel
          </Button>
          <Button type="submit" loading={isPending}>
            Save Changes
          </Button>
        </div>
      </form>
    </Modal>
  );
}

/* ───────────────────────── Import Contacts Modal ───────────────────────── */

function ImportContactsModal({
  open,
  lists,
  onClose,
  onImported,
}: {
  open: boolean;
  lists: ContactListRow[];
  onClose: () => void;
  onImported: () => void;
}) {
  const [raw, setRaw] = useState("");
  const [listId, setListId] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();

  function handleClose() {
    setRaw("");
    setListId("");
    setError(null);
    onClose();
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    startTransition(async () => {
      const result = await importContacts({ raw, listId: listId || null });
      if (result.success) {
        void swalAlert(
          "Import complete!",
          `${result.data?.imported ?? 0} new contact(s) added, ${result.data?.skipped ?? 0} already existed.`,
          "success"
        );
        setRaw("");
        setListId("");
        onImported();
      } else {
        setError(result.error ?? "Import failed");
      }
    });
  }

  return (
    <Modal
      open={open}
      onClose={handleClose}
      title="Import Contacts"
      description="Paste one contact per line: name, email, phone"
      maxWidthClassName="max-w-lg"
    >
      <form onSubmit={handleSubmit} className="space-y-4">
        <Field className="mb-2">
          <Label>Paste contacts *</Label>
          <textarea
            value={raw}
            onChange={(e) => setRaw(e.target.value)}
            className="min-h-[160px] w-full rounded-sm border border-border p-3 font-mono text-xs focus:border-primary focus:outline-none"
            placeholder={"Jane Doe, jane@company.com, +1 555 000 0000\nbob@company.com\nAlice Smith, alice@company.com"}
            required
          />
          <p className="mt-1 text-[11.5px] text-muted">
            Works with comma, tab, or semicolon separated values. Name and phone are optional.
          </p>
        </Field>

        {lists.length > 0 && (
          <Field>
            <Label>Add to list (optional)</Label>
            <Select value={listId} onChange={(e) => setListId(e.target.value)}>
              <option value="">Don&apos;t add to a list</option>
              {lists.map((l) => (
                <option key={l.id} value={l.id}>
                  {l.name}
                </option>
              ))}
            </Select>
          </Field>
        )}

        {error && <p className="rounded-[8px] bg-danger-bg px-3 py-2 text-[12.5px] text-danger">{error}</p>}

        <div className="flex justify-end gap-2 pt-1">
          <Button type="button" variant="outline" onClick={handleClose}>
            Cancel
          </Button>
          <Button type="submit" loading={isPending} disabled={!raw.trim()}>
            <Upload className="mr-1 h-3.5 w-3.5" />
            Import Contacts
          </Button>
        </div>
      </form>
    </Modal>
  );
}

/* ───────────────────────── Create List Modal ───────────────────────── */

function CreateListModal({
  open,
  onClose,
  onCreated,
}: {
  open: boolean;
  onClose: () => void;
  onCreated: () => void;
}) {
  const [form, setForm] = useState({ name: "", description: "" });
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();

  function handleClose() {
    setForm({ name: "", description: "" });
    setError(null);
    onClose();
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    startTransition(async () => {
      const result = await createContactList({
        name: form.name,
        description: form.description || null,
      });
      if (result.success) {
        setForm({ name: "", description: "" });
        onCreated();
      } else {
        setError(result.error ?? "Failed to create list");
      }
    });
  }

  return (
    <Modal open={open} onClose={handleClose} title="Create List" description="Group contacts for targeted invites.">
      <form onSubmit={handleSubmit} className="space-y-4">
        <Field>
          <Label>List Name *</Label>
          <Input
            value={form.name}
            onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
            placeholder="e.g. Newsletter Subscribers"
            required
          />
        </Field>
        <Field className="mb-2">
          <Label>Description</Label>
          <textarea
            value={form.description}
            onChange={(e) => setForm((f) => ({ ...f, description: e.target.value }))}
            className="min-h-[70px] w-full rounded-sm border border-border p-3 text-sm focus:border-primary focus:outline-none"
            placeholder="Optional description"
          />
        </Field>
        {error && <p className="rounded-[8px] bg-danger-bg px-3 py-2 text-[12.5px] text-danger">{error}</p>}
        <div className="flex justify-end gap-2 pt-1">
          <Button type="button" variant="outline" onClick={handleClose}>
            Cancel
          </Button>
          <Button type="submit" loading={isPending}>
            <FolderPlus className="mr-1 h-3.5 w-3.5" />
            Create List
          </Button>
        </div>
      </form>
    </Modal>
  );
}

/* ───────────────────────── Add To List Modal ───────────────────────── */

function AddToListModal({
  open,
  lists,
  selectedCount,
  onClose,
  onAdded,
  getSelectedIds,
}: {
  open: boolean;
  lists: ContactListRow[];
  selectedCount: number;
  onClose: () => void;
  onAdded: () => void;
  getSelectedIds: () => string[];
}) {
  const [listId, setListId] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!listId) {
      setError("Choose a list");
      return;
    }
    setError(null);
    startTransition(async () => {
      const result = await addContactsToList({ listId, contactIds: getSelectedIds() });
      if (result.success) {
        setListId("");
        onAdded();
      } else {
        setError(result.error ?? "Failed to add contacts");
      }
    });
  }

  return (
    <Modal
      open={open}
      onClose={onClose}
      title="Add to List"
      description={`Add ${selectedCount} selected contact(s) to a list.`}
    >
      {lists.length === 0 ? (
        <p className="text-[13px] text-muted">
          You don&apos;t have any lists yet. Create one first from the Lists tab.
        </p>
      ) : (
        <form onSubmit={handleSubmit} className="space-y-4">
          <Field className="mb-2">
            <Label>Choose list *</Label>
            <Select value={listId} onChange={(e) => setListId(e.target.value)} required>
              <option value="">Select a list…</option>
              {lists.map((l) => (
                <option key={l.id} value={l.id}>
                  {l.name} ({l.contactCount})
                </option>
              ))}
            </Select>
          </Field>
          {error && <p className="rounded-[8px] bg-danger-bg px-3 py-2 text-[12.5px] text-danger">{error}</p>}
          <div className="flex justify-end gap-2 pt-1">
            <Button type="button" variant="outline" onClick={onClose}>
              Cancel
            </Button>
            <Button type="submit" loading={isPending}>
              Add to List
            </Button>
          </div>
        </form>
      )}
    </Modal>
  );
}

/* ───────────────────────── View List Modal ───────────────────────── */

function ViewListModal({
  list,
  contacts,
  onClose,
  onChanged,
}: {
  list: ContactListRow | null;
  contacts: ContactRow[];
  onClose: () => void;
  onChanged: () => void;
}) {
  const [isPending, startTransition] = useTransition();

  function handleRemove(contactId: string) {
    if (!list) return;
    startTransition(async () => {
      const result = await removeContactFromList({ listId: list.id, contactId });
      if (result.success) onChanged();
      else void swalAlert("Failed", result.error, "error");
    });
  }

  return (
    <Modal
      open={!!list}
      onClose={onClose}
      title={list?.name ?? ""}
      description={`${contacts.length} contact${contacts.length !== 1 ? "s" : ""} in this list`}
      maxWidthClassName="max-w-lg"
    >
      {contacts.length === 0 ? (
        <div className="flex flex-col items-center justify-center py-8 text-center">
          <UserPlus className="mb-2 h-8 w-8 text-border" />
          <p className="text-[13px] text-muted">No contacts in this list yet.</p>
        </div>
      ) : (
        <div className="space-y-1.5">
          {contacts.map((c) => (
            <div
              key={c.id}
              className="flex items-center gap-3 rounded-[8px] border border-border px-3 py-2.5"
            >
              <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent/15 text-[11px] font-bold text-accent">
                {initialsOf(c.name)}
              </div>
              <div className="min-w-0 flex-1">
                <div className="truncate text-[13px] font-semibold text-navy">{c.name}</div>
                <div className="truncate text-[11.5px] text-muted">{c.email}</div>
              </div>
              <button
                type="button"
                disabled={isPending}
                onClick={() => handleRemove(c.id)}
                className="shrink-0 rounded-[6px] p-1.5 text-muted transition-colors hover:bg-danger-bg hover:text-danger disabled:opacity-50"
                title="Remove from list"
              >
                <X className="h-3.5 w-3.5" />
              </button>
            </div>
          ))}
        </div>
      )}
    </Modal>
  );
}

/* ───────────────────────── Send Invite Modal ───────────────────────── */

function SendInviteModal({
  list,
  surveys,
  onClose,
  onSent,
}: {
  list: ContactListRow | null;
  surveys: { id: string; title: string }[];
  onClose: () => void;
  onSent: () => void;
}) {
  const [surveyId, setSurveyId] = useState("");
  const [subject, setSubject] = useState("You're invited to share your feedback");
  const [body, setBody] = useState(
    "Hi,\n\nWe'd love your feedback. Please take a few minutes to complete our survey."
  );
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();

  function handleClose() {
    setSurveyId("");
    setError(null);
    onClose();
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!list) return;
    if (!surveyId) {
      setError("Choose a survey to send");
      return;
    }
    setError(null);
    startTransition(async () => {
      const result = await sendSurveyToList({ surveyId, listId: list.id, subject, body });
      if (result.success) {
        const sentCount = result.data?.sent ?? 0;
        const failedCount = result.data?.failed ?? 0;
        if (sentCount === 0 && failedCount > 0) {
          void swalAlert(
            "No emails were sent",
            "All send attempts failed — this usually means SMTP isn't configured yet. Ask a super admin to set it up in Admin \u2192 Settings, then try again.",
            "error"
          );
        } else {
          void swalAlert(
            "Invites sent!",
            `${sentCount} email(s) sent${failedCount ? `, ${failedCount} failed` : ""}.`,
            "success"
          );
        }
        onSent();
      } else {
        setError(result.error ?? "Failed to send invites");
      }
    });
  }

  return (
    <Modal
      open={!!list}
      onClose={handleClose}
      title="Send Survey Invite"
      description={list ? `Sending to everyone in "${list.name}" (${list.contactCount} contacts)` : ""}
      maxWidthClassName="max-w-lg"
    >
      {surveys.length === 0 ? (
        <p className="text-[13px] text-muted">
          You need at least one <strong>active</strong> (published) survey to send invites.
        </p>
      ) : (
        <form onSubmit={handleSubmit} className="space-y-4">
          <Field>
            <Label>Survey *</Label>
            <Select value={surveyId} onChange={(e) => setSurveyId(e.target.value)} required>
              <option value="">Choose a survey…</option>
              {surveys.map((s) => (
                <option key={s.id} value={s.id}>
                  {s.title}
                </option>
              ))}
            </Select>
          </Field>
          <Field>
            <Label>Subject</Label>
            <Input value={subject} onChange={(e) => setSubject(e.target.value)} required />
          </Field>
          <Field className="mb-2">
            <Label>Message</Label>
            <textarea
              value={body}
              onChange={(e) => setBody(e.target.value)}
              className="min-h-[100px] w-full rounded-sm border border-border p-3 text-sm focus:border-primary focus:outline-none"
              required
            />
          </Field>
          {error && <p className="rounded-[8px] bg-danger-bg px-3 py-2 text-[12.5px] text-danger">{error}</p>}
          <div className="flex justify-end gap-2 pt-1">
            <Button type="button" variant="outline" onClick={handleClose}>
              Cancel
            </Button>
            <Button type="submit" loading={isPending}>
              <Send className="mr-1 h-3.5 w-3.5" />
              Send Invites
            </Button>
          </div>
        </form>
      )}
    </Modal>
  );
}
