"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { Alert } from "@/components/ui/Alert";
import { PageContentSkeleton } from "@/components/ui/Skeleton";
import { SocialChatList, type SocialChatItem } from "@/components/social/SocialChatList";
import { SocialEmptyPane } from "@/components/social/SocialEmptyPane";
import { SocialMessageSearch, type SearchHit } from "@/components/social/SocialMessageSearch";
import { SocialNavRail } from "@/components/social/SocialNavRail";
import { SocialShell } from "@/components/social/SocialShell";
import { SocialSpacePane, type SpaceDetails } from "@/components/social/SocialSpacePane";
import type { SocialPost } from "@/components/social/SocialMessageBubble";
import type { SocialSendPayload } from "@/components/social/social-types";
import { ApiError, apiDelete, apiGet, apiPatch, apiPost, apiPostFormData } from "@/lib/api";

function isBroadcastChatId(id: number) {
  return id < 0;
}

function broadcastSpaceIdFromChat(id: number, chat?: SocialChatItem | null) {
  if (chat?.broadcast_space_id) return chat.broadcast_space_id;
  if (id < 0) return Math.abs(id);
  return null;
}

export function SocialApp({ spaceId }: { spaceId?: number | null }) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const scheduleId = searchParams.get("schedule_id") ? Number(searchParams.get("schedule_id")) : null;

  const [chats, setChats] = useState<SocialChatItem[]>([]);
  const [filter, setFilter] = useState<"all" | "channel" | "group">("all");
  const [space, setSpace] = useState<SpaceDetails | null>(null);
  const [posts, setPosts] = useState<SocialPost[]>([]);
  const [pinned, setPinned] = useState<SocialPost | null>(null);
  const [loading, setLoading] = useState(true);
  const [feedLoading, setFeedLoading] = useState(false);
  const [sending, setSending] = useState(false);
  const [votingPollId, setVotingPollId] = useState<number | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [messageSearchOpen, setMessageSearchOpen] = useState(false);
  const [messageSearchQ, setMessageSearchQ] = useState("");
  const [messageSearchResults, setMessageSearchResults] = useState<SearchHit[]>([]);
  const [messageSearchLoading, setMessageSearchLoading] = useState(false);
  /** active = current space only; all = every visible chat */
  const [messageSearchScope, setMessageSearchScope] = useState<"active" | "all">("all");
  const searchSeq = useRef(0);
  const [rollCall, setRollCall] = useState<{
    id: number;
    closes_at?: string;
    is_open?: boolean;
    responses_count?: number;
  } | null>(null);

  const loadChats = useCallback(async () => {
    try {
      const data = await apiGet<{ chats: SocialChatItem[] }>("/social/chats");
      setChats(data.chats ?? []);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری گفتگوها");
    } finally {
      setLoading(false);
    }
  }, []);

  const loadSpace = useCallback(
    async (id: number) => {
      setFeedLoading(true);
      setError(null);
      try {
        if (isBroadcastChatId(id)) {
          const broadcastId = Math.abs(id);
          const feed = await apiGet<{
            space: SpaceDetails;
            posts: SocialPost[];
            pinned?: SocialPost | null;
          }>(`/social/broadcast-spaces/${broadcastId}/feed`);
          setSpace({
            ...feed.space,
            id,
            broadcast_space_id: feed.space.broadcast_space_id ?? broadcastId,
            linked_space_id: null,
          });
          setPosts(feed.posts ?? []);
          setPinned(feed.pinned ?? null);
          setRollCall(null);
          return;
        }

        const detail = await apiGet<{ space: SpaceDetails }>(`/social/spaces/${id}`);
        setSpace(detail.space);
        const feed = await apiGet<{ posts: SocialPost[]; pinned?: SocialPost | null }>(
          `/social/spaces/${id}/feed`,
        );
        setPosts(feed.posts ?? []);
        setPinned(feed.pinned ?? null);
        await apiPost(`/social/spaces/${id}/read`, {});

        if (scheduleId && detail.space.can_roll_call) {
          const rolls = await apiGet<{
            roll_calls: Array<{
              id: number;
              closes_at?: string;
              is_open?: boolean;
              responses_count?: number;
            }>;
          }>(`/social/schedules/${scheduleId}/roll-calls`);
          setRollCall(rolls.roll_calls?.find((r) => r.is_open) ?? rolls.roll_calls?.[0] ?? null);
        } else {
          setRollCall(null);
        }
      } catch (err) {
        setError(err instanceof ApiError ? err.message : "خطا");
      } finally {
        setFeedLoading(false);
      }
    },
    [scheduleId],
  );

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

  useEffect(() => {
    if (spaceId) void loadSpace(spaceId);
    else {
      setSpace(null);
      setPosts([]);
    }
  }, [spaceId, loadSpace]);

  const selectChat = (chat: SocialChatItem) => {
    const qs = scheduleId ? `?schedule_id=${scheduleId}` : "";
    router.push(`/social/${chat.id}${qs}`);
  };

  const switchPair = () => {
    if (!space?.linked_space_id) return;
    const qs = scheduleId ? `?schedule_id=${scheduleId}` : "";
    router.push(`/social/${space.linked_space_id}${qs}`);
  };

  const runMessageSearch = useCallback(
    async (raw: string, scope: "active" | "all" = messageSearchScope) => {
      const q = raw.trim();
      const seq = ++searchSeq.current;
      if (!q) {
        setMessageSearchResults([]);
        setMessageSearchLoading(false);
        return;
      }

      setMessageSearchLoading(true);
      setMessageSearchQ(q);
      try {
        const targets =
          scope === "active" && spaceId
            ? chats.filter((c) => c.id === spaceId)
            : chats;
        const searchTargets = (targets.length ? targets : chats).filter(
          (chat) => !isBroadcastChatId(chat.id) && chat.kind !== "system_announcement",
        );
        const chatMap = new Map(chats.map((c) => [c.id, c]));

        const batches = await Promise.all(
          searchTargets.map(async (chat) => {
            try {
              const data = await apiGet<{ posts: SocialPost[] }>(
                `/social/spaces/${chat.id}/search?q=${encodeURIComponent(q)}`,
              );
              return (data.posts ?? []).map(
                (p): SearchHit => ({
                  ...p,
                  space_id: (p as SearchHit).space_id ?? chat.id,
                  space_title: chatMap.get(chat.id)?.title ?? chat.title,
                }),
              );
            } catch {
              return [] as SearchHit[];
            }
          }),
        );

        if (seq !== searchSeq.current) return;
        setMessageSearchResults(
          batches.flat().sort((a, b) => {
            const ta = a.created_at ? new Date(a.created_at).getTime() : 0;
            const tb = b.created_at ? new Date(b.created_at).getTime() : 0;
            return tb - ta;
          }),
        );
      } catch (err) {
        if (seq !== searchSeq.current) return;
        setError(err instanceof ApiError ? err.message : "خطا در جستجو");
        setMessageSearchResults([]);
      } finally {
        if (seq === searchSeq.current) setMessageSearchLoading(false);
      }
    },
    [chats, messageSearchScope, spaceId],
  );

  const openMessageSearch = useCallback(
    (initial = "", scope: "active" | "all" = "all") => {
      setMessageSearchScope(scope);
      setMessageSearchOpen(true);
      setMessageSearchQ(initial);
      setMessageSearchResults([]);
      if (initial.trim()) void runMessageSearch(initial, scope);
    },
    [runMessageSearch],
  );

  const closeMessageSearch = () => {
    searchSeq.current += 1;
    setMessageSearchOpen(false);
    setMessageSearchQ("");
    setMessageSearchResults([]);
    setMessageSearchLoading(false);
  };

  const selectSearchHit = (hit: SearchHit) => {
    const id = hit.space_id;
    closeMessageSearch();
    if (!id) return;
    const qs = scheduleId ? `?schedule_id=${scheduleId}` : "";
    router.push(`/social/${id}${qs}`);
  };

  const send = async (payload: SocialSendPayload) => {
    if (!space) return;
    setSending(true);
    try {
      const broadcastId = broadcastSpaceIdFromChat(space.id, {
        id: space.id,
        pair_id: space.pair_id,
        type: space.type,
        broadcast_space_id: space.broadcast_space_id,
        title: space.title,
        unread_count: 0,
      });

      if (broadcastId) {
        if (!payload.body?.trim()) {
          setError("برای کانال اعلان فقط متن پشتیبانی می‌شود.");
          return;
        }
        await apiPost(`/social/broadcast-spaces/${broadcastId}/posts`, {
          body: payload.body.trim(),
        });
      } else if (payload.pollQuestion && payload.pollOptions?.length) {
        await apiPost(`/social/spaces/${space.id}/posts`, {
          body: payload.body || payload.pollQuestion,
          post_type: "poll",
          poll_question: payload.pollQuestion,
          poll_options: payload.pollOptions,
          reply_to_post_id: payload.replyToId ?? undefined,
        });
      } else if (payload.file) {
        const form = new FormData();
        form.append("body", payload.body || payload.file.name);
        if (payload.replyToId) form.append("reply_to_post_id", String(payload.replyToId));
        if (payload.postType) form.append("post_type", payload.postType);
        if (payload.durationSeconds) form.append("duration_seconds", String(payload.durationSeconds));
        form.append("file", payload.file);
        await apiPostFormData(`/social/spaces/${space.id}/posts`, form);
      } else if (payload.body?.trim()) {
        await apiPost(`/social/spaces/${space.id}/posts`, {
          body: payload.body.trim(),
          reply_to_post_id: payload.replyToId ?? undefined,
        });
      }
      await loadSpace(space.id);
      await loadChats();
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ارسال");
    } finally {
      setSending(false);
    }
  };

  const toggleActive = async () => {
    if (!space) return;
    try {
      const next = !(space.is_active !== false);
      const broadcastId = space.broadcast_space_id ?? (space.id < 0 ? Math.abs(space.id) : null);
      if (broadcastId) {
        await apiPatch(`/social/broadcast-spaces/${broadcastId}`, { is_active: next });
      } else {
        await apiPatch(`/social/spaces/${space.id}`, { is_active: next });
      }
      await loadSpace(space.id);
      await loadChats();
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در تغییر وضعیت");
    }
  };

  const votePoll = async (postId: number, optionId: number) => {
    if (!space) return;
    setVotingPollId(postId);
    try {
      await apiPost(`/social/posts/${postId}/poll/vote`, { option_id: optionId });
      await loadSpace(space.id);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ثبت رأی");
    } finally {
      setVotingPollId(null);
    }
  };

  const openRollCall = async () => {
    if (!scheduleId || !space) return;
    try {
      const res = await apiPost<{
        roll_call: { id: number; closes_at?: string; is_open?: boolean; responses_count?: number };
      }>(`/social/schedules/${scheduleId}/roll-calls`, {});
      setRollCall(res.roll_call);
      await loadSpace(space.id);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در roll call");
    }
  };

  const spacePane =
    space && !feedLoading ? (
      <SocialSpacePane
        space={space}
        posts={posts}
        pinned={pinned}
        onSwitchPair={switchPair}
        onReply={() => undefined}
        onSend={send}
        onVotePoll={votePoll}
        votingPollId={votingPollId}
        onPin={async (p) => {
          await apiPost(`/social/posts/${p.id}/pin`, {});
          await loadSpace(space.id);
        }}
        onUnpin={async (p) => {
          await apiDelete(`/social/posts/${p.id}/pin`);
          await loadSpace(space.id);
        }}
        onDelete={async (p) => {
          await apiDelete(`/social/posts/${p.id}`);
          await loadSpace(space.id);
        }}
        onTagSearch={(raw) => openMessageSearch(raw, "active")}
        onOpenMessageSearch={() => openMessageSearch("", "active")}
        onOpenRollCall={openRollCall}
        onBack={() => router.push("/social")}
        onToggleActive={toggleActive}
        scheduleId={scheduleId}
        rollCall={rollCall}
        sending={sending}
      />
    ) : null;

  return (
    <SocialShell hideTopHeader={Boolean(spaceId)}>
      {loading ? (
        <div className="flex flex-1 p-6">
          <PageContentSkeleton rows={6} />
        </div>
      ) : (
        <div className="flex min-h-0 flex-1 flex-col lg:flex-row">
          {messageSearchOpen ? (
            <SocialMessageSearch
              initialQuery={messageSearchQ}
              loading={messageSearchLoading}
              results={messageSearchResults}
              onSearch={(q) => void runMessageSearch(q)}
              onClose={closeMessageSearch}
              onSelect={selectSearchHit}
              className="flex flex-1"
            />
          ) : (
            <SocialChatList
              chats={chats}
              activeId={spaceId}
              onSelect={selectChat}
              onOpenSearch={() => openMessageSearch("", "all")}
              filter={filter}
              onFilterChange={setFilter}
              className={spaceId ? "hidden lg:flex" : "flex flex-1"}
            />
          )}

          {error ? (
            <div className="absolute left-3 right-3 top-3 z-20 lg:left-4 lg:right-auto lg:top-20 lg:max-w-sm">
              <Alert tone="error">{error}</Alert>
            </div>
          ) : null}

          {messageSearchOpen ? (
            <div className="hidden min-h-0 flex-1 lg:flex">
              {spaceId && spacePane ? spacePane : <SocialEmptyPane />}
            </div>
          ) : !spaceId ? (
            <div className="hidden min-h-0 flex-1 lg:flex">
              <SocialEmptyPane />
            </div>
          ) : feedLoading || !space ? (
            <div className="flex min-h-0 flex-1 p-6">
              <PageContentSkeleton rows={5} />
            </div>
          ) : (
            spacePane
          )}

          <SocialNavRail mode="desktop" active="chats" />
          <SocialNavRail mode="mobile" active="chats" hideMobile={Boolean(spaceId) || messageSearchOpen} />
        </div>
      )}

    </SocialShell>
  );
}
