import { createFileRoute } from "@tanstack/react-router";
import { useEffect, useMemo, useRef, useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { supabase } from "@/integrations/supabase/client";
import { SupportAttachment } from "@/components/bkash/SupportAttachment";
import { Headphones, Send, Loader2, ArrowLeft, Paperclip, X } from "lucide-react";
import { toast } from "sonner";

export const Route = createFileRoute("/admin/support")({
  component: AdminSupportPage,
});

type Msg = {
  id: string;
  user_id: string;
  sender: "user" | "admin";
  body: string | null;
  attachment_url: string | null;
  attachment_type: string | null;
  attachment_name: string | null;
  created_at: string;
};

type Profile = { id: string; full_name: string; phone: string };

function AdminSupportPage() {
  const qc = useQueryClient();
  const [selected, setSelected] = useState<string | null>(null);

  const msgsQ = useQuery({
    queryKey: ["admin-support-all"],
    queryFn: async () => {
      const { data, error } = await supabase
        .from("support_messages")
        .select("id, user_id, sender, body, attachment_url, attachment_type, attachment_name, created_at")
        .order("created_at", { ascending: false })
        .limit(1000);
      if (error) throw new Error(error.message);
      return (data ?? []) as Msg[];
    },
  });

  const userIds = useMemo(() => {
    const set = new Set<string>();
    (msgsQ.data ?? []).forEach((m) => set.add(m.user_id));
    return Array.from(set);
  }, [msgsQ.data]);

  const profQ = useQuery({
    queryKey: ["admin-support-profiles", userIds.join(",")],
    enabled: userIds.length > 0,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("profiles")
        .select("id, full_name, phone")
        .in("id", userIds);
      if (error) throw new Error(error.message);
      return (data ?? []) as Profile[];
    },
  });

  useEffect(() => {
    const channel = supabase
      .channel("admin-support-feed")
      .on(
        "postgres_changes",
        { event: "INSERT", schema: "public", table: "support_messages" },
        () => qc.invalidateQueries({ queryKey: ["admin-support-all"] }),
      )
      .subscribe();
    return () => {
      supabase.removeChannel(channel);
    };
  }, [qc]);

  const threads = useMemo(() => {
    const map = new Map<string, Msg>();
    (msgsQ.data ?? []).forEach((m) => {
      if (!map.has(m.user_id)) map.set(m.user_id, m);
    });
    return Array.from(map.entries()).map(([uid, last]) => {
      const p = profQ.data?.find((x) => x.id === uid);
      return { uid, last, name: p?.full_name ?? "User", phone: p?.phone ?? "" };
    });
  }, [msgsQ.data, profQ.data]);

  if (selected) {
    const p = profQ.data?.find((x) => x.id === selected);
    return (
      <AdminThread
        userId={selected}
        name={p?.full_name ?? "User"}
        phone={p?.phone ?? ""}
        onBack={() => setSelected(null)}
      />
    );
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center gap-2">
        <Headphones className="h-5 w-5 text-primary" />
        <h1 className="text-lg font-bold">সাপোর্ট চ্যাট</h1>
      </div>
      {msgsQ.isLoading && (
        <div className="grid place-items-center py-10">
          <Loader2 className="h-5 w-5 animate-spin text-primary" />
        </div>
      )}
      {threads.length === 0 && !msgsQ.isLoading && (
        <div className="bg-card rounded-xl p-10 text-center text-sm text-muted-foreground">
          কোনো সাপোর্ট মেসেজ নেই
        </div>
      )}
      <div className="bg-card rounded-xl divide-y overflow-hidden">
        {threads.map((t) => (
          <button
            key={t.uid}
            onClick={() => setSelected(t.uid)}
            className="w-full p-3 flex items-center gap-3 text-left hover:bg-muted active:bg-muted"
          >
            <div className="h-10 w-10 rounded-full bg-primary/10 text-primary grid place-items-center font-bold">
              {(t.name ?? "U").charAt(0).toUpperCase()}
            </div>
            <div className="flex-1 min-w-0">
              <div className="flex items-center justify-between gap-2">
                <p className="text-sm font-semibold truncate">
                  {t.name}{" "}
                  <span className="font-normal text-muted-foreground tabular-nums">
                    {t.phone}
                  </span>
                </p>
                <span className="text-[10px] text-muted-foreground shrink-0">
                  {new Date(t.last.created_at).toLocaleString("en-GB", {
                    day: "2-digit",
                    month: "short",
                    hour: "2-digit",
                    minute: "2-digit",
                  })}
                </span>
              </div>
              <p className="text-xs text-muted-foreground truncate">
                {t.last.sender === "admin" ? "আপনি: " : ""}
                {t.last.body ?? (t.last.attachment_url ? "📎 অ্যাটাচমেন্ট" : "")}
              </p>
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

function AdminThread({
  userId,
  name,
  phone,
  onBack,
}: {
  userId: string;
  name: string;
  phone: string;
  onBack: () => void;
}) {
  const qc = useQueryClient();
  const [text, setText] = useState("");
  const [sending, setSending] = useState(false);
  const [file, setFile] = useState<File | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);
  const endRef = useRef<HTMLDivElement>(null);

  const q = useQuery({
    queryKey: ["admin-support-thread", userId],
    queryFn: async () => {
      const { data, error } = await supabase
        .from("support_messages")
        .select("id, user_id, sender, body, attachment_url, attachment_type, attachment_name, created_at")
        .eq("user_id", userId)
        .order("created_at", { ascending: true })
        .limit(500);
      if (error) throw new Error(error.message);
      return (data ?? []) as Msg[];
    },
  });

  useEffect(() => {
    const channel = supabase
      .channel(`admin-thread-${userId}`)
      .on(
        "postgres_changes",
        { event: "INSERT", schema: "public", table: "support_messages", filter: `user_id=eq.${userId}` },
        () => qc.invalidateQueries({ queryKey: ["admin-support-thread", userId] }),
      )
      .subscribe();
    return () => {
      supabase.removeChannel(channel);
    };
  }, [userId, qc]);

  useEffect(() => {
    endRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [q.data?.length]);

  async function send() {
    if (sending) return;
    const body = text.trim();
    if (!body && !file) return;
    setSending(true);
    try {
      let attachment_url: string | null = null;
      let attachment_type: string | null = null;
      let attachment_name: string | null = null;
      if (file) {
        if (file.size > 10 * 1024 * 1024) throw new Error("ফাইল ১০MB এর বেশি হতে পারবে না");
        const safe = file.name.replace(/[^a-zA-Z0-9._-]/g, "_");
        const path = `${userId}/${Date.now()}-${safe}`;
        const up = await supabase.storage.from("support-attachments").upload(path, file, {
          contentType: file.type || "application/octet-stream",
          upsert: false,
        });
        if (up.error) throw new Error(up.error.message);
        attachment_url = path;
        attachment_type = file.type || "application/octet-stream";
        attachment_name = file.name;
      }
      const { error } = await supabase.from("support_messages").insert({
        user_id: userId,
        sender: "admin",
        body: body || null,
        attachment_url,
        attachment_type,
        attachment_name,
      });
      if (error) throw new Error(error.message);
      setText("");
      setFile(null);
      if (fileRef.current) fileRef.current.value = "";
      qc.invalidateQueries({ queryKey: ["admin-support-thread", userId] });
    } catch (e: any) {
      toast.error(e.message ?? "পাঠানো যায়নি");
    } finally {
      setSending(false);
    }
  }

  const items = q.data ?? [];

  return (
    <div className="bg-card rounded-xl shadow flex flex-col h-[75vh] overflow-hidden">
      <div className="border-b p-3 flex items-center gap-2">
        <button onClick={onBack} className="h-9 w-9 grid place-items-center rounded-lg hover:bg-muted">
          <ArrowLeft className="h-4 w-4" />
        </button>
        <div className="h-9 w-9 rounded-full bg-primary/10 text-primary grid place-items-center font-bold">
          {name.charAt(0).toUpperCase()}
        </div>
        <div className="min-w-0">
          <p className="text-sm font-bold leading-tight truncate">{name}</p>
          <p className="text-[11px] text-muted-foreground tabular-nums">{phone}</p>
        </div>
      </div>
      <div className="flex-1 overflow-y-auto p-4 space-y-2">
        {items.map((m) => {
          const isAdmin = m.sender === "admin";
          return (
            <div key={m.id} className={`flex ${isAdmin ? "justify-end" : "justify-start"}`}>
              <div
                className={`max-w-[80%] px-3 py-2 rounded-2xl text-sm whitespace-pre-wrap break-words ${
                  isAdmin
                    ? "bg-primary text-primary-foreground rounded-br-sm"
                    : "bg-muted text-foreground rounded-bl-sm"
                }`}
              >
                {!isAdmin && <p className="text-[10px] font-bold opacity-70 mb-0.5">ইউজার</p>}
                {m.attachment_url && (
                  <div className="mb-1">
                    <SupportAttachment
                      path={m.attachment_url}
                      type={m.attachment_type}
                      name={m.attachment_name}
                    />
                  </div>
                )}
                {m.body && <p>{m.body}</p>}
                <p className={`text-[9px] mt-1 ${isAdmin ? "opacity-70" : "text-muted-foreground"}`}>
                  {new Date(m.created_at).toLocaleTimeString("en-GB", {
                    hour: "2-digit",
                    minute: "2-digit",
                  })}
                </p>
              </div>
            </div>
          );
        })}
        <div ref={endRef} />
      </div>
      {file && (
        <div className="px-3 py-2 border-t flex items-center gap-2 text-xs bg-muted/40">
          <Paperclip className="h-3 w-3" />
          <span className="flex-1 truncate">{file.name}</span>
          <button onClick={() => { setFile(null); if (fileRef.current) fileRef.current.value = ""; }} className="h-6 w-6 grid place-items-center rounded hover:bg-muted">
            <X className="h-3 w-3" />
          </button>
        </div>
      )}
      <div className="border-t p-2 flex items-center gap-2">
        <input
          ref={fileRef}
          type="file"
          accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.txt"
          className="hidden"
          onChange={(e) => setFile(e.target.files?.[0] ?? null)}
        />
        <button
          onClick={() => fileRef.current?.click()}
          className="h-11 w-11 rounded-full bg-muted grid place-items-center shrink-0"
          aria-label="Attach"
        >
          <Paperclip className="h-4 w-4" />
        </button>
        <input
          value={text}
          onChange={(e) => setText(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              send();
            }
          }}
          placeholder="রিপ্লাই লিখুন..."
          className="flex-1 h-11 px-4 rounded-full bg-muted text-sm outline-none focus:ring-2 focus:ring-primary min-w-0"
        />
        <button
          onClick={send}
          disabled={sending || (!text.trim() && !file)}
          className="h-11 w-11 rounded-full bg-primary text-primary-foreground grid place-items-center disabled:opacity-50 shrink-0"
          aria-label="Send"
        >
          {sending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
        </button>
      </div>
    </div>
  );
}
