import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { archiveChat, clearChat, createPrivateChat, deleteChat, getChats, joinChat, unarchiveChat } from "../api/chats";
import { globalSearch } from "../api/search";
import type { DiscoverChat, Message, UserSearchItem } from "../chat/types";
import { updateMyProfile } from "../api/users";
import { useAuthStore } from "../store/authStore";
import { useChatStore } from "../store/chatStore";
import { NewChatPanel } from "./NewChatPanel";

export function ChatList() {
  const chats = useChatStore((s) => s.chats);
  const messagesByChat = useChatStore((s) => s.messagesByChat);
  const activeChatId = useChatStore((s) => s.activeChatId);
  const setActiveChatId = useChatStore((s) => s.setActiveChatId);
  const setFocusedMessage = useChatStore((s) => s.setFocusedMessage);
  const loadChats = useChatStore((s) => s.loadChats);
  const me = useAuthStore((s) => s.me);
  const [search, setSearch] = useState("");
  const [userResults, setUserResults] = useState<UserSearchItem[]>([]);
  const [discoverResults, setDiscoverResults] = useState<DiscoverChat[]>([]);
  const [messageResults, setMessageResults] = useState<Message[]>([]);
  const [archivedChats, setArchivedChats] = useState<typeof chats>([]);
  const [searchLoading, setSearchLoading] = useState(false);
  const [tab, setTab] = useState<"all" | "people" | "groups" | "channels" | "archived">("all");
  const [ctxChatId, setCtxChatId] = useState<number | null>(null);
  const [ctxPos, setCtxPos] = useState<{ x: number; y: number } | null>(null);
  const [deleteModalChatId, setDeleteModalChatId] = useState<number | null>(null);
  const [deleteForAll, setDeleteForAll] = useState(false);
  const [profileOpen, setProfileOpen] = useState(false);
  const [profileName, setProfileName] = useState("");
  const [profileUsername, setProfileUsername] = useState("");
  const [profileBio, setProfileBio] = useState("");
  const [profileAvatarUrl, setProfileAvatarUrl] = useState("");
  const [profileAllowPrivateMessages, setProfileAllowPrivateMessages] = useState(true);
  const [profileError, setProfileError] = useState<string | null>(null);
  const [profileSaving, setProfileSaving] = useState(false);
  const deleteModalChat = chats.find((chat) => chat.id === deleteModalChatId) ?? null;
  const canDeleteForEveryone = Boolean(
    deleteModalChat &&
    !deleteModalChat.is_saved &&
    (deleteModalChat.type === "group" || deleteModalChat.type === "private")
  );

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

  useEffect(() => {
    if (tab !== "archived") {
      return;
    }
    let cancelled = false;
    void (async () => {
      try {
        const rows = await getChats(undefined, true);
        if (!cancelled) {
          setArchivedChats(rows);
        }
      } catch {
        if (!cancelled) {
          setArchivedChats([]);
        }
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [tab]);

  useEffect(() => {
    const term = search.trim();
    if (term.replace("@", "").length < 2) {
      setUserResults([]);
      setDiscoverResults([]);
      setMessageResults([]);
      setSearchLoading(false);
      return;
    }
    let cancelled = false;
    setSearchLoading(true);
    void (async () => {
      try {
        const result = await globalSearch(term);
        if (cancelled) {
          return;
        }
        setUserResults(result.users);
        setDiscoverResults(result.chats);
        setMessageResults(result.messages);
      } catch {
        if (!cancelled) {
          setUserResults([]);
          setDiscoverResults([]);
          setMessageResults([]);
        }
      } finally {
        if (!cancelled) {
          setSearchLoading(false);
        }
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [search]);

  useEffect(() => {
    const onKeyDown = (event: KeyboardEvent) => {
      if (event.key !== "Escape") {
        return;
      }
      setCtxChatId(null);
      setCtxPos(null);
      setDeleteModalChatId(null);
      setProfileOpen(false);
    };
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, []);

  useEffect(() => {
    if (!me) {
      return;
    }
    setProfileName(me.name || "");
    setProfileUsername(me.username || "");
    setProfileBio(me.bio || "");
    setProfileAvatarUrl(me.avatar_url || "");
    setProfileAllowPrivateMessages(me.allow_private_messages ?? true);
  }, [me]);

  const filteredChats = chats.filter((chat) => {
    if (chat.archived) {
      return false;
    }
    if (tab === "people") {
      return chat.type === "private";
    }
    if (tab === "groups") {
      return chat.type === "group";
    }
    if (tab === "channels") {
      return chat.type === "channel";
    }
    return true;
  });

  const tabs: Array<{ id: "all" | "people" | "groups" | "channels" | "archived"; label: string }> = [
    { id: "all", label: "All" },
    { id: "people", label: "Люди" },
    { id: "groups", label: "Groups" },
    { id: "channels", label: "Каналы" },
    { id: "archived", label: "Архив" }
  ];

  const visibleChats = tab === "archived" ? archivedChats : filteredChats;

  return (
    <aside className="relative flex h-full w-full max-w-xs flex-col bg-slate-900/60" onClick={() => { setCtxChatId(null); setCtxPos(null); }}>
      <div className="border-b border-slate-700/50 px-3 py-3">
        <div className="mb-2 flex items-center gap-2">
          <button className="rounded-lg bg-slate-700/70 px-2 py-2 text-xs">☰</button>
          <label className="block flex-1">
            <input
              className="w-full rounded-full border border-slate-700/80 bg-slate-800/80 px-3 py-2 text-sm outline-none placeholder:text-slate-400 focus:border-sky-500"
              placeholder="Search"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
            />
          </label>
          <button className="flex h-8 w-8 items-center justify-center rounded-full bg-sky-500/30 text-xs font-semibold uppercase text-sky-100" onClick={() => setProfileOpen(true)}>
            {(me?.name || me?.username || "u").slice(0, 1)}
          </button>
        </div>
        <div className="flex items-center gap-3 overflow-x-auto pt-1 text-sm">
          {tabs.map((item) => (
            <button
              className={`whitespace-nowrap pb-1.5 ${tab === item.id ? "border-b-2 border-sky-400 font-semibold text-sky-300" : "text-slate-300/80"}`}
              key={item.id}
              onClick={() => setTab(item.id)}
            >
              {item.label}
            </button>
          ))}
        </div>
        {search.trim().replace("@", "").length >= 2 ? (
          <div className="mt-3 rounded-xl border border-slate-700/70 bg-slate-900/70 p-2">
            {searchLoading ? <p className="px-2 py-1 text-xs text-slate-400">Searching...</p> : null}
            {!searchLoading && userResults.length === 0 && discoverResults.length === 0 && messageResults.length === 0 ? (
              <p className="px-2 py-1 text-xs text-slate-400">Nothing found</p>
            ) : null}
            {userResults.length > 0 ? (
              <div className="mb-1">
                <p className="px-2 py-1 text-[10px] uppercase tracking-wide text-slate-400">People</p>
                {userResults.slice(0, 5).map((user) => (
                  <button
                    className="block w-full rounded-lg px-2 py-1.5 text-left hover:bg-slate-800"
                    key={`user-${user.id}`}
                    onClick={async () => {
                      const chat = await createPrivateChat(user.id);
                      const updatedChats = await getChats();
                      useChatStore.setState({ chats: updatedChats, activeChatId: chat.id });
                      setSearch("");
                      setUserResults([]);
                      setDiscoverResults([]);
                      setMessageResults([]);
                    }}
                  >
                    <p className="truncate text-xs font-semibold">{user.name}</p>
                    <p className="truncate text-[11px] text-slate-400">@{user.username}</p>
                  </button>
                ))}
              </div>
            ) : null}
            {discoverResults.length > 0 ? (
              <div>
                <p className="px-2 py-1 text-[10px] uppercase tracking-wide text-slate-400">Groups and Channels</p>
                {discoverResults.slice(0, 5).map((chat) => (
                  <button
                    className="flex w-full items-center justify-between rounded-lg px-2 py-1.5 text-left hover:bg-slate-800"
                    key={`discover-${chat.id}`}
                    onClick={async () => {
                      if (!chat.is_member) {
                        await joinChat(chat.id);
                      }
                      const updatedChats = await getChats();
                      useChatStore.setState({ chats: updatedChats, activeChatId: chat.id });
                      setSearch("");
                      setUserResults([]);
                      setDiscoverResults([]);
                      setMessageResults([]);
                    }}
                  >
                    <div className="min-w-0">
                      <p className="truncate text-xs font-semibold">{chat.display_title || chat.title || (chat.type === "group" ? "Group" : "Channel")}</p>
                      <p className="truncate text-[11px] text-slate-400">{chat.handle ? `@${chat.handle}` : chat.type}</p>
                    </div>
                    <span className="ml-2 shrink-0 text-[10px] text-slate-400">{chat.is_member ? "open" : "join"}</span>
                  </button>
                ))}
              </div>
            ) : null}
            {messageResults.length > 0 ? (
              <div>
                <p className="px-2 py-1 text-[10px] uppercase tracking-wide text-slate-400">Messages</p>
                {messageResults.slice(0, 5).map((message) => (
                  <button
                    className="block w-full rounded-lg px-2 py-1.5 text-left hover:bg-slate-800"
                    key={`message-${message.id}`}
                    onClick={async () => {
                      setActiveChatId(message.chat_id);
                      setFocusedMessage(message.chat_id, message.id);
                      setSearch("");
                      setUserResults([]);
                      setDiscoverResults([]);
                      setMessageResults([]);
                    }}
                  >
                    <p className="truncate text-[11px] text-slate-400">chat #{message.chat_id}</p>
                    <p className="truncate text-xs font-semibold">{message.text || "[media]"}</p>
                  </button>
                ))}
              </div>
            ) : null}
          </div>
        ) : null}
      </div>
      <div className="tg-scrollbar flex-1 overflow-auto">
        {visibleChats.map((chat) => (
          <button
            className={`block w-full border-b border-slate-800/60 px-4 py-3 text-left transition ${
              activeChatId === chat.id ? "bg-sky-500/20" : "hover:bg-slate-800/65"
            }`}
            key={chat.id}
            onClick={() => setActiveChatId(chat.id)}
            onContextMenu={(e) => {
              e.preventDefault();
              const safePos = getSafeContextPosition(e.clientX, e.clientY, 176, 56);
              setCtxChatId(chat.id);
              setCtxPos(safePos);
            }}
          >
            <div className="flex items-start gap-3">
              <div className="mt-0.5 flex h-10 w-10 items-center justify-center rounded-full bg-sky-500/30 text-sm font-semibold uppercase text-sky-100">
                {(chat.display_title || chat.title || chat.type).slice(0, 1)}
              </div>
              <div className="min-w-0 flex-1">
                <div className="flex items-center justify-between gap-2">
                  <p className="truncate text-sm font-semibold">{chatLabel(chat)}</p>
                  {(chat.unread_count ?? 0) > 0 ? (
                    <span className="inline-flex min-w-5 items-center justify-center rounded-full bg-sky-500 px-1.5 py-0.5 text-[10px] font-semibold text-slate-950">
                      {chat.unread_count}
                    </span>
                  ) : (
                    <span className="shrink-0 text-[11px] text-slate-400">
                      {messagesByChat[chat.id]?.length ? "now" : ""}
                    </span>
                  )}
                </div>
                <p className="truncate text-xs text-slate-400">{chatMetaLabel(chat)}</p>
              </div>
            </div>
          </button>
        ))}
      </div>
      <NewChatPanel />

      {ctxChatId && ctxPos
        ? createPortal(
          <div className="fixed z-[100] w-44 rounded-lg border border-slate-700/80 bg-slate-900/95 p-1 shadow-2xl" style={{ left: ctxPos.x, top: ctxPos.y }} onClick={(e) => e.stopPropagation()}>
            <button
              className="block w-full rounded px-2 py-1.5 text-left text-sm text-red-300 hover:bg-slate-800"
              onClick={() => {
                setDeleteModalChatId(ctxChatId);
                setCtxChatId(null);
                setCtxPos(null);
                setDeleteForAll(false);
              }}
            >
              {chats.find((c) => c.id === ctxChatId)?.is_saved ? "Clear chat" : "Delete chat"}
            </button>
            <button
              className="block w-full rounded px-2 py-1.5 text-left text-sm hover:bg-slate-800"
              onClick={async () => {
                const target = chats.find((c) => c.id === ctxChatId) ?? archivedChats.find((c) => c.id === ctxChatId);
                if (!target) {
                  return;
                }
                if (target.archived) {
                  await unarchiveChat(target.id);
                } else {
                  await archiveChat(target.id);
                }
                await loadChats();
                const nextArchived = await getChats(undefined, true);
                setArchivedChats(nextArchived);
                setCtxChatId(null);
                setCtxPos(null);
              }}
            >
              {(chats.find((c) => c.id === ctxChatId) ?? archivedChats.find((c) => c.id === ctxChatId))?.archived ? "Unarchive" : "Archive"}
            </button>
          </div>,
          document.body
        )
        : null}

      {deleteModalChatId ? (
        <div className="absolute inset-0 z-50 flex items-end justify-center bg-slate-950/55 p-3">
          <div className="w-full rounded-xl border border-slate-700/80 bg-slate-900 p-3">
            <p className="mb-2 text-sm font-semibold">
              {deleteModalChat?.is_saved ? "Clear chat" : "Delete chat"}: {deleteModalChat ? chatLabel(deleteModalChat) : "selected chat"}
            </p>
            {deleteModalChat?.type === "channel" ? (
              <p className="mb-3 text-xs text-slate-400">Channels are removed for all subscribers.</p>
            ) : null}
            {deleteModalChat?.is_saved ? (
              <p className="mb-3 text-xs text-slate-400">This will clear all messages in Saved Messages.</p>
            ) : null}
            {canDeleteForEveryone ? (
              <label className="mb-3 flex items-center gap-2 text-sm">
                <input checked={deleteForAll} onChange={(e) => setDeleteForAll(e.target.checked)} type="checkbox" />
                Delete for everyone
              </label>
            ) : null}
            <div className="flex gap-2">
              <button
                className="flex-1 rounded bg-red-500 px-3 py-2 text-sm font-semibold text-white"
                onClick={async () => {
                  if (deleteModalChat?.is_saved) {
                    await clearChat(deleteModalChatId);
                    useChatStore.getState().clearChatMessages(deleteModalChatId);
                    setDeleteModalChatId(null);
                    return;
                  }
                  await deleteChat(deleteModalChatId, canDeleteForEveryone && deleteForAll);
                  await loadChats();
                  if (activeChatId === deleteModalChatId) {
                    setActiveChatId(null);
                  }
                  setDeleteModalChatId(null);
                }}
              >
                {deleteModalChat?.is_saved ? "Clear" : "Delete"}
              </button>
              <button className="flex-1 rounded bg-slate-700 px-3 py-2 text-sm" onClick={() => setDeleteModalChatId(null)}>
                Cancel
              </button>
            </div>
          </div>
        </div>
      ) : null}

      {profileOpen ? (
        <div className="absolute inset-0 z-50 flex items-end justify-center bg-slate-950/55 p-3">
          <div className="w-full rounded-xl border border-slate-700/80 bg-slate-900 p-3">
            <p className="mb-2 text-sm font-semibold">Edit profile</p>
            <div className="space-y-2">
              <input className="w-full rounded bg-slate-800 px-3 py-2 text-sm" placeholder="Name" value={profileName} onChange={(e) => setProfileName(e.target.value)} />
              <input className="w-full rounded bg-slate-800 px-3 py-2 text-sm" placeholder="Username" value={profileUsername} onChange={(e) => setProfileUsername(e.target.value.replace("@", ""))} />
              <input className="w-full rounded bg-slate-800 px-3 py-2 text-sm" placeholder="Bio (optional)" value={profileBio} onChange={(e) => setProfileBio(e.target.value)} />
              <input className="w-full rounded bg-slate-800 px-3 py-2 text-sm" placeholder="Avatar URL (optional)" value={profileAvatarUrl} onChange={(e) => setProfileAvatarUrl(e.target.value)} />
              <label className="flex items-center gap-2 rounded bg-slate-800 px-3 py-2 text-sm">
                <input
                  type="checkbox"
                  checked={profileAllowPrivateMessages}
                  onChange={(e) => setProfileAllowPrivateMessages(e.target.checked)}
                />
                Allow private messages
              </label>
            </div>
            {profileError ? <p className="mt-2 text-xs text-red-400">{profileError}</p> : null}
            <div className="mt-3 flex gap-2">
              <button
                className="flex-1 rounded bg-sky-500 px-3 py-2 text-sm font-semibold text-slate-950 disabled:opacity-60"
                disabled={profileSaving}
                onClick={async () => {
                  setProfileSaving(true);
                  setProfileError(null);
                  try {
                    const updated = await updateMyProfile({
                      name: profileName.trim() || undefined,
                      username: profileUsername.trim() || undefined,
                      bio: profileBio.trim() || null,
                      avatar_url: profileAvatarUrl.trim() || null,
                      allow_private_messages: profileAllowPrivateMessages
                    });
                    useAuthStore.setState({ me: updated });
                    await loadChats();
                    setProfileOpen(false);
                  } catch {
                    setProfileError("Failed to update profile");
                  } finally {
                    setProfileSaving(false);
                  }
                }}
              >
                Save
              </button>
              <button className="flex-1 rounded bg-slate-700 px-3 py-2 text-sm" onClick={() => setProfileOpen(false)}>
                Cancel
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </aside>
  );
}
  function getSafeContextPosition(x: number, y: number, menuWidth: number, menuHeight: number): { x: number; y: number } {
    const pad = 8;
    const cursorOffset = 4;
    const wantedX = x + cursorOffset;
    const wantedY = y + cursorOffset;
    const safeX = Math.min(Math.max(pad, wantedX), window.innerWidth - menuWidth - pad);
    const safeY = Math.min(Math.max(pad, wantedY), window.innerHeight - menuHeight - pad);
    return { x: safeX, y: safeY };
  }

function chatLabel(chat: { display_title?: string | null; title: string | null; type: "private" | "group" | "channel"; is_saved?: boolean }): string {
  if (chat.display_title?.trim()) return chat.display_title;
  if (chat.title?.trim()) return chat.title;
  if (chat.is_saved) return "Saved Messages";
  if (chat.type === "private") return "Direct chat";
  if (chat.type === "group") return "Group";
  return "Channel";
}

function chatMetaLabel(chat: {
  type: "private" | "group" | "channel";
  is_saved?: boolean;
  counterpart_is_online?: boolean | null;
  counterpart_last_seen_at?: string | null;
  members_count?: number | null;
  online_count?: number | null;
  subscribers_count?: number | null;
}): string {
  if (chat.is_saved) {
    return "Personal cloud chat";
  }
  if (chat.type === "private") {
    if (chat.counterpart_is_online) {
      return "online";
    }
    if (chat.counterpart_last_seen_at) {
      return `last seen ${formatLastSeen(chat.counterpart_last_seen_at)}`;
    }
    return "offline";
  }
  if (chat.type === "group") {
    const members = chat.members_count ?? 0;
    const online = chat.online_count ?? 0;
    return `${members} members, ${online} online`;
  }
  const subscribers = chat.subscribers_count ?? chat.members_count ?? 0;
  return `${subscribers} subscribers`;
}

function formatLastSeen(value: string): string {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return "recently";
  }
  return date.toLocaleString(undefined, {
    day: "2-digit",
    month: "short",
    hour: "2-digit",
    minute: "2-digit"
  });
}
