"use client";
/* eslint-disable @next/next/no-img-element -- served through /api/media */

import * as React from "react";
import { useMutation } from "convex/react";
import { motion } from "motion/react";
import { toast } from "sonner";
import { Check, Copy, Images, Link2, Mail, MessageCircle, MessageSquare, Send, Share2 } from "lucide-react";
import { api } from "../../../convex/_generated/api";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input, Textarea } from "@/components/ui/input";
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
import { fmtMoney } from "@/lib/format";
import { fmtDate, parseDay } from "@/lib/dates";

export interface ShareTarget {
  apartment: { id: string; code: string; name: string; imageIds: string[]; maxGuests: number; bedrooms: number; bathrooms: number; basePrice: number; city?: string; building?: string | null };
  checkIn: string;
  checkOut: string;
  nights: number;
  subtotal: number | null;
  guests: number;
  /** guest already in the conversation, if any */
  to?: { name: string; phone: string } | null;
}
export interface ShareBusiness {
  name: string;
  phone: string;
  email: string;
  checkInTime: string;
  checkOutTime: string;
}

const media = (id: string, w: number) => `/api/media/${id}?w=${w}`;
const digitsOf = (s: string) => s.replace(/[^\d]/g, "");

/** Public link that opens this apartment in the showroom with the dates preselected. */
export function shareLink(t: ShareTarget) {
  const origin = typeof window === "undefined" ? "" : window.location.origin;
  const p = new URLSearchParams();
  if (t.nights > 0) {
    p.set("in", t.checkIn);
    p.set("out", t.checkOut);
  }
  if (t.guests > 1) p.set("g", String(t.guests));
  const qs = p.toString();
  return `${origin}/a/${t.apartment.id}${qs ? `?${qs}` : ""}`;
}

/**
 * Share an apartment with a prospective guest in two taps: photos, price for
 * their dates and the public link go out over WhatsApp, SMS, email or the
 * phone's own share sheet — with the photos attached where the browser
 * allows it. Every share is logged for the manager.
 */
export function ShareSheet({ target: t, business, currency, onClose }: { target: ShareTarget | null; business: ShareBusiness | null | undefined; currency: string; onClose: () => void }) {
  const logShare = useMutation(api.frontDesk.logShare);
  const [to, setTo] = React.useState("");
  const [msg, setMsg] = React.useState("");
  const [picked, setPicked] = React.useState<string[]>([]);
  const [copied, setCopied] = React.useState<"link" | "msg" | null>(null);
  const [sending, setSending] = React.useState(false);
  const [canFiles, setCanFiles] = React.useState(false);
  const link = t ? shareLink(t) : "";

  React.useEffect(() => {
    if (!t) return;
    setTo(t.to?.phone ?? "");
    setPicked(t.apartment.imageIds.slice(0, 4));
    setCopied(null);
    const a = t.apartment;
    const lines = [
      `${t.to?.name ? `Hello ${t.to.name.split(" ")[0]}, here` : "Here"} is ${a.name} (${a.code})${a.city ? ` in ${a.city}` : ""}:`,
      `• ${a.bedrooms ? `${a.bedrooms} bedroom${a.bedrooms > 1 ? "s" : ""}` : "Studio"} · ${a.bathrooms} bath · up to ${a.maxGuests} guests`,
      t.nights > 0 && t.subtotal != null ? `• ${fmtDate(parseDay(t.checkIn), { style: "weekday" })} → ${fmtDate(parseDay(t.checkOut), { style: "weekday" })} · ${t.nights} night${t.nights > 1 ? "s" : ""} · ${fmtMoney(t.subtotal, currency, { whole: true })} total` : `• From ${fmtMoney(a.basePrice, currency, { whole: true })} per night`,
      `• Photos & live availability: ${shareLink(t)}`,
      business ? `${business.name}${business.phone ? ` · ${business.phone}` : ""} · check-in from ${business.checkInTime}` : "",
    ].filter(Boolean);
    setMsg(lines.join("\n"));
    try {
      setCanFiles(typeof navigator !== "undefined" && !!navigator.canShare && navigator.canShare({ files: [new File([""], "x.jpg", { type: "image/jpeg" })] }));
    } catch {
      setCanFiles(false);
    }
  }, [t, business, currency]);

  const log = (channel: string) => {
    if (!t) return;
    void logShare({ apartmentId: t.apartment.id as never, channel, checkIn: t.nights > 0 ? t.checkIn : undefined, checkOut: t.nights > 0 ? t.checkOut : undefined, to: digitsOf(to) || undefined, photos: picked.length }).catch(() => {});
  };
  const copy = async (what: "link" | "msg") => {
    try {
      await navigator.clipboard.writeText(what === "link" ? link : msg);
      setCopied(what);
      toast.success(what === "link" ? "Link copied" : "Message copied");
      log(what === "link" ? "COPY_LINK" : "COPY_MESSAGE");
      setTimeout(() => setCopied(null), 1600);
    } catch {
      toast.error("Could not copy — long-press the text to copy it.");
    }
  };
  const waHref = `https://wa.me/${digitsOf(to)}?text=${encodeURIComponent(msg)}`;
  const smsHref = `sms:${digitsOf(to) ? (/iPhone|iPad|Macintosh/.test(navigator.userAgent) ? `${to}&body=` : `${to}?body=`) : "?body="}${encodeURIComponent(msg)}`;
  const mailHref = `mailto:?subject=${encodeURIComponent(t ? `${t.apartment.name} · ${t.apartment.code}` : "Apartment")}&body=${encodeURIComponent(msg)}`;

  async function nativeShare() {
    if (!t) return;
    setSending(true);
    try {
      let files: File[] = [];
      if (canFiles && picked.length) {
        files = (await Promise.all(picked.map(async (id, i) => {
          const r = await fetch(media(id, 1280));
          const b = await r.blob();
          return new File([b], `${t.apartment.code}-${i + 1}.jpg`, { type: b.type || "image/jpeg" });
        }))).filter(Boolean);
      }
      const data: ShareData = { title: `${t.apartment.name} · ${t.apartment.code}`, text: msg };
      if (files.length && navigator.canShare?.({ files })) data.files = files;
      else data.url = link;
      await navigator.share(data);
      log(files.length ? "NATIVE_PHOTOS" : "NATIVE");
    } catch (e) {
      if (!(e instanceof DOMException && e.name === "AbortError")) toast.error("Sharing is not available here — use WhatsApp or copy the message.");
    } finally {
      setSending(false);
    }
  }
  const toggle = (id: string) => setPicked((p) => (p.includes(id) ? p.filter((x) => x !== id) : p.length >= 6 ? p : [...p, id]));

  return (
    <Dialog open={!!t} onOpenChange={(o) => !o && onClose()}>
      <DialogContent size="md" className="overflow-hidden p-0">
        {t ? (
          <>
            <DialogTitle className="sr-only">Share {t.apartment.name}</DialogTitle>
            <div className="border-b border-border bg-surface-2/60 p-4 pr-12">
              <p className="eyebrow flex items-center gap-1.5"><Share2 className="size-3" /> Share with the client</p>
              <p className="font-display text-xl font-medium leading-tight">{t.apartment.name} <span className="font-mono text-sm text-fg-muted">{t.apartment.code}</span></p>
              <p className="text-xs text-fg-muted">{t.nights > 0 ? `${fmtDate(parseDay(t.checkIn), { style: "weekday" })} → ${fmtDate(parseDay(t.checkOut), { style: "weekday" })} · ${t.nights} night${t.nights > 1 ? "s" : ""}${t.subtotal != null ? ` · ${fmtMoney(t.subtotal, currency, { whole: true })}` : ""}` : `From ${fmtMoney(t.apartment.basePrice, currency, { whole: true })}/night`}</p>
            </div>
            <div className="max-h-[70dvh] space-y-4 overflow-y-auto p-4 scrollbar-thin sm:p-5">
              {/* Photos */}
              {t.apartment.imageIds.length ? (
                <div>
                  <div className="mb-1.5 flex items-center justify-between">
                    <p className="flex items-center gap-1.5 text-xs font-medium text-fg-muted"><Images className="size-3.5" /> Photos to send</p>
                    <span className="text-2xs text-fg-subtle">{picked.length} selected{canFiles ? "" : " · link only on this device"}</span>
                  </div>
                  <div className="flex gap-2 overflow-x-auto pb-1 scrollbar-none">
                    {t.apartment.imageIds.map((id, i) => {
                      const on = picked.includes(id);
                      return (
                        <motion.button key={id} type="button" onClick={() => toggle(id)} initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: i * 0.03 }} className={cn("relative h-20 w-28 shrink-0 overflow-hidden rounded-lg ring-2 transition-all active:scale-95", on ? "ring-primary" : "ring-transparent opacity-70 hover:opacity-100")} aria-pressed={on} aria-label={`Photo ${i + 1}`}>
                          <img src={media(id, 320)} alt="" className="size-full object-cover" loading="lazy" />
                          <span className={cn("absolute right-1 top-1 flex size-5 items-center justify-center rounded-full text-white transition", on ? "bg-primary" : "bg-stone-950/40")}>{on ? <Check className="size-3" /> : <span className="text-[10px] font-bold">{i + 1}</span>}</span>
                        </motion.button>
                      );
                    })}
                  </div>
                </div>
              ) : null}

              {/* To */}
              <div>
                <p className="mb-1.5 text-xs font-medium text-fg-muted">Client phone <span className="text-fg-subtle">(optional · opens their WhatsApp chat)</span></p>
                <Input value={to} onChange={(e) => setTo(e.target.value)} inputMode="tel" placeholder="+212 6 XX XX XX XX" className="h-11 rounded-xl" />
              </div>

              {/* Message */}
              <div>
                <div className="mb-1.5 flex items-center justify-between">
                  <p className="text-xs font-medium text-fg-muted">Message</p>
                  <button type="button" onClick={() => copy("msg")} className="flex items-center gap-1 text-2xs font-medium text-primary hover:underline">{copied === "msg" ? <Check className="size-3" /> : <Copy className="size-3" />} {copied === "msg" ? "Copied" : "Copy text"}</button>
                </div>
                <Textarea value={msg} onChange={(e) => setMsg(e.target.value)} rows={6} className="rounded-xl text-sm leading-relaxed" />
              </div>

              {/* Link */}
              <button type="button" onClick={() => copy("link")} className="flex w-full items-center gap-2 rounded-xl border border-border bg-surface-2 px-3 py-2 text-left text-xs transition hover:border-border-strong active:scale-[0.99]">
                <Link2 className="size-4 shrink-0 text-fg-muted" />
                <span className="min-w-0 flex-1 truncate font-mono text-fg-muted">{link.replace(/^https?:\/\//, "")}</span>
                <span className={cn("shrink-0 font-semibold", copied === "link" ? "text-positive-600" : "text-primary")}>{copied === "link" ? "Copied" : "Copy link"}</span>
              </button>

              {/* Actions */}
              <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
                <Button size="lg" className="col-span-2 bg-[#25D366] text-white hover:bg-[#1fb857] sm:col-span-2" asChild onClick={() => log("WHATSAPP")}>
                  <a href={waHref} target="_blank" rel="noreferrer">
                    <MessageCircle /> WhatsApp{digitsOf(to) ? "" : " · pick contact"}
                  </a>
                </Button>
                <Button size="lg" variant="secondary" onClick={nativeShare} loading={sending} disabled={typeof navigator === "undefined" || !("share" in navigator)}>
                  <Send /> {canFiles ? "Photos" : "Share…"}
                </Button>
                <Button size="lg" variant="secondary" asChild onClick={() => log("SMS")}>
                  <a href={smsHref}>
                    <MessageSquare /> SMS
                  </a>
                </Button>
                <Button size="lg" variant="ghost" className="col-span-2 sm:col-span-4" asChild onClick={() => log("EMAIL")}>
                  <a href={mailHref}>
                    <Mail /> Send by email
                  </a>
                </Button>
              </div>
              <p className="text-center text-2xs text-fg-subtle">The link shows the photos, the price and live free dates. No guest data leaves the system.</p>
            </div>
          </>
        ) : null}
      </DialogContent>
    </Dialog>
  );
}
