"use client";

import { useEffect, useRef, useState } from "react";
import { Archive, ArchiveRestore, Pencil, Trash2, X } from "lucide-react";
import { Badge, Button, Skeleton } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { useSession } from "@/components/session";
import { api } from "@/lib/api";
import { useApi } from "@/lib/use-api";
import { flag, formatDate, formatDateTime, formatPhone, initials } from "@/lib/format";
import type { Activity, Contact, CustomField } from "@/lib/types";
import { ConsentBadge } from "./consent-badge";

export function ContactDrawer({
  contactId,
  customFields,
  onClose,
  onEdit,
  onDelete,
  onChanged,
}: {
  contactId: number | null;
  customFields: CustomField[];
  onClose: () => void;
  onEdit: (c: Contact) => void;
  onDelete: (c: Contact) => void;
  onChanged: () => void;
}) {
  const { can } = useSession();
  const toast = useToast();
  const [busy, setBusy] = useState<string | null>(null);
  const panelRef = useRef<HTMLDivElement>(null);
  // Mounted with key={contactId}, so these start empty for each contact.
  const contactReq = useApi<{ data: Contact }>(contactId ? `/contacts/${contactId}` : null);
  const activityReq = useApi<{ data: Activity[] }>(contactId ? `/contacts/${contactId}/activities` : null);
  const contact = contactReq.data?.data ?? null;
  const activity = activityReq.data?.data ?? null;

  useEffect(() => {
    if (contactReq.error) {
      toast("error", contactReq.error);
      onClose();
    }
  }, [contactReq.error, toast, onClose]);

  useEffect(() => {
    panelRef.current?.focus();
    const onKey = (e: KeyboardEvent) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  if (!contactId) return null;

  async function act(name: string, path: string, body?: Record<string, unknown>, message?: string) {
    setBusy(name);
    try {
      await api.post(path, body);
      contactReq.reload();
      activityReq.reload();
      onChanged();
      if (message) toast("success", message);
    } catch (e) {
      toast("error", (e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  return (
    <div className="fixed inset-0 z-40">
      <div className="absolute inset-0 bg-ink/30" onClick={onClose} />
      <div
        ref={panelRef}
        tabIndex={-1}
        role="dialog"
        aria-modal="true"
        aria-label="Contact details"
        className="drawer-in absolute inset-y-0 right-0 flex w-full max-w-[440px] flex-col bg-white shadow-2xl focus:outline-none"
      >
        <header className="flex items-start gap-3 border-b border-line px-6 py-5">
          {contact ? (
            <>
              <span className="grid size-11 shrink-0 place-items-center rounded-full bg-teal-soft font-semibold text-teal">{initials(contact.full_name)}</span>
              <div className="min-w-0 flex-1">
                <h2 className="truncate text-lg font-semibold">{contact.full_name}</h2>
                <p className="tabular text-sm text-muted">{formatPhone(contact.phone)}</p>
              </div>
            </>
          ) : (
            <div className="flex-1 space-y-2">
              <Skeleton className="h-5 w-40" />
              <Skeleton className="h-4 w-28" />
            </div>
          )}
          <button onClick={onClose} aria-label="Close details" className="rounded p-1 text-muted hover:bg-paper hover:text-text">
            <X className="size-5" />
          </button>
        </header>

        {contact && (
          <div className="flex flex-wrap gap-2 border-b border-line px-6 py-3">
            {can("contacts.manage") && (
              <Button size="sm" icon={<Pencil className="size-3.5" />} onClick={() => onEdit(contact)}>
                Edit
              </Button>
            )}
            {can("contacts.manage") &&
              (contact.archived_at ? (
                <Button size="sm" icon={<ArchiveRestore className="size-3.5" />} loading={busy === "restore"} onClick={() => act("restore", `/contacts/${contact.id}/restore`, undefined, "Contact restored")}>
                  Restore
                </Button>
              ) : (
                <Button size="sm" icon={<Archive className="size-3.5" />} loading={busy === "archive"} onClick={() => act("archive", `/contacts/${contact.id}/archive`, undefined, "Contact archived")}>
                  Archive
                </Button>
              ))}
            {can("contacts.delete") && (
              <Button size="sm" variant="ghost" className="text-brick hover:bg-brick-soft hover:text-brick" icon={<Trash2 className="size-3.5" />} onClick={() => onDelete(contact)}>
                Delete
              </Button>
            )}
          </div>
        )}

        <div className="flex-1 overflow-y-auto px-6 py-5">
          {!contact ? (
            <div className="space-y-3">
              {Array.from({ length: 6 }).map((_, i) => (
                <Skeleton key={i} className="h-4 w-full" />
              ))}
            </div>
          ) : (
            <div className="space-y-7">
              {contact.archived_at && <p className="rounded-md bg-amber-soft px-3 py-2 text-sm text-amber">Archived on {formatDate(contact.archived_at)}. Archived contacts are hidden from lists and campaigns.</p>}

              <dl className="grid grid-cols-[120px_1fr] gap-x-4 gap-y-2.5 text-sm">
                <dt className="text-muted">Email</dt>
                <dd className="break-all">{contact.email ?? "—"}</dd>
                <dt className="text-muted">Country</dt>
                <dd>{contact.country ? `${flag(contact.country)} ${contact.country_name}` : "—"}</dd>
                <dt className="text-muted">Language</dt>
                <dd>{contact.language_code ?? "—"}</dd>
                <dt className="text-muted">Added</dt>
                <dd>{formatDateTime(contact.created_at)}</dd>
              </dl>

              <section>
                <h3 className="mb-2 text-sm font-semibold">Marketing consent</h3>
                <div className="flex flex-wrap items-center gap-3">
                  <ConsentBadge status={contact.opt_in_status} />
                  <span className="text-xs text-muted">
                    {contact.opt_in_status === "opted_out" && `since ${formatDate(contact.opted_out_at)}`}
                    {contact.opt_in_status === "opted_in" && `since ${formatDate(contact.opted_in_at)}`}
                    {contact.consent_source && `, via ${contact.consent_source}`}
                  </span>
                </div>
                {can("contacts.manage") && (
                  <div className="mt-3">
                    {contact.opt_in_status === "opted_out" ? (
                      <Button size="sm" loading={busy === "consent"} onClick={() => act("consent", `/contacts/${contact.id}/consent`, { status: "opted_in" }, "Marked as opted in")}>
                        Mark as opted in
                      </Button>
                    ) : (
                      <Button size="sm" loading={busy === "consent"} onClick={() => act("consent", `/contacts/${contact.id}/consent`, { status: "opted_out" }, "Opted out of marketing")}>
                        Opt out of marketing
                      </Button>
                    )}
                  </div>
                )}
              </section>

              <section>
                <h3 className="mb-2 text-sm font-semibold">Groups and tags</h3>
                {contact.groups.length + contact.tags.length === 0 ? (
                  <p className="text-sm text-muted">Not in any group yet.</p>
                ) : (
                  <div className="flex flex-wrap gap-1.5">
                    {contact.groups.map((g) => (
                      <Badge key={`g${g.id}`} tone="teal">
                        {g.name}
                      </Badge>
                    ))}
                    {contact.tags.map((t) => (
                      <Badge key={`t${t.id}`}>#{t.name}</Badge>
                    ))}
                  </div>
                )}
              </section>

              {customFields.length > 0 && (
                <section>
                  <h3 className="mb-2 text-sm font-semibold">Other information</h3>
                  <dl className="grid grid-cols-[120px_1fr] gap-x-4 gap-y-2.5 text-sm">
                    {customFields.map((f) => (
                      <div key={f.id} className="contents">
                        <dt className="text-muted">{f.label}</dt>
                        <dd className="break-words">{contact.custom_fields[f.key] ?? "—"}</dd>
                      </div>
                    ))}
                  </dl>
                </section>
              )}

              <section>
                <h3 className="mb-3 text-sm font-semibold">Activity</h3>
                {!activity ? (
                  <Skeleton className="h-16 w-full" />
                ) : (
                  <ol className="relative space-y-4 border-l border-line pl-4">
                    {activity.map((a) => (
                      <li key={a.id} className="text-sm">
                        <span className="absolute -left-[4.5px] mt-1.5 size-2 rounded-full bg-teal" />
                        <p>{a.description}</p>
                        <p className="text-xs text-muted">
                          {formatDateTime(a.created_at)}
                          {a.user_name && ` by ${a.user_name}`}
                        </p>
                      </li>
                    ))}
                  </ol>
                )}
              </section>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
