"use client";

import * as React from "react";
import { useMutation, useQuery } from "convex/react";
import { AnimatePresence, motion } from "motion/react";
import { toast } from "sonner";
import { CalendarCheck, Check, ExternalLink, Globe, Megaphone, MessageCircle, Phone, ShieldAlert, X, Zap } from "lucide-react";
import Link from "next/link";
import { changeReservationStatus } from "@/lib/actions/reservations";
import { fmtMoney } from "@/lib/format";
import { api } from "../../../convex/_generated/api";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Avatar } from "@/components/ui/primitives";
import { AnimatedNumber } from "@/components/motion/animated-number";
import { useChanged } from "@/components/motion/use-changed";
import { fmtPhone } from "@/lib/format";
import { fmtDate, parseDay, relativeTime } from "@/lib/dates";

export interface Lead {
  id: string;
  name: string;
  phone: string;
  email: string | null;
  apartment: { id: string; code: string; name: string } | null;
  checkIn: string | null;
  checkOut: string | null;
  guests: number;
  message: string | null;
  kind: string;
  status: string;
  utmSource: string | null;
  utmCampaign: string | null;
  utmMedium: string | null;
  page: string | null;
  createdAt: number;
  handledAt: number | null;
  handledBy: { fullName: string } | null;
  reservationId: string | null;
}
const KIND: Record<string, string> = { LEAD_FORM: "Booking request", WAITLIST: "Waitlist", CALLBACK: "Call-back", EXIT: "Call-back", BOOKING: "Online booking" };
interface WebBooking {
  id: string;
  code: string;
  checkIn: string;
  checkOut: string;
  nights: number;
  guests: number;
  totalAmount: number;
  createdAt: number;
  note: string | null;
  customer: { id: string; fullName: string; phone: string; riskLevel: string };
  apartment: { id: string; code: string; name: string };
}
const STATUS: Record<string, { label: string; cls: string }> = {
  NEW: { label: "New", cls: "bg-primary/10 text-primary" },
  CONTACTED: { label: "Contacted", cls: "bg-info-500/10 text-info-700 dark:text-info-400" },
  CONVERTED: { label: "Booked", cls: "bg-positive-500/12 text-positive-700 dark:text-positive-500" },
  LOST: { label: "Lost", cls: "bg-surface-3 text-fg-muted" },
};
const digitsOf = (s: string) => s.replace(/[^\d]/g, "");

/**
 * Website enquiries for the desk. Every visitor who left a number appears
 * here live, with the campaign that brought them; one tap to answer on
 * WhatsApp, call, or turn it into a booking.
 */
export function LeadsPanel({ businessName, onBook, full, currency = "MAD" }: { businessName: string; onBook?: (l: Lead) => void; full?: boolean; currency?: string }) {
  const web = useQuery(api.frontDesk.webBookings, {}) as WebBooking[] | undefined;
  const [confirming, setConfirming] = React.useState<string | null>(null);
  const confirm = async (b: WebBooking) => {
    setConfirming(b.id);
    const res = await changeReservationStatus(b.id, "CONFIRMED");
    setConfirming(null);
    if (!res.ok) return toast.error(res.error);
    toast.success(`${b.code} confirmed — tell ${b.customer.fullName.split(" ")[0]} on WhatsApp`);
    window.open(`https://wa.me/${digitsOf(b.customer.phone)}?text=${encodeURIComponent(`Hello ${b.customer.fullName.split(" ")[0]}, your booking ${b.code} at ${businessName} is confirmed ✅ ${b.apartment.name} · ${fmtDate(parseDay(b.checkIn), { style: "weekday" })} → ${fmtDate(parseDay(b.checkOut), { style: "weekday" })} · ${fmtMoney(b.totalAmount, currency, { whole: true })} payable at check-in. See you soon!`)}`, "_blank", "noopener");
  };
  const [status, setStatus] = React.useState<string>(full ? "ALL" : "NEW");
  const rows = useQuery(api.leads.list, status === "ALL" ? { limit: 200 } : { status, limit: full ? 200 : 12 }) as Lead[] | undefined;
  const counts = useQuery(api.leads.counts, {}) as { new: number; today: number } | undefined;
  const setLeadStatus = useMutation(api.leads.setStatus);
  const changed = useChanged(counts?.new ?? 0);
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => setMounted(true), []);
  const mark = async (l: Lead, s: string) => {
    try {
      await setLeadStatus({ id: l.id as never, status: s });
      if (s === "LOST" || s === "CONVERTED") toast.success(s === "LOST" ? "Marked as lost" : "Marked as booked");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Could not update");
    }
  };
  const waText = (l: Lead) => `Hello ${l.name.split(" ")[0]}, this is ${businessName}. Thank you for your request${l.apartment ? ` about ${l.apartment.name}` : ""}${l.checkIn && l.checkOut ? ` for ${fmtDate(parseDay(l.checkIn), { style: "short" })} → ${fmtDate(parseDay(l.checkOut), { style: "short" })}` : ""}. `;

  return (
    <section className={cn("rounded-2xl border border-border bg-surface shadow-xs hairline-top", changed && "animate-glow-flash")}>
      {web && web.length ? (
        <div className="border-b border-border bg-primary/5 px-4 pb-3 pt-4">
          <h2 className="flex items-center gap-2 text-base font-semibold">
            <span className="flex size-7 items-center justify-center rounded-lg bg-primary text-primary-fg"><Zap className="size-4" /></span> Online bookings to confirm
            <span key={web.length} className="rounded-full bg-primary px-2 py-0.5 text-2xs font-bold text-primary-fg animate-badge-pop">{web.length}</span>
          </h2>
          <ul className="mt-2 divide-y divide-border/70">
            <AnimatePresence initial={false}>
              {web.map((b) => (
                <motion.li key={b.id} layout initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, x: -12 }} className="flex flex-wrap items-center gap-3 py-2.5">
                  <span className="flex size-10 shrink-0 items-center justify-center rounded-lg bg-surface font-mono text-xs font-bold shadow-xs">{b.apartment.code}</span>
                  <span className="min-w-0 flex-1">
                    <span className="flex flex-wrap items-center gap-x-2 text-sm font-semibold">
                      {b.customer.fullName}
                      <span className="font-mono text-2xs font-normal text-fg-muted">{b.code}</span>
                      {b.customer.riskLevel !== "NORMAL" ? <span className="inline-flex items-center gap-1 rounded-full bg-warning-500/12 px-1.5 py-0.5 text-2xs font-semibold text-warning-700"><ShieldAlert className="size-3" /> {b.customer.riskLevel.toLowerCase().replace("_", " ")}</span> : null}
                    </span>
                    <span className="block text-xs text-fg-muted">{fmtDate(parseDay(b.checkIn), { style: "short" })} → {fmtDate(parseDay(b.checkOut), { style: "short" })} · {b.nights} night{b.nights > 1 ? "s" : ""} · {b.guests} guest{b.guests > 1 ? "s" : ""} · {fmtMoney(b.totalAmount, currency, { whole: true })}<span suppressHydrationWarning> · {mounted ? relativeTime(new Date(b.createdAt)) : ""}</span></span>
                    {b.note ? <span className="block text-xs italic text-fg-muted">“{b.note}”</span> : null}
                  </span>
                  <span className="flex items-center gap-1.5">
                    <Button size="xs" onClick={() => confirm(b)} loading={confirming === b.id}><Check /> Confirm</Button>
                    <Button size="xs" variant="secondary" asChild><a href={`https://wa.me/${digitsOf(b.customer.phone)}`} target="_blank" rel="noreferrer"><MessageCircle /></a></Button>
                    <Button size="xs" variant="ghost" asChild><Link href={`/reservations/${b.id}`}><ExternalLink /></Link></Button>
                  </span>
                </motion.li>
              ))}
            </AnimatePresence>
          </ul>
        </div>
      ) : null}
      <header className="flex flex-wrap items-center justify-between gap-2 px-4 pb-2 pt-4">
        <h2 className="flex items-center gap-2 text-base font-semibold">
          <span className="flex size-7 items-center justify-center rounded-lg bg-primary/10 text-primary"><Globe className="size-4" /></span> Website enquiries
          {counts?.new ? <span key={counts.new} className="rounded-full bg-primary px-2 py-0.5 text-2xs font-bold text-primary-fg animate-badge-pop"><AnimatedNumber value={counts.new} /> new</span> : null}
        </h2>
        <div className="flex items-center gap-1 rounded-lg bg-surface-2 p-0.5 text-xs">
          {(full ? ["ALL", "NEW", "CONTACTED", "CONVERTED", "LOST"] : ["NEW", "CONTACTED", "CONVERTED"]).map((s) => (
            <button key={s} type="button" onClick={() => setStatus(s)} className={cn("rounded-md px-2 py-1 font-medium transition", status === s ? "bg-surface text-fg shadow-xs" : "text-fg-muted hover:text-fg")}>
              {s === "ALL" ? "All" : STATUS[s].label}
            </button>
          ))}
        </div>
      </header>
      {rows === undefined ? (
        <div className="space-y-2 p-4">{[0, 1].map((i) => <div key={i} className="skeleton h-14" />)}</div>
      ) : rows.length === 0 ? (
        <p className="px-4 pb-4 text-sm text-fg-muted">{status === "NEW" ? "No new enquiries. Visitors who leave their number on the website appear here instantly." : "Nothing here."}</p>
      ) : (
        <ul className="divide-y divide-border">
          <AnimatePresence initial={false}>
            {rows.map((l) => {
              const st = STATUS[l.status] ?? STATUS.NEW;
              return (
                <motion.li key={l.id} layout initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, x: -12 }} className="px-4 py-3">
                  <div className="flex items-start gap-3">
                    <Avatar name={l.name} size="md" seed={l.phone} />
                    <div className="min-w-0 flex-1">
                      <p className="flex flex-wrap items-center gap-x-2 gap-y-0.5">
                        <span className="font-semibold">{l.name}</span>
                        <span className={cn("rounded-full px-1.5 py-0.5 text-2xs font-semibold", st.cls)}>{st.label}</span>
                        <span className="text-2xs text-fg-subtle">{KIND[l.kind] ?? l.kind}</span>
                        {l.utmSource ? <span className="inline-flex items-center gap-1 rounded-full bg-accent-100 px-1.5 py-0.5 text-2xs font-medium text-accent-700 dark:bg-accent-500/10"><Megaphone className="size-3" /> {l.utmSource}{l.utmCampaign ? ` · ${l.utmCampaign}` : ""}</span> : null}
                      </p>
                      <p className="text-xs text-fg-muted">
                        <a href={`tel:${l.phone}`} className="font-medium text-fg hover:text-primary">{fmtPhone(l.phone)}</a>
                        {l.apartment ? ` · ${l.apartment.code} ${l.apartment.name}` : ""}
                        {l.checkIn && l.checkOut ? ` · ${fmtDate(parseDay(l.checkIn), { style: "short" })} → ${fmtDate(parseDay(l.checkOut), { style: "short" })}` : ""}
                        {l.guests > 1 ? ` · ${l.guests} guests` : ""}
                        <span suppressHydrationWarning> · {mounted ? relativeTime(new Date(l.createdAt)) : ""}</span>
                      </p>
                      {l.message ? <p className="mt-1 rounded-lg bg-surface-2 px-2 py-1 text-xs italic text-fg-muted">“{l.message}”</p> : null}
                      {l.handledBy && l.status !== "NEW" ? <p className="mt-0.5 text-2xs text-fg-subtle">{st.label} by {l.handledBy.fullName}</p> : null}
                    </div>
                  </div>
                  {l.status === "NEW" || l.status === "CONTACTED" ? (
                    <div className="mt-2 flex flex-wrap gap-1.5 pl-12">
                      <Button size="xs" className="bg-[#25D366] text-white hover:bg-[#1fb857]" asChild onClick={() => l.status === "NEW" && mark(l, "CONTACTED")}>
                        <a href={`https://wa.me/${digitsOf(l.phone)}?text=${encodeURIComponent(waText(l))}`} target="_blank" rel="noreferrer"><MessageCircle /> WhatsApp</a>
                      </Button>
                      <Button size="xs" variant="secondary" asChild onClick={() => l.status === "NEW" && mark(l, "CONTACTED")}>
                        <a href={`tel:${l.phone}`}><Phone /> Call</a>
                      </Button>
                      {onBook ? (
                        <Button size="xs" variant="secondary" onClick={() => onBook(l)}>
                          <CalendarCheck /> Book
                        </Button>
                      ) : null}
                      <Button size="xs" variant="ghost" onClick={() => mark(l, "CONVERTED")} aria-label="Mark as booked"><Check /> Booked</Button>
                      <Button size="xs" variant="ghost" className="text-fg-muted" onClick={() => mark(l, "LOST")} aria-label="Mark as lost"><X /> Lost</Button>
                    </div>
                  ) : null}
                </motion.li>
              );
            })}
          </AnimatePresence>
        </ul>
      )}
    </section>
  );
}
