import LoadingWheel from '../LoadingWheel';
import { useEffect, useState } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import { socket } from '@/socket/socket';
import { UserRoundPlus } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useChat } from '@/context/chat/useChat';
import { axiosClient } from '@/utils/axiosClient';
import axios from 'axios';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';

type Inputs = {
  username: string;
};

function AddGroupMember() {
  const { currentContact } = useChat();
  const [open, setOpen] = useState(false);
  const { register, handleSubmit, watch, reset } = useForm<Inputs>();
  const contactInput = watch('username');
  const [suggestions, setSuggestions] = useState<string[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [notFound, setNotFound] = useState<boolean>(false);
  const [selectedIndex, setSelectedIndex] = useState<number>(0);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  useEffect(() => {
    const fetchSuggestions = async () => {
      if (contactInput?.length >= 3) {
        try {
          setIsLoading(true);
          setErrorMessage(null);
          const response = await axiosClient.get(
            `/api/chat/contacts/suggestions/${contactInput}`,
          );
          setSuggestions(response.data);
          setSelectedIndex(0);
          if (response.data.length < 1) {
            setIsLoading(false);
            setNotFound(true);
          } else {
            setIsLoading(false);
            setNotFound(false);
          }
        } catch (e) {
          if (axios.isAxiosError(e)) {
            setIsLoading(false);
            console.error('Error fetching suggestions:', e);
            setErrorMessage(
              e.response?.data?.message || 'Failed to fetch suggestions',
            );
          } else {
            console.error('Unexpected error occurred');
          }
        }
      } else {
        setNotFound(false);
        setIsLoading(false);
        setSuggestions([]);
      }
    };

    const delay = setTimeout(() => {
      fetchSuggestions();
    }, 300);

    return () => clearTimeout(delay);
  }, [contactInput]);

  if (!socket) return null;

  const onSubmit: SubmitHandler<Inputs> = async (data) => {
    const contactToSubmit =
      suggestions.length > 0
        ? suggestions[selectedIndex]
        : data.username.trim();

    try {
      setIsLoading(true);
      setErrorMessage(null);
      const response = await axiosClient.post(`/api/chat/groups/addMember/`, {
        group_id: currentContact?.conversation_id,
        username: contactToSubmit,
      });
      console.log('Add member to group', response);
      setIsLoading(false);
      socket?.emit('added to group', {
        group_id: currentContact?.conversation_id,
      });
      setOpen(false);
      reset();
    } catch (e) {
      if (axios.isAxiosError(e)) {
        console.error('Failed to add group member: ', e);
        setIsLoading(false);
        setErrorMessage(e.response?.data?.message || 'Failed to add member');
      } else {
        console.error('Unexpected error occurred');
      }
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (suggestions.length > 0) {
      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault();
          setSelectedIndex((prev) => (prev + 1) % suggestions.length);
          break;
        case 'ArrowUp':
          e.preventDefault();
          setSelectedIndex(
            (prev) => (prev - 1 + suggestions.length) % suggestions.length,
          );
          break;
        case 'Enter':
          if (suggestions.length > 0) {
            e.preventDefault();
            reset({ username: suggestions[selectedIndex] });
            handleSubmit(onSubmit)();
          }
          break;
      }
    }
  };

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <button className="p-2 hover:bg-zinc-800 rounded-lg" title="Add member">
          <UserRoundPlus />
        </button>
      </DialogTrigger>
      <DialogContent className="bg-zinc-950 text-white sm:max-w-md w-full border">
        <DialogHeader>
          <DialogTitle className="text-center text-gray-200">
            Enter username
          </DialogTitle>
        </DialogHeader>
        <div className="flex flex-col items-center justify-center space-y-4">
          <form onSubmit={handleSubmit(onSubmit)} className="w-full space-y-2">
            <div className="relative p-3">
              <Input
                className="bg-gray-100 text-black pl-2 h-10 rounded-lg"
                type="text"
                onKeyDown={handleKeyDown}
                {...register('username', {
                  minLength: 4,
                  maxLength: 20,
                })}
              />
              <div className="mt-1">
                {suggestions?.length > 0 ? (
                  <ul className="text-left p-2 bg-gray-900 shadow-md rounded-md w-full border">
                    {suggestions.map((suggestion, index) => (
                      <li
                        key={suggestion}
                        className={`p-1 cursor-pointer rounded-md mt-1 mb-1 ${
                          index === selectedIndex
                            ? 'bg-gray-500'
                            : 'hover:bg-gray-500'
                        }`}
                        onClick={() => {
                          handleSubmit(() =>
                            onSubmit({ username: suggestion }),
                          )();
                          setSuggestions([]);
                        }}
                      >
                        {suggestion}
                      </li>
                    ))}
                  </ul>
                ) : isLoading ? (
                  <div className="flex justify-center">
                    <LoadingWheel />
                  </div>
                ) : null}
                {notFound && (
                  <p className="p-1 bg-gray-800 shadow-md rounded-md w-full border text-gray-400">
                    user not found
                  </p>
                )}
              </div>
            </div>
            {errorMessage && (
              <p className="text-red-500 mt-2 p-1 bg-gray-800 rounded-md w-full">
                {errorMessage}
              </p>
            )}
            <div className="flex justify-center pt-4">
              <Button
                type="submit"
                className="w-24 bg-green-500 text-black hover:bg-green-600"
                disabled={isLoading}
              >
                {isLoading ? <LoadingWheel /> : 'Add'}
              </Button>
            </div>
          </form>
        </div>
      </DialogContent>
    </Dialog>
  );
}

export default AddGroupMember;
