"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { MessagesSquare } from "lucide-react";
import { useRepositories } from "@/di/repository-provider";
import { useAuth } from "@/presentation/hooks/use-auth";
import { useDebounce } from "@/presentation/hooks/use-debounce";
import { useSupportActivity } from "@/presentation/hooks/use-support-activity";
import { supportRealtime } from "@/infrastructure/realtime/support-realtime";
import { useT } from "@/shared/i18n/client";
import { cn } from "@/shared/lib/utils";
import { ClientPanel } from "./client-panel";
import { ConversationList } from "./conversation-list";
import { ConversationThread } from "./conversation-thread";
import type { SupportInboxCounts, SupportInboxView, Ticket, TicketDetail } from "@/domain/entities/ticket";

const PER_PAGE = 25;
const VIEWS: SupportInboxView[] = ["mine", "unassigned", "open", "resolved"];
const PANEL_KEY = "support.panelOpen";

export function SupportInbox() {
  const t = useT();
  const router = useRouter();
  const pathname = usePathname();
  const params = useSearchParams();
  const container = useRepositories();
  const { user } = useAuth();

  const selectedId = Number(params.get("c")) || null;
  const view = (VIEWS.includes(params.get("view") as SupportInboxView) ? params.get("view") : "mine") as SupportInboxView;

  const [search, setSearch] = useState("");
  const debouncedSearch = useDebounce(search.trim(), 300);
  const [conversations, setConversations] = useState<Ticket[]>([]);
  const [page, setPage] = useState(1);
  const [lastPage, setLastPage] = useState(1);
  const [loading, setLoading] = useState(true);
  const [counts, setCounts] = useState<SupportInboxCounts | null>(null);
  const [detail, setDetail] = useState<TicketDetail | null>(null);
  const [activityToken, setActivityToken] = useState(0);
  const [live, setLive] = useState(false);
  const [panelOpen, setPanelOpen] = useState(true);
  const requestId = useRef(0);

  useEffect(() => {
    try {
      setPanelOpen(localStorage.getItem(PANEL_KEY) !== "false");
    } catch {
      // Private mode: keep the default.
    }
  }, []);

  const setQuery = useCallback(
    (changes: Record<string, string | null>) => {
      const next = new URLSearchParams(params.toString());
      Object.entries(changes).forEach(([key, value]) => (value === null ? next.delete(key) : next.set(key, value)));
      router.replace(`${pathname}?${next.toString()}`, { scroll: false });
    },
    [params, pathname, router],
  );

  const loadCounts = useCallback(async () => {
    try {
      setCounts(await container.ticketRepository.getInboxCounts());
    } catch {
      // Counts are decorative.
    }
  }, [container]);

  // Always reloads from page 1 and keeps as many rows as were already shown, so a
  // live refresh never collapses a list the agent scrolled through.
  const loadConversations = useCallback(
    async (targetPage = 1, { silent = false }: { silent?: boolean } = {}) => {
      const id = ++requestId.current;
      if (!silent) setLoading(true);
      try {
        const result = await container.ticketRepository.findAll({
          view,
          search: debouncedSearch || undefined,
          order_by: "last_activity",
          order: "DESC",
          page: targetPage,
          per_page: PER_PAGE,
        });
        if (id !== requestId.current) return;
        setConversations((prev) =>
          targetPage === 1 ? result.items : [...prev, ...result.items.filter((c) => !prev.some((p) => p.id === c.id))],
        );
        setPage(result.current_page);
        setLastPage(result.last_page);
      } catch {
        // Keep the current list; the next refresh retries.
      } finally {
        if (id === requestId.current) setLoading(false);
      }
    },
    [container, view, debouncedSearch],
  );

  useEffect(() => {
    setConversations([]);
    void loadConversations(1);
  }, [loadConversations]);

  useEffect(() => { void loadCounts(); }, [loadCounts]);

  const refreshSoon = useRef<number | null>(null);
  const refreshAll = useCallback(() => {
    if (refreshSoon.current) window.clearTimeout(refreshSoon.current);
    // Coalesce bursts (a message triggers read + list + counts updates).
    refreshSoon.current = window.setTimeout(() => {
      void loadConversations(1, { silent: true });
      void loadCounts();
    }, 250);
  }, [loadConversations, loadCounts]);

  useSupportActivity(() => {
    setLive(supportRealtime.isConnected);
    refreshAll();
    setActivityToken((n) => n + 1);
  });

  useEffect(() => {
    const unread = counts?.unread ?? 0;
    const base = `${t.support.title} · Dadycar Admin`;
    document.title = unread > 0 ? `(${unread}) ${base}` : base;
  }, [counts?.unread, t.support.title]);

  const selectedSummary = useMemo(
    () => conversations.find((c) => c.id === selectedId) ?? null,
    [conversations, selectedId],
  );

  const select = (id: number) => {
    // Optimistically clear the unread badge of the opened conversation.
    setConversations((prev) => prev.map((c) => (c.id === id ? { ...c, unread_count: 0 } : c)));
    setQuery({ c: String(id) });
  };

  const togglePanel = () => {
    setPanelOpen((open) => {
      try {
        localStorage.setItem(PANEL_KEY, String(!open));
      } catch {
        // Not persisted.
      }
      return !open;
    });
  };

  return (
    <div className="flex h-full min-h-0 overflow-hidden">
      <div className={cn("h-full w-full shrink-0 lg:w-[360px]", selectedId && "hidden lg:block")}>
        <ConversationList
          view={view}
          onViewChange={(next) => setQuery({ view: next })}
          counts={counts}
          search={search}
          onSearchChange={setSearch}
          conversations={conversations}
          loading={loading}
          hasMore={page < lastPage}
          onLoadMore={() => void loadConversations(page + 1, { silent: true })}
          selectedId={selectedId}
          onSelect={(conversation) => select(conversation.id)}
          currentUserId={user?.id}
          live={live}
        />
      </div>

      <div className={cn("h-full min-w-0 flex-1", !selectedId && "hidden lg:block")}>
        {selectedId ? (
          <ConversationThread
            key={selectedId}
            conversationId={selectedId}
            summary={selectedSummary}
            panelOpen={panelOpen}
            onTogglePanel={togglePanel}
            onClose={() => setQuery({ c: null })}
            onChanged={(fresh) => {
              if (fresh) setCounts(fresh);
              refreshAll();
              setActivityToken((n) => n + 1);
            }}
            onDetailLoaded={setDetail}
          />
        ) : (
          <div className="flex h-full flex-col items-center justify-center gap-3 bg-background px-8 text-center">
            <div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-primary/15 to-primary/5 text-primary">
              <MessagesSquare className="h-7 w-7" />
            </div>
            <div>
              <p className="text-base font-semibold text-foreground">{t.support.selectTitle}</p>
              <p className="mt-1 text-sm text-muted-foreground">{t.support.selectDescription}</p>
            </div>
          </div>
        )}
      </div>

      {selectedId && panelOpen && detail?.id === selectedId && (
        <div className="hidden h-full w-[320px] shrink-0 xl:block">
          <ClientPanel
            detail={detail}
            activityToken={activityToken}
            onOpenConversation={select}
            onUpdated={() => {
              refreshAll();
              setActivityToken((n) => n + 1);
              void container.ticketRepository.findById(selectedId).then(setDetail).catch(() => {});
            }}
          />
        </div>
      )}
    </div>
  );
}
