import { useEffect, useMemo, useRef } from "react";
import { useSearchParams } from "react-router-dom";
import { useI18n } from "../../i18n";
import type { PostScope } from "../../types/post";
import { FilterChips } from "./FilterChips";
import { MessageBubble } from "./MessageBubble";
import { useGroupedByDay } from "./hooks/useGroupedByDay";
import { usePostStream } from "./hooks/usePostStream";

export type MessageStreamProps = {
  scope: PostScope;
};

export function MessageStream({ scope }: MessageStreamProps) {
  const { t, lang } = useI18n();
  const [sp, setSp] = useSearchParams();

  const type = sp.get("type") || "all";

  const params = useMemo(() => ({ scope, type, lang }), [scope, type, lang]);

  const { items, isLoading, error, hasMore, loadMore, reset } =
    usePostStream(params);
  const groups = useGroupedByDay(items, lang);
  const retryLabel = lang === "zh-CN" ? "重试" : "Retry";

  const sentinelRef = useRef<HTMLDivElement>(null);
  const hasMoreRef = useRef(hasMore);
  const isLoadingRef = useRef(isLoading);
  useEffect(() => {
    hasMoreRef.current = hasMore;
  }, [hasMore]);
  useEffect(() => {
    isLoadingRef.current = isLoading;
  }, [isLoading]);

  useEffect(() => {
    const el = sentinelRef.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (
            entry.isIntersecting &&
            hasMoreRef.current &&
            !isLoadingRef.current
          ) {
            loadMore();
          }
        }
      },
      { rootMargin: "200px" },
    );
    io.observe(el);
    return () => io.disconnect();
  }, [loadMore]);

  const updateParam = (key: string, value: string) => {
    const n = new URLSearchParams(sp);
    if (!value || value === "all") n.delete(key);
    else n.set(key, value);
    setSp(n, { replace: true });
  };

  return (
    <div className="mx-auto max-w-full px-3 md:max-w-[820px] lg:max-w-[1080px] xl:max-w-[1180px]">
      <FilterChips type={type} onTypeChange={(v) => updateParam("type", v)} />

      <div className="flex flex-col gap-2 pb-10 pt-2">
        {groups.map((group) => (
          <div key={group.dayKey} className="flex flex-col gap-2">
            {group.items.map((post) => (
              <MessageBubble key={post.id} post={post} />
            ))}
          </div>
        ))}

        {!isLoading && !error && items.length === 0 ? (
          <p className="py-10 text-center text-sm text-neutral-400">
            {t("noResults")}
          </p>
        ) : null}

        {error ? (
          <div className="my-4 flex items-center justify-between gap-3 rounded-xl border border-red-900 bg-red-950/40 px-4 py-3 text-sm text-red-200">
            <span className="break-all">{error}</span>
            <button
              type="button"
              onClick={() => reset()}
              className="shrink-0 rounded-full border border-red-700 px-3 py-1 text-xs text-red-100 hover:border-red-500"
            >
              {retryLabel}
            </button>
          </div>
        ) : null}

        {isLoading ? (
          <div className="py-4 text-center text-xs text-neutral-500">…</div>
        ) : null}

        <div ref={sentinelRef} aria-hidden className="h-1" />
      </div>
    </div>
  );
}
