import { FormEvent, useMemo, useState } from "react";
import { createChat, createPrivateChat, createPublicChat, getChats, getSavedMessagesChat, joinByInvite } from "../api/chats";
import { searchUsers } from "../api/users";
import type { ChatType, UserSearchItem } from "../chat/types";
import { useChatStore } from "../store/chatStore";

type CreateMode = "group" | "channel";
type DialogMode = "none" | "private" | "group" | "channel" | "invite";

export function NewChatPanel() {
  const [dialog, setDialog] = useState<DialogMode>("none");
  const [query, setQuery] = useState("");
  const [title, setTitle] = useState("");
  const [handle, setHandle] = useState("");
  const [description, setDescription] = useState("");
  const [inviteToken, setInviteToken] = useState("");
  const [isPublic, setIsPublic] = useState(false);
  const [results, setResults] = useState<UserSearchItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [menuOpen, setMenuOpen] = useState(false);
  const setActiveChatId = useChatStore((s) => s.setActiveChatId);

  const normalizedQuery = useMemo(() => query.trim(), [query]);

  async function handleSearchUsers(value: string) {
    setQuery(value);
    setError(null);
    if (value.trim().replace("@", "").length < 2) {
      setResults([]);
      return;
    }
    try {
      const users = await searchUsers(value);
      setResults(users);
    } catch {
      setError("Search failed");
    }
  }

  async function refreshChatsAndSelect(chatId?: number) {
    const chats = await getChats();
    useChatStore.setState({ chats });
    if (chatId) {
      setActiveChatId(chatId);
      return;
    }
    if (chats[0]) {
      setActiveChatId(chats[0].id);
    }
  }

  async function openSavedMessages() {
    const saved = await getSavedMessagesChat();
    await refreshChatsAndSelect(saved.id);
  }

  async function createPrivate(userId: number) {
    setLoading(true);
    setError(null);
    try {
      const chat = await createPrivateChat(userId);
      await refreshChatsAndSelect(chat.id);
      setDialog("none");
      setQuery("");
      setResults([]);
    } catch {
      setError("Failed to create private chat");
    } finally {
      setLoading(false);
    }
  }

  async function createByType(event: FormEvent, mode: CreateMode) {
    event.preventDefault();
    if (!title.trim()) {
      setError("Title is required");
      return;
    }
    setLoading(true);
    setError(null);
    try {
      let chat;
      if (isPublic) {
        const normalizedHandle = handle.trim().replace("@", "").toLowerCase();
        if (!normalizedHandle) {
          setError("Public chat requires @handle");
          setLoading(false);
          return;
        }
        chat = await createPublicChat(mode, title.trim(), normalizedHandle, description.trim() || undefined);
      } else {
        chat = await createChat(mode as ChatType, title.trim(), []);
      }
      await refreshChatsAndSelect(chat.id);
      setDialog("none");
      setTitle("");
      setHandle("");
      setDescription("");
      setIsPublic(false);
    } catch {
      setError("Failed to create chat");
    } finally {
      setLoading(false);
    }
  }

  function closeDialog() {
    setDialog("none");
    setError(null);
    setQuery("");
    setResults([]);
    setIsPublic(false);
    setInviteToken("");
  }

  return (
    <>
      <div className="absolute bottom-4 right-4 z-20">
        <div className="relative">
        {menuOpen ? (
          <div className="absolute bottom-14 right-0 w-48 rounded-xl border border-slate-700/80 bg-slate-900/95 p-1 shadow-xl">
            <button className="block w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-slate-800" onClick={() => void openSavedMessages()}>
              Saved Messages
            </button>
            <button className="block w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-slate-800" onClick={() => { setDialog("channel"); setMenuOpen(false); }}>
              New Channel
            </button>
            <button className="block w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-slate-800" onClick={() => { setDialog("group"); setMenuOpen(false); }}>
              New Group
            </button>
            <button className="block w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-slate-800" onClick={() => { setDialog("private"); setMenuOpen(false); }}>
              New Message
            </button>
            <button className="block w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-slate-800" onClick={() => { setDialog("invite"); setMenuOpen(false); }}>
              Join by Link
            </button>
          </div>
        ) : null}
        <button className="flex h-12 w-12 items-center justify-center rounded-full bg-sky-500 text-slate-950 shadow-lg hover:bg-sky-400" onClick={() => setMenuOpen((v) => !v)}>
          <span className="block w-5 text-center text-2xl leading-none">{menuOpen ? "✕" : "+"}</span>
        </button>
        </div>
      </div>

      {dialog !== "none" ? (
        <div className="absolute inset-0 z-30 flex items-end justify-center bg-slate-950/55 p-3">
          <div className="w-full max-w-sm rounded-2xl border border-slate-700/80 bg-slate-900 p-3 shadow-2xl">
            <div className="mb-2 flex items-center justify-between">
              <p className="text-sm font-semibold">
                {dialog === "private" ? "New Message" : dialog === "group" ? "New Group" : dialog === "channel" ? "New Channel" : "Join by Link"}
              </p>
              <button className="rounded-md bg-slate-700/80 px-2 py-1 text-xs" onClick={closeDialog}>Close</button>
            </div>

            {dialog === "private" ? (
              <div className="space-y-2">
                <input className="w-full rounded-xl 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="@username" value={query} onChange={(e) => void handleSearchUsers(e.target.value)} />
                <div className="tg-scrollbar max-h-44 overflow-auto">
                  {results.map((user) => (
                    <button className="mb-1 block w-full rounded-lg bg-slate-800 px-3 py-2 text-left text-sm hover:bg-slate-700" key={user.id} onClick={() => void createPrivate(user.id)}>
                      <p className="truncate font-semibold">{user.name}</p>
                      <p className="truncate text-xs text-slate-400">@{user.username}</p>
                    </button>
                  ))}
                  {normalizedQuery && results.length === 0 ? <p className="text-xs text-slate-400">No users</p> : null}
                </div>
              </div>
            ) : null}

            {dialog === "group" || dialog === "channel" ? (
              <form className="space-y-2" onSubmit={(e) => void createByType(e, dialog)}>
                <input className="w-full rounded-xl 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={dialog === "group" ? "Group title" : "Channel title"} value={title} onChange={(e) => setTitle(e.target.value)} />
                <label className="flex items-center gap-2 rounded-xl border border-slate-700/80 bg-slate-800/60 px-3 py-2 text-sm">
                  <input checked={isPublic} onChange={(e) => setIsPublic(e.target.checked)} type="checkbox" />
                  Public {dialog} (discover + join by others)
                </label>
                {isPublic ? (
                  <input className="w-full rounded-xl 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="@handle (required for public)" value={handle} onChange={(e) => setHandle(e.target.value)} />
                ) : null}
                <input className="w-full rounded-xl 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="Description (optional)" value={description} onChange={(e) => setDescription(e.target.value)} />
                <button className="w-full rounded-lg bg-sky-500 px-3 py-2 text-sm font-semibold text-slate-950 hover:bg-sky-400 disabled:opacity-60" disabled={loading} type="submit">
                  Create {dialog}
                </button>
              </form>
            ) : null}

            {dialog === "invite" ? (
              <form
                className="space-y-2"
                onSubmit={async (e) => {
                  e.preventDefault();
                  if (!inviteToken.trim()) {
                    setError("Invite token is required");
                    return;
                  }
                  setLoading(true);
                  setError(null);
                  try {
                    const raw = inviteToken.trim();
                    const match = raw.match(/[?&]token=([^&]+)/i);
                    const token = match ? decodeURIComponent(match[1]) : raw;
                    const chat = await joinByInvite(token);
                    await refreshChatsAndSelect(chat.id);
                    closeDialog();
                  } catch {
                    setError("Failed to join by invite");
                  } finally {
                    setLoading(false);
                  }
                }}
              >
                <input
                  className="w-full rounded-xl 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="Invite link or token"
                  value={inviteToken}
                  onChange={(e) => setInviteToken(e.target.value)}
                />
                <button className="w-full rounded-lg bg-sky-500 px-3 py-2 text-sm font-semibold text-slate-950 hover:bg-sky-400 disabled:opacity-60" disabled={loading} type="submit">
                  Join
                </button>
              </form>
            ) : null}

            {error ? <p className="mt-2 text-xs text-red-400">{error}</p> : null}
          </div>
        </div>
      ) : null}
    </>
  );
}
