import {
  IInformationCenterNPC,
  NPCAlignment,
  isMobileOrTablet,
} from '@rpg-engine/shared';
import React, { useMemo, useState } from 'react';
import styled from 'styled-components';
import { useTooltipPosition } from '../../../../hooks/useTooltipPosition';
import { IOptionsProps } from '../../../Dropdown';
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
import { Portal } from '../../../shared/Portal/Portal';
import { InformationCenterCell } from '../../InformationCenterCell';
import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
import { formatItemType } from '../items/InformationCenterItemsSection';
import { BestiaryAdvancedFilters } from './BestiaryAdvancedFilters';
import { InformationCenterNPCDetails } from './InformationCenterNPCDetails';
import { InformationCenterNPCTooltip } from './InformationCenterNPCTooltip';

interface IBestiarySectionProps {
  bestiaryItems: IInformationCenterNPC[];
  itemsAtlasJSON: Record<string, any>;
  itemsAtlasIMG: string;
  entitiesAtlasJSON: Record<string, any>;
  entitiesAtlasIMG: string;
  iconsAtlasIMG: any;
  iconsAtlasJSON: any;
  initialSearchQuery: string;
  tabId: string;
}

export const InformationCenterBestiarySection = ({
  bestiaryItems,
  itemsAtlasJSON,
  itemsAtlasIMG,
  iconsAtlasIMG,
  iconsAtlasJSON,
  entitiesAtlasJSON,
  entitiesAtlasIMG,
  initialSearchQuery,
  tabId,
}: IBestiarySectionProps): JSX.Element => {
  const isMobile = isMobileOrTablet();
  const [searchQuery, setSearchQuery] = useState<string>(initialSearchQuery);
  const [
    selectedMonster,
    setSelectedMonster,
  ] = useState<IInformationCenterNPC | null>(null);
  const [selectedBestiaryCategory, setSelectedBestiaryCategory] = useState<
    string
  >('all');

  const {
    tooltipState,
    handleMouseEnter,
    handleMouseLeave,
    TOOLTIP_WIDTH,
  } = useTooltipPosition<IInformationCenterNPC>();

  // Advanced filters state
  const [isAdvancedFiltersOpen, setIsAdvancedFiltersOpen] = useState<boolean>(
    false
  );
  const [levelRange, setLevelRange] = useState<
    [number | undefined, number | undefined]
  >([undefined, undefined]);
  const [selectedSubtype, setSelectedSubtype] = useState<string>('all');
  const [selectedAttackType, setSelectedAttackType] = useState<string>('all');

  const handleTouchStart = (
    monster: IInformationCenterNPC,
    event: React.TouchEvent
  ): void => {
    event.preventDefault();
    setSelectedMonster(monster);
  };

  const handleMonsterClick = (monster: IInformationCenterNPC): void => {
    setSelectedMonster(monster);
  };

  const bestiaryCategoryOptions: IOptionsProps[] = [
    { id: 0, value: 'all', option: 'All Monsters' },
    { id: 1, value: 'bosses', option: 'Bosses' },
    ...Object.entries(NPCAlignment)
      .filter(([, value]) => value !== NPCAlignment.Friendly)
      .map(([, value], index) => ({
        id: index + 2,
        value,
        option: formatItemType(value),
      })),
  ];

  const renderItem = (item: IInformationCenterNPC): JSX.Element => (
    <InformationCenterCell
      key={item.id}
      name={item.name}
      spriteKey={item.key}
      atlasJSON={entitiesAtlasJSON}
      atlasIMG={entitiesAtlasIMG}
      onClick={() => handleMonsterClick(item)}
      onMouseEnter={e => handleMouseEnter(item, e)}
      onMouseLeave={handleMouseLeave}
      onTouchStart={e => handleTouchStart(item, e)}
    />
  );

  const filteredItems = useMemo<IInformationCenterNPC[]>(() => {
    return bestiaryItems.filter(item => {
      // Basic search filter
      const matchesSearch = item.name
        .toLowerCase()
        .includes(searchQuery.toLowerCase());

      // Category filter
      let matchesCategory = true;
      if (selectedBestiaryCategory === 'bosses') {
        matchesCategory = item.isBoss === true;
      } else if (selectedBestiaryCategory === NPCAlignment.Hostile) {
        matchesCategory =
          item.alignment === NPCAlignment.Hostile && !item.isBoss;
      } else if (selectedBestiaryCategory !== 'all') {
        matchesCategory = item.alignment === selectedBestiaryCategory;
      }

      // Advanced filters
      const matchesLevel =
        (!levelRange[0] || item.skills.level >= levelRange[0]) &&
        (!levelRange[1] || item.skills.level <= levelRange[1]);

      const matchesSubtype =
        selectedSubtype === 'all' || item.subType === selectedSubtype;

      const matchesAttackType =
        selectedAttackType === 'all' || item.attackType === selectedAttackType;

      // Filter out friendly NPCs
      const isNotFriendly = item.alignment !== NPCAlignment.Friendly;

      return (
        matchesSearch &&
        matchesCategory &&
        matchesLevel &&
        matchesSubtype &&
        matchesAttackType &&
        isNotFriendly
      );
    });
  }, [
    bestiaryItems,
    searchQuery,
    selectedBestiaryCategory,
    levelRange,
    selectedSubtype,
    selectedAttackType,
  ]);

  const handleSearchChange = (newQuery: string): void => {
    setSearchQuery(newQuery);
    if (newQuery && selectedBestiaryCategory !== 'all') {
      setSelectedBestiaryCategory('all');
    }
  };

  const SearchBarRightElement = (
    <SearchBarActions>
      <BestiaryAdvancedFilters
        isOpen={isAdvancedFiltersOpen}
        onToggle={() => setIsAdvancedFiltersOpen(!isAdvancedFiltersOpen)}
        onLevelRangeChange={setLevelRange}
        onSubtypeChange={setSelectedSubtype}
        onAttackTypeChange={setSelectedAttackType}
        levelRange={levelRange}
        selectedSubtype={selectedSubtype}
        selectedAttackType={selectedAttackType}
      />
    </SearchBarActions>
  );

  return (
    <>
      <PaginatedContent<IInformationCenterNPC>
        items={filteredItems}
        renderItem={renderItem}
        emptyMessage="No monsters found"
        tabId={tabId}
        layout="grid"
        filterOptions={{
          options: bestiaryCategoryOptions,
          selectedOption: selectedBestiaryCategory,
          onOptionChange: setSelectedBestiaryCategory,
        }}
        searchOptions={{
          value: searchQuery,
          onChange: handleSearchChange,
          placeholder: 'Search monsters...',
          rightElement: SearchBarRightElement,
        }}
        dependencies={[
          selectedBestiaryCategory,
          levelRange,
          selectedSubtype,
          selectedAttackType,
        ]}
        itemHeight={isMobile ? '150px' : '180px'}
      />
      {!isMobile && tooltipState && tooltipState.item && (
        <Portal>
          <TooltipWrapper
            width={TOOLTIP_WIDTH}
            style={{
              position: 'fixed',
              left: `${tooltipState.position.x}px`,
              top: `${tooltipState.position.y}px`,
            }}
          >
            <InformationCenterNPCTooltip
              npc={tooltipState.item}
              itemsAtlasJSON={itemsAtlasJSON}
              itemsAtlasIMG={itemsAtlasIMG}
            />
          </TooltipWrapper>
        </Portal>
      )}
      {selectedMonster && (
        <Portal>
          <BaseInformationDetails
            name={selectedMonster.name}
            spriteKey={selectedMonster.key}
            atlasJSON={entitiesAtlasJSON}
            atlasIMG={entitiesAtlasIMG}
            onBack={() => setSelectedMonster(null)}
          >
            <InformationCenterNPCDetails
              npc={selectedMonster}
              itemsAtlasJSON={itemsAtlasJSON}
              itemsAtlasIMG={itemsAtlasIMG}
              iconAtlasIMG={iconsAtlasIMG}
              iconAtlasJSON={iconsAtlasJSON}
              entitiesAtlasJSON={entitiesAtlasJSON}
              entitiesAtlasIMG={entitiesAtlasIMG}
              onBack={() => setSelectedMonster(null)}
            />
          </BaseInformationDetails>
        </Portal>
      )}
    </>
  );
};

const TooltipWrapper = styled.div<{ width: number }>`
  z-index: 1000;
  pointer-events: none;
  width: ${props => `${props.width}px`};
`;

const SearchBarActions = styled.div`
  display: flex;
  align-items: center;
  gap: 0.5rem;
`;
