"use client";

import clsx from "clsx";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { Suspense, useCallback, useEffect, useState } from "react";
import { MessagesSquare } from "lucide-react";
import { Button, EmptyState } from "@/components/ui/kit";
import { useSession } from "@/components/session";
import { ChatPanel } from "@/components/inbox/chat-panel";
import { ContactPanel } from "@/components/inbox/contact-panel";
import { ConversationList, type Tab } from "@/components/inbox/conversation-list";
import { useInboxStream, type InboxEvent } from "@/components/inbox/use-inbox-stream";
import { SendTemplateDialog } from "@/components/templates/send-template-dialog";
import { api, qs } from "@/lib/api";
import { useApi } from "@/lib/use-api";
import type { ChatMessage, ConversationDetail, ConversationEvent, ConversationSummary, TeamMember, WhatsAppAccount } from "@/lib/types";

export default function InboxPage() {
  return (
    <div className="full-bleed">
      <Suspense fallback={<div className="h-[calc(100dvh-4rem)] bg-paper" />}>
        <Inbox />
      </Suspense>
    </div>
  );
}

type MessagesResponse = { data: ChatMessage[]; events: ConversationEvent[]; meta: { has_more: boolean } };

function Inbox() {
  const router = useRouter();
  const params = useSearchParams();
  const { can } = useSession();
  const selectedId = Number(params.get("c")) || null;

  const [tab, setTab] = useState<Tab>("all");
  const [status, setStatus] = useState<"open" | "closed">("open");
  const [search, setSearch] = useState("");
  const [query, setQuery] = useState("");
  const [listV, setListV] = useState(0);
  const [convV, setConvV] = useState(0);
  const [msgV, setMsgV] = useState(0);
  const [details, setDetails] = useState(false);
  const [templateFor, setTemplateFor] = useState<ConversationDetail | null>(null);
  const [older, setOlder] = useState<{ convId: number; items: ChatMessage[]; hasMore: boolean } | null>(null);
  const [loadingOlder, setLoadingOlder] = useState(false);

  useEffect(() => {
    const t = setTimeout(() => setQuery(search.trim()), 300);
    return () => clearTimeout(t);
  }, [search]);

  const accounts = useApi<{ data: WhatsAppAccount[] }>("/whatsapp/accounts");
  const list = useApi<{ data: ConversationSummary[]; meta: { counts: Record<string, number> } }>(`/inbox/conversations${qs({ tab, status, q: query, v: listV })}`);
  const detail = useApi<{ data: ConversationDetail }>(selectedId ? `/inbox/conversations/${selectedId}?v=${convV}` : null);
  const msgs = useApi<MessagesResponse>(selectedId ? `/inbox/conversations/${selectedId}/messages?v=${msgV}` : null);
  const team = useApi<{ data: TeamMember[] }>(can("inbox.assign_any") ? "/team" : null);

  const conversation = detail.data?.data && detail.data.data.id === selectedId ? detail.data.data : null;
  const current = msgs.data && selectedId ? msgs.data : null;
  const olderItems = older && older.convId === selectedId ? older : null;
  const messages = current ? [...(olderItems?.items ?? []), ...current.data] : null;
  const hasMore = olderItems ? olderItems.hasMore : (current?.meta.has_more ?? false);

  const onEvent = useCallback(
    (e: InboxEvent) => {
      setListV((v) => v + 1);
      if (!e.conversation_id || e.conversation_id === selectedId) {
        setConvV((v) => v + 1);
        if (e.type !== "conversation.updated" || !e.conversation_id) setMsgV((v) => v + 1);
      }
    },
    [selectedId],
  );
  const live = useInboxStream(onEvent);

  // Opening a conversation (or receiving a message in it) marks it read.
  const unread = conversation?.unread_count ?? 0;
  useEffect(() => {
    if (!selectedId || unread === 0) return;
    api
      .post(`/inbox/conversations/${selectedId}/read`)
      .then(() => setListV((v) => v + 1))
      .catch(() => {});
  }, [selectedId, unread]);

  const select = (id: number | null) => {
    setDetails(false);
    router.replace(id ? `/inbox?c=${id}` : "/inbox", { scroll: false });
  };

  async function loadOlder() {
    if (!selectedId || !messages?.length) return;
    setLoadingOlder(true);
    try {
      const r = await api.get<MessagesResponse>(`/inbox/conversations/${selectedId}/messages?before=${messages[0].id}`);
      setOlder({ convId: selectedId, items: [...r.data, ...(olderItems?.items ?? [])], hasMore: r.meta.has_more });
    } finally {
      setLoadingOlder(false);
    }
  }

  const refreshConversation = () => {
    setConvV((v) => v + 1);
    setMsgV((v) => v + 1);
    setListV((v) => v + 1);
  };

  const noNumber = accounts.data && !accounts.data.data.some((a) => a.status !== "disconnected");
  if (noNumber) {
    return (
      <div className="mx-auto max-w-[1280px] px-4 py-8 sm:px-6 lg:px-8">
        <EmptyState
          icon={<MessagesSquare className="size-5" />}
          title="Connect WhatsApp to use the inbox"
          body="Once your number is connected, customer messages arrive here and your team can reply together."
          action={
            can("whatsapp.manage") && (
              <Link href="/settings/whatsapp">
                <Button variant="primary">Go to WhatsApp setup</Button>
              </Link>
            )
          }
        />
      </div>
    );
  }

  return (
    <div className="relative grid h-[calc(100dvh-4rem)] min-h-0 grid-cols-1 md:grid-cols-[320px_minmax(0,1fr)] xl:grid-cols-[340px_minmax(0,1fr)_320px]">
      <div className={clsx("min-h-0", selectedId ? "hidden md:block" : "block")}>
        <ConversationList
          items={list.data?.data ?? null}
          counts={list.data?.meta.counts ?? null}
          tab={tab}
          onTab={(t) => setTab(t)}
          status={status}
          onStatus={setStatus}
          search={search}
          onSearch={setSearch}
          selectedId={selectedId}
          onSelect={(id) => select(id)}
        />
      </div>
      <div className={clsx("min-h-0", selectedId ? "flex" : "hidden md:flex")}>
        <ChatPanel
          key={selectedId ?? "none"}
          conversation={conversation}
          messages={conversation ? messages : null}
          events={conversation ? (current?.events ?? []) : []}
          hasMore={hasMore}
          loadingOlder={loadingOlder}
          onLoadOlder={loadOlder}
          team={team.data?.data ?? []}
          onBack={() => select(null)}
          onSent={() => {
            setMsgV((v) => v + 1);
            setListV((v) => v + 1);
          }}
          onChanged={refreshConversation}
          onSendTemplate={() => conversation && setTemplateFor(conversation)}
          onToggleDetails={() => setDetails((d) => !d)}
        />
      </div>
      {conversation && (
        <div className={clsx("min-h-0", details ? "absolute inset-y-0 right-0 z-30 w-full max-w-[340px] shadow-2xl xl:static xl:shadow-none" : "hidden xl:block")}>
          <ContactPanel key={conversation.id} conversation={conversation} onClose={() => setDetails(false)} onChanged={refreshConversation} />
        </div>
      )}
      <span className="sr-only" aria-live="polite">
        {live ? "Live updates on" : ""}
      </span>
      {templateFor && (
        <SendTemplateDialog
          contactId={templateFor.contact.id}
          contactName={templateFor.contact.name}
          conversationId={templateFor.id}
          onClose={() => setTemplateFor(null)}
          onSent={() => {
            setTemplateFor(null);
            refreshConversation();
          }}
        />
      )}
    </div>
  );
}
