import {
  IInformationCenterNPC,
  NPCAlignment,
  isMobileOrTablet,
} from '@rpg-engine/shared';
import React, { useMemo, useState } from 'react';
import styled from 'styled-components';
import { IOptionsProps } from '../../../Dropdown';
import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
import { Portal } from '../../../shared/Portal/Portal';
import { InformationCenterCell } from '../../InformationCenterCell';
import { formatItemType } from '../items/InformationCenterItemsSection';
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: React.FC<IBestiarySectionProps> = ({
  bestiaryItems,
  itemsAtlasJSON,
  itemsAtlasIMG,
  iconsAtlasIMG,
  iconsAtlasJSON,
  entitiesAtlasJSON,
  entitiesAtlasIMG,
  initialSearchQuery,
  tabId,
}) => {
  const isMobile = isMobileOrTablet();
  const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
  const [tooltipData, setTooltipData] = useState<{
    npc: IInformationCenterNPC;
    position: { x: number; y: number };
  } | null>(null);
  const [
    selectedMonster,
    setSelectedMonster,
  ] = useState<IInformationCenterNPC | null>(null);

  const handleMouseEnter = (
    monster: IInformationCenterNPC,
    event: React.MouseEvent
  ) => {
    if (!isMobile && !selectedMonster) {
      setTooltipData({
        npc: monster,
        position: { x: event.clientX, y: event.clientY },
      });
    }
  };

  const handleMouseLeave = () => {
    if (!isMobile) {
      setTooltipData(null);
    }
  };

  const handleMouseMove = (event: React.MouseEvent) => {
    if (!isMobile && tooltipData) {
      setTooltipData({
        ...tooltipData,
        position: { x: event.clientX, y: event.clientY },
      });
    }
  };

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

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

  const [selectedBestiaryCategory, setSelectedBestiaryCategory] = useState<
    string
  >('all');

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

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

  const filteredItems = useMemo(() => {
    return bestiaryItems.filter(item => {
      const matchesSearch = item.name
        .toLowerCase()
        .includes(searchQuery.toLowerCase());

      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;
      }

      return matchesSearch && matchesCategory;
    });
  }, [bestiaryItems, searchQuery, selectedBestiaryCategory]);

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

  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...',
        }}
        dependencies={[selectedBestiaryCategory]}
        itemHeight="180px"
      />
      {!isMobile && tooltipData && (
        <Portal>
          <TooltipWrapper
            style={{
              position: 'fixed',
              left: tooltipData.position.x + 10,
              top: tooltipData.position.y + 10,
            }}
          >
            <InformationCenterNPCTooltip
              npc={tooltipData.npc}
              itemsAtlasJSON={itemsAtlasJSON}
              itemsAtlasIMG={itemsAtlasIMG}
            />
          </TooltipWrapper>
        </Portal>
      )}
      {selectedMonster && (
        <Portal>
          <InformationCenterNPCDetails
            npc={selectedMonster}
            itemsAtlasJSON={itemsAtlasJSON}
            itemsAtlasIMG={itemsAtlasIMG}
            iconAtlasIMG={iconsAtlasIMG}
            iconAtlasJSON={iconsAtlasJSON}
            entitiesAtlasJSON={entitiesAtlasJSON}
            entitiesAtlasIMG={entitiesAtlasIMG}
            onBack={() => setSelectedMonster(null)}
          />
        </Portal>
      )}
    </>
  );
};

const TooltipWrapper = styled.div`
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  width: 300px;
`;
