import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import axiosInstance from "../../api/axiosInstance";
import { useCreatedPlaylists } from "../../context/playlistContext";

interface PlaylistDropdownProps {
  songId: number;
  isOpen: boolean;
  onClose: () => void;
  position?: { top: number; left: number };

  usePortal?: boolean;

  direction?: "above" | "below";

  onCreateNewPlaylist?: () => void;
}

const PlaylistDropdown = ({
  songId,
  isOpen,
  onClose,
  position,
  usePortal = false,
  direction = "above",
  onCreateNewPlaylist,
}: PlaylistDropdownProps) => {
  const { createdPlaylists, refreshPlaylists } = useCreatedPlaylists();
  const [containingPlaylistIds, setContainingPlaylistIds] = useState<number[]>(
    [],
  );
  const [loading, setLoading] = useState(false);
  const [processingPlaylistId, setProcessingPlaylistId] = useState<
    number | null
  >(null);
  const dropdownRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (isOpen && songId) {
      const fetchPlaylistIds = async () => {
        setLoading(true);
        setContainingPlaylistIds([]);
        try {
          const response = await axiosInstance.get<number[]>(
            `/playlists/song/${songId}`,
          );
          setContainingPlaylistIds(response.data);
        } catch (error) {
          console.error("Failed to fetch song presence:", error);
        } finally {
          setLoading(false);
        }
      };
      fetchPlaylistIds();
    } else {
      setContainingPlaylistIds([]);
    }
  }, [isOpen, songId]);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(event.target as Node)
      ) {
        onClose();
      }
    };

    if (isOpen) {
      document.addEventListener("mousedown", handleClickOutside);
    }
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [isOpen, onClose]);

  const handleTogglePlaylist = async (playlistId: number, songId: number) => {
    if (processingPlaylistId !== null) return;

    setProcessingPlaylistId(playlistId);

    try {
      const response = await axiosInstance.post<{
        playlistId: number;
        isSongAddedToPlaylist: boolean;
      }>(`/playlists/${playlistId}/song/${songId}`);

      const { playlistId: returnedPlaylistId, isSongAddedToPlaylist } =
        response.data;

      if (isSongAddedToPlaylist) {
        setContainingPlaylistIds((prev) =>
          prev.includes(returnedPlaylistId)
            ? prev
            : [...prev, returnedPlaylistId],
        );
      } else {
        setContainingPlaylistIds((prev) =>
          prev.filter((id) => id !== returnedPlaylistId),
        );
      }
    } catch (error) {
      console.error("Failed to toggle playlist:", error);
    } finally {
      refreshPlaylists(true);
      setTimeout(() => {
        setProcessingPlaylistId(null);
      }, 500);
    }
  };

  const handleCreateNew = () => {
    onCreateNewPlaylist?.();
    onClose();
  };

  if (!isOpen) return null;

  const inlinePositionClass =
    direction === "below"
      ? "absolute left-0 top-full mt-2"
      : "absolute right-0 bottom-full mb-2";

  const dropdownContent = (
    <div
      ref={dropdownRef}
      className={`${usePortal ? "fixed" : inlinePositionClass} w-56 bg-[#282828] rounded-lg shadow-2xl py-2 z-[9999] border border-white/10 max-h-60 overflow-y-auto custom-scrollbar`}
      style={
        usePortal && position
          ? {
              top: position.top,
              left: position.left,
              transform:
                direction === "below" ? undefined : "translateY(-100%)",
            }
          : undefined
      }
      onClick={(e) => e.stopPropagation()}
    >
      <div className="px-4 py-2 text-xs font-bold text-gray-400 uppercase tracking-wider border-b border-white/5 mb-1">
        Add to playlist
      </div>

      {loading ? (
        <div className="flex items-center justify-center py-4">
          <div className="w-5 h-5 border-2 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
        </div>
      ) : createdPlaylists && createdPlaylists.length > 0 ? (
        createdPlaylists.map((playlist) => {
          const isProcessing = processingPlaylistId === playlist.id;
          const isChecked = containingPlaylistIds.includes(playlist.id);

          return (
            <label
              key={playlist.id}
              className={`flex items-center px-4 py-2 hover:bg-white/10 transition-colors group/item ${
                isProcessing ? "pointer-events-none" : "cursor-pointer"
              }`}
              onClick={(e) => e.stopPropagation()}
            >
              <div className="relative flex items-center justify-center">
                <input
                  type="checkbox"
                  className="peer sr-only"
                  checked={isChecked}
                  disabled={processingPlaylistId !== null}
                  onChange={() => handleTogglePlaylist(playlist.id, songId)}
                />
                <div
                  className={`w-5 h-5 border-2 rounded bg-[#181818] transition-all ${
                    isProcessing
                      ? "border-[#1db954] animate-pulse"
                      : isChecked
                        ? "bg-[#1db954] border-[#1db954]"
                        : "border-gray-500"
                  }`}
                >
                  {isProcessing && (
                    <div className="absolute inset-0 flex items-center justify-center">
                      <div className="w-3 h-3 border-2 border-transparent border-t-[#1db954] rounded-full animate-spin"></div>
                    </div>
                  )}
                </div>
                <svg
                  className={`absolute w-3 h-3  transition-opacity ${
                    isChecked && !isProcessing ? "opacity-100" : "opacity-0"
                  }`}
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="3"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M5 13l4 4L19 7"
                  />
                </svg>
              </div>
              <span
                className={`ml-3 text-sm truncate transition-all ${
                  isProcessing
                    ? "text-[#1db954] animate-pulse"
                    : "text-gray-200 group-hover/item:text-white"
                }`}
              >
                {playlist.name}
              </span>
              {isProcessing && (
                <span className="ml-auto text-xs text-[#1db954] animate-pulse">
                  •••
                </span>
              )}
            </label>
          );
        })
      ) : (
        <div className="px-4 py-3 text-sm text-gray-500 italic">
          No playlists created
        </div>
      )}

      <button
        onClick={(e) => {
          e.stopPropagation();
          handleCreateNew();
        }}
        className="w-full text-left px-4 py-2 mt-1 text-sm text-[#1db954] hover:bg-white/5 transition-colors border-t border-white/5 flex items-center gap-2 font-medium cursor-pointer"
      >
        <svg
          className="w-4 h-4"
          fill="none"
          stroke="currentColor"
          viewBox="0 0 24 24"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M12 4v16m8-8H4"
          />
        </svg>
        Create new playlist
      </button>
    </div>
  );

  return usePortal
    ? createPortal(dropdownContent, document.body)
    : dropdownContent;
};

export default PlaylistDropdown;
