import React, { useEffect, useMemo, useRef, useState } from "react";
import { FaChevronDown, FaChevronUp, FaLock } from "react-icons/fa6";
import { FaSearch, FaTimes } from "react-icons/fa";
import { Category, Style } from "@/types/categories";
import { useActiveStyles, useExpandedCategories } from "@/ui/hooks";
import { useWallpaperCategories } from "@/ui/hooks/useWallpaperCategories";
import { useModeSearch } from "@/ui/hooks/useModeSearch";
import { useLicense } from "@/ui/hooks/useLicense";
import { FREE_STYLE_SELECTION_LIMIT } from "@/types/license";
import { UpgradeModal } from "../UpgradeModal";

interface UseExpandedCategoriesReturn {
  expandedCategories: string[];
  toggleCategory: (category: string) => void;
  setExpandedCategories: (categories: string[] | ((prevCategories: string[]) => string[])) => void;
}

export const RandomModePanel: React.FC = () => {
  const { activeStyles, setActiveStyles, toggleStyle, isStyleActive } = useActiveStyles();
  const {
    expandedCategories,
    toggleCategory: originalToggleCategory,
    setExpandedCategories: setAllExpandedCategories,
  }: UseExpandedCategoriesReturn = useExpandedCategories();
  const { wallpaperCategories, loading, error } = useWallpaperCategories();
  const { isPremium } = useLicense();
  const panelRef = useRef<HTMLDivElement>(null);
  const categoryCheckboxRefs = useRef<Map<string, HTMLInputElement>>(new Map());

  // State for upgrade modal/prompt
  const [showUpgradePrompt, setShowUpgradePrompt] = useState(false);
  const [lockedStyleClicked, setLockedStyleClicked] = useState<string | null>(null);

  // Use the search hook
  const { searchQuery, handleSearchChange, filteredCategories, clearSearch } = useModeSearch({
    wallpaperCategories,
    setExpandedCategories: setAllExpandedCategories,
  });

  // Helper to check if a style is premium and locked for current user
  const isStyleLocked = (style: Style): boolean => {
    return !isPremium && style.tier === "premium";
  };

  // Helper to get free styles only (for counting available selections)
  const getAvailableStyles = (): Style[] => {
    return wallpaperCategories.flatMap((category) => category.styles.filter((style) => !isStyleLocked(style)));
  };

  // Set all categories to be expanded initially if expandedCategories is empty
  useEffect(() => {
    if (wallpaperCategories.length > 0 && expandedCategories.length === 0) {
      setAllExpandedCategories(wallpaperCategories.map((category: Category) => category.id));
    }
  }, [wallpaperCategories, expandedCategories.length, setAllExpandedCategories]);

  // Custom toggleCategory to maintain scroll position
  const toggleCategory = (categoryId: string) => {
    if (panelRef.current) {
      const scrollPosition = panelRef.current.scrollTop;
      originalToggleCategory(categoryId);
      setTimeout(() => {
        if (panelRef.current) {
          panelRef.current.scrollTop = scrollPosition;
        }
      }, 0);
    } else {
      originalToggleCategory(categoryId);
    }
  };

  // Enhanced toggleStyle with premium style checking
  const handleToggleStyle = (style: Style) => {
    // Check if style is locked for free users
    if (isStyleLocked(style)) {
      setLockedStyleClicked(style.label);
      setShowUpgradePrompt(true);
      return;
    }

    // If the style is already active, allow deselection
    if (isStyleActive(style.label)) {
      toggleStyle(style.label);
      return;
    }

    // For free users, check the selection limit (only count available styles)
    if (!isPremium) {
      const availableStyles = getAvailableStyles();
      const currentFreeSelections = activeStyles.filter((activeStyle) =>
        availableStyles.some((availableStyle) => availableStyle.label === activeStyle),
      ).length;

      if (currentFreeSelections >= FREE_STYLE_SELECTION_LIMIT) {
        // Don't allow selection of more styles
        return;
      }
    }

    // Allow selection
    toggleStyle(style.label);
  };

  // Toggle all styles in a category with premium checking
  const toggleCategoryStyles = (category: Category, event: React.MouseEvent) => {
    event.stopPropagation();

    // Filter category styles based on what user can access
    const accessibleStyles = category.styles.filter((style) => !isStyleLocked(style));
    const categoryStyleLabels = accessibleStyles.map((style) => style.label);

    if (categoryStyleLabels.length === 0) {
      // All styles in category are locked
      setShowUpgradePrompt(true);
      return;
    }

    const allActive = categoryStyleLabels.every((label) => isStyleActive(label));
    const someActive = categoryStyleLabels.some((label) => isStyleActive(label));

    if (allActive || someActive) {
      // Deselecting - always allowed
      setActiveStyles((prev) => prev.filter((style) => !categoryStyleLabels.includes(style)));
    } else {
      // Selecting - check limits for free users
      if (!isPremium) {
        const currentCount = activeStyles.filter((activeStyle) =>
          getAvailableStyles().some((availableStyle) => availableStyle.label === activeStyle),
        ).length;
        const availableSlots = FREE_STYLE_SELECTION_LIMIT - currentCount;
        const stylesToAdd = categoryStyleLabels.slice(0, availableSlots);

        if (stylesToAdd.length > 0) {
          setActiveStyles((prev) => [...prev, ...stylesToAdd]);
        }
      } else {
        // Premium users can select all accessible styles
        setActiveStyles((prev) => [...prev, ...categoryStyleLabels]);
      }
    }
  };

  // Check the state of a category (only count accessible styles)
  const getCategoryCheckState = (category: Category) => {
    const accessibleStyles = category.styles.filter((style) => !isStyleLocked(style));
    const categoryStyleLabels = accessibleStyles.map((style) => style.label);
    const allActive = categoryStyleLabels.every((label) => isStyleActive(label));
    const someActive = categoryStyleLabels.some((label) => isStyleActive(label));
    const activeCount = categoryStyleLabels.filter((label) => isStyleActive(label)).length;
    const totalCount = categoryStyleLabels.length;
    const lockedCount = category.styles.length - accessibleStyles.length;

    return {
      checked: allActive,
      indeterminate: !allActive && someActive,
      categoryStyles: categoryStyleLabels,
      activeCount,
      totalCount,
      lockedCount,
    };
  };

  // Update indeterminate states after render
  useEffect(() => {
    wallpaperCategories.forEach((category) => {
      const checkbox = categoryCheckboxRefs.current.get(category.id);
      if (checkbox) {
        const { indeterminate } = getCategoryCheckState(category);
        checkbox.indeterminate = indeterminate;
      }
    });
  }, [activeStyles, wallpaperCategories, isPremium]);

  // --- Select/Deselect All Logic ---
  const allAvailableStyleLabels = useMemo(() => {
    return getAvailableStyles().map((style) => style.label);
  }, [wallpaperCategories, isPremium]);

  const isAllSelected = useMemo(() => {
    if (allAvailableStyleLabels.length === 0) return false;
    const activeSet = new Set(activeStyles);
    return allAvailableStyleLabels.every((label) => activeSet.has(label));
  }, [activeStyles, allAvailableStyleLabels]);

  const selectAllStyles = () => {
    if (!isPremium) {
      // For free users, only select up to the limit from available styles
      const stylesToSelect = allAvailableStyleLabels.slice(0, FREE_STYLE_SELECTION_LIMIT);
      setActiveStyles(stylesToSelect);
    } else {
      // Premium users can select all available styles
      setActiveStyles(allAvailableStyleLabels);
    }
  };

  const deselectAllStyles = () => {
    setActiveStyles([]);
  };

  // Check if style selection is at limit for free users (only count accessible styles)
  const currentAccessibleSelections = activeStyles.filter((activeStyle) =>
    allAvailableStyleLabels.includes(activeStyle),
  ).length;

  const isAtSelectionLimit = !isPremium && currentAccessibleSelections >= FREE_STYLE_SELECTION_LIMIT;
  const remainingSelections = isPremium
    ? Infinity
    : Math.max(0, FREE_STYLE_SELECTION_LIMIT - currentAccessibleSelections);

  // Count total styles for display
  const totalStyles = wallpaperCategories.flatMap((cat) => cat.styles).length;
  const freeStylesCount = wallpaperCategories
    .flatMap((cat) => cat.styles)
    .filter((style) => style.tier === "free").length;
  const premiumStylesCount = totalStyles - freeStylesCount;

  if (loading) {
    return (
      <div className='bg-gray-800 p-2 rounded-md mb-2 flex items-center justify-center'>
        <p className='text-white text-sm'>Loading styles...</p>
      </div>
    );
  }

  if (error) {
    return (
      <div className='bg-gray-800 p-2 rounded-md mb-2 flex flex-col items-center justify-center'>
        <p className='text-sm text-red-400'>{error}</p>
        {wallpaperCategories.length === 0 && (
          <p className='text-xs text-gray-400 mt-1'>Style categories unavailable. Check your network connection.</p>
        )}
      </div>
    );
  }

  return (
    <div className='bg-gray-800 p-2 rounded-md mb-2' ref={panelRef}>
      <h2 className='text-white text-sm font-medium mb-1'>Selected Style Settings</h2>
      <p className='text-gray-400 text-xs mb-1'>
        Select multiple styles below. When you generate a wallpaper, one will be chosen at random.
        {!isPremium && (
          <span className='text-amber-300'>
            {" "}
            You can select {freeStylesCount} free styles. {premiumStylesCount} premium styles are locked.
          </span>
        )}
        {isPremium && <span className='text-purple-300'> Premium access: All {totalStyles} styles available!</span>}
      </p>

      {/* Free user info and upgrade prompt */}
      {!isPremium && (
        <div className='mb-2 p-2 bg-amber-900/30 border border-amber-500/50 rounded text-xs'>
          <p className='text-amber-200'>
            Free plan: {freeStylesCount} free styles, {premiumStylesCount} locked. ({remainingSelections} remaining)
          </p>
          {isAtSelectionLimit && (
            <p className='text-amber-300 mt-1'>Selection limit reached. Upgrade for unlimited style selection!</p>
          )}
          <button
            onClick={() => setShowUpgradePrompt(true)}
            className='mt-1 px-2 py-1 bg-amber-600 hover:bg-amber-700 text-white rounded text-xs transition-colors'
          >
            Upgrade for unlimited style selection
          </button>
        </div>
      )}

      {/* Upgrade Modal */}
      <UpgradeModal
        isOpen={showUpgradePrompt}
        onClose={() => {
          setShowUpgradePrompt(false);
          setLockedStyleClicked(null);
        }}
        lockedStyle={lockedStyleClicked}
        message={
          lockedStyleClicked
            ? `${lockedStyleClicked} requires premium access`
            : `Upgrade to unlock all ${premiumStylesCount} premium styles`
        }
      />

      <div>
        {/* Select/Deselect All Buttons */}
        {allAvailableStyleLabels.length > 0 && (
          <div className='flex items-center gap-2 my-1 mb-2'>
            {isAllSelected || (!isPremium && currentAccessibleSelections >= FREE_STYLE_SELECTION_LIMIT) ? (
              <button
                className='text-xs text-indigo-400 hover:text-indigo-300 focus:outline-none focus:ring-1 rounded px-1 py-0.5'
                onClick={deselectAllStyles}
              >
                Deselect All
              </button>
            ) : (
              <button
                onClick={selectAllStyles}
                className='text-xs text-indigo-400 hover:text-indigo-300 focus:outline-none focus:ring-1 rounded px-1 py-0.5'
              >
                Select All{" "}
                {!isPremium
                  ? `Free (${Math.min(FREE_STYLE_SELECTION_LIMIT, allAvailableStyleLabels.length)})`
                  : `(${allAvailableStyleLabels.length})`}
              </button>
            )}
            <span className='text-xs text-gray-400'>
              ({currentAccessibleSelections}/{isPremium ? allAvailableStyleLabels.length : FREE_STYLE_SELECTION_LIMIT}{" "}
              selected)
            </span>
          </div>
        )}
        {/* Search input */}
        <div className='relative flex items-center my-1 mb-2'>
          <input
            type='text'
            placeholder='Search styles...'
            className='w-full rounded-md py-1.5 px-3 pr-16 bg-gray-700 text-white text-sm border border-gray-600 focus:border-indigo-400 focus:outline-none'
            value={searchQuery}
            onChange={handleSearchChange}
          />
          <div className='absolute right-0 flex items-center pr-2'>
            {searchQuery && (
              <button
                className='text-gray-400 hover:text-white p-1 focus:outline-none'
                onClick={clearSearch}
                aria-label='Clear search'
              >
                <FaTimes size={14} />
              </button>
            )}
            <span className='text-gray-400 ml-1 mr-1'>
              <FaSearch size={14} />
            </span>
          </div>
        </div>
      </div>
      {/* Style Selection Grid */}
      <div className='flex flex-col gap-2'>
        {filteredCategories.length === 0 && searchQuery && (
          <div className='text-gray-400 text-center py-4'>No styles found matching &quot;{searchQuery}&quot;</div>
        )}

        {filteredCategories.map((category) => {
          const { checked, activeCount, totalCount, lockedCount } = getCategoryCheckState(category);

          return (
            <div key={category.id} className='relative'>
              <div
                className='sticky -top-2 flex justify-between items-center py-1 px-2 cursor-pointer mb-1 border-b border-gray-700 bg-gray-800 z-20 shadow-md'
                onClick={() => toggleCategory(category.id)}
                role='button'
                tabIndex={0}
                onKeyDown={(e) => {
                  if (e.key === "Enter" || e.key === " ") {
                    toggleCategory(category.id);
                  }
                }}
              >
                <h3 className='text-white font-medium text-sm'>{category.title}</h3>
                <div className='flex items-center gap-2'>
                  <span className='text-xs text-gray-400'>
                    {activeCount === 0 && totalCount === 0 && "All locked"}
                    {activeCount === 0 && totalCount > 0 && "None selected"}
                    {activeCount > 0 && activeCount < totalCount && `${activeCount}/${totalCount} selected`}
                    {activeCount === totalCount && totalCount > 0 && "All selected"}
                    {lockedCount > 0 && <span className='text-amber-400 ml-1'>({lockedCount} 🔒)</span>}
                  </span>
                  {totalCount > 0 && (
                    <input
                      type='checkbox'
                      className='h-3.5 w-3.5 rounded border-gray-600 text-indigo-500 focus:ring-indigo-500'
                      checked={checked}
                      readOnly
                      onClick={(e) => toggleCategoryStyles(category, e)}
                      ref={(el) => {
                        if (el) categoryCheckboxRefs.current.set(category.id, el);
                      }}
                    />
                  )}
                  {expandedCategories.includes(category.id) ? (
                    <FaChevronUp className='text-white text-xs opacity-60' />
                  ) : (
                    <FaChevronDown className='text-white text-xs opacity-60' />
                  )}
                </div>
              </div>

              {expandedCategories.includes(category.id) && (
                <div className='grid grid-cols-2 gap-2 mb-2'>
                  {category.styles.map((style: Style, idx: number) => {
                    const isLocked = isStyleLocked(style);
                    const canSelect = !isLocked && (isPremium || isStyleActive(style.label) || !isAtSelectionLimit);

                    return (
                      <div
                        key={style.label}
                        role='button'
                        tabIndex={idx + 4}
                        className={`relative flex flex-col w-full h-28 justify-between p-1 cursor-pointer rounded-md overflow-hidden bg-gray-700 ${
                          isLocked ? "opacity-75" : !canSelect ? "opacity-50 cursor-not-allowed" : ""
                        }`}
                        onClick={() => (isLocked ? handleToggleStyle(style) : canSelect && handleToggleStyle(style))}
                        onKeyDown={(e) => {
                          if (e.key === " " || e.key === "Enter") {
                            if (isLocked) {
                              handleToggleStyle(style);
                            } else if (canSelect) {
                              handleToggleStyle(style);
                            }
                          }
                        }}
                      >
                        {/* Background image with overlay */}
                        <>
                          <div
                            className='absolute inset-0 bg-cover bg-center'
                            style={{ backgroundImage: `url(${style.preview_url})` }}
                          />
                          <div
                            className={`absolute inset-0 ${isLocked ? "bg-black bg-opacity-60" : "bg-black bg-opacity-40"}`}
                          />
                        </>

                        {/* Premium lock overlay */}
                        {isLocked && (
                          <div className='absolute inset-0 flex items-center justify-center z-20'>
                            <div className='flex flex-col items-center'>
                              <div className='bg-amber-500 rounded-full p-2 mb-1'>
                                <FaLock className='text-black' size={12} />
                              </div>
                              <span className='text-amber-300 text-[10px] font-bold'>PREMIUM</span>
                            </div>
                          </div>
                        )}

                        {/* Content */}
                        <div className='flex justify-end relative z-10'>
                          <input
                            type='checkbox'
                            checked={isStyleActive(style.label)}
                            onChange={() => handleToggleStyle(style)}
                            onClick={(e) => e.stopPropagation()}
                            disabled={isLocked || !canSelect}
                            className={isLocked ? "opacity-50" : ""}
                          />
                        </div>
                        <div className='flex justify-start relative z-10 max-w-full'>
                          <p
                            className={`text-white text-xs font-medium text-wrap drop-shadow-lg shadow-black ${isLocked ? "opacity-90" : ""}`}
                          >
                            {style.label}
                          </p>
                        </div>

                        {/* Selection limit indicator for free users (only on unlocked styles) */}
                        {!isPremium && !isLocked && !isStyleActive(style.label) && isAtSelectionLimit && (
                          <div className='absolute inset-0 bg-black bg-opacity-60 flex items-center justify-center z-20'>
                            <div className='text-amber-300 text-[10px] text-center px-1'>
                              <p>Limit</p>
                              <p>Reached</p>
                            </div>
                          </div>
                        )}
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
};
