import React, { RefObject, useCallback, useMemo } from 'react';
import { ContextMenu } from 'primereact/contextmenu';
import { PrimeIcons } from 'primereact/api';
import { MenuItem } from 'primereact/menuitem';
import { CharacterTypeRaw, SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
import classes from './ContextMenuSystemInfo.module.scss';
import { getSystemById } from '@/hooks/Mapper/helpers';
import { useWaypointMenu } from '@/hooks/Mapper/components/contexts/hooks';
import { WaypointSetContextHandler } from '@/hooks/Mapper/components/contexts/types.ts';
import { FastSystemActions } from '@/hooks/Mapper/components/contexts/components';
import { useJumpPlannerMenu } from '@/hooks/Mapper/components/contexts/hooks';
import { Route, RouteStationSummary } from '@/hooks/Mapper/types/routes.ts';
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace.ts';
import { MapAddIcon, MapDeleteIcon } from '@/hooks/Mapper/icons';
import { useRouteProvider } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
import { useGetOwnOnlineCharacters } from '@/hooks/Mapper/components/hooks/useGetOwnOnlineCharacters.ts';
import { sortStationsByDistance } from './sortStationsByDistance.ts';

export interface ContextMenuSystemInfoProps {
  systemStatics: Map<number, SolarSystemStaticInfoRaw>;
  contextMenuRef: RefObject<ContextMenu>;
  systemId: string | undefined;
  systemIdFrom?: string | undefined;
  systems: SolarSystemRawType[];
  onOpenSettings(): void;
  onHubToggle(): void;
  onAddSystem(): void;
  onWaypointSet: WaypointSetContextHandler;
  routes: Route[];
}

export const ContextMenuSystemInfo: React.FC<ContextMenuSystemInfoProps> = ({
  systems,
  systemStatics,
  contextMenuRef,
  onHubToggle,
  onOpenSettings,
  onAddSystem,
  onWaypointSet,
  systemId,
  systemIdFrom,
  routes,
}) => {
  const getWaypointMenu = useWaypointMenu(onWaypointSet);
  const getJumpPlannerMenu = useJumpPlannerMenu(systems, systemIdFrom);
  const { toggleHubCommand, hubs } = useRouteProvider();
  const getOwnOnlineCharacters = useGetOwnOnlineCharacters();

  const getStationWaypointItems = useCallback(
    (destinationId: string, chars: CharacterTypeRaw[]): MenuItem[] => [
      {
        label: 'Set Destination',
        icon: PrimeIcons.SEND,
        command: () => {
          onWaypointSet({
            fromBeginning: true,
            clearWay: true,
            destination: destinationId,
            charIds: chars.map(char => char.eve_id),
          });
        },
      },
      {
        label: 'Add Waypoint',
        icon: PrimeIcons.DIRECTIONS_ALT,
        command: () => {
          onWaypointSet({
            fromBeginning: false,
            clearWay: false,
            destination: destinationId,
            charIds: chars.map(char => char.eve_id),
          });
        },
      },
      {
        label: 'Add Waypoint Front',
        icon: PrimeIcons.DIRECTIONS,
        command: () => {
          onWaypointSet({
            fromBeginning: true,
            clearWay: false,
            destination: destinationId,
            charIds: chars.map(char => char.eve_id),
          });
        },
      },
    ],
    [onWaypointSet],
  );

  const getStationsMenu = useCallback(
    (stations: RouteStationSummary[]) => {
      const chars = getOwnOnlineCharacters().filter(x => x.online);
      const sortedStations = sortStationsByDistance(stations);

      return [
        {
          label: 'Stations',
          icon: PrimeIcons.MAP_MARKER,
          items: sortedStations.map(station => {
            const destinationId = station.station_id.toString();
            const specialClass = station.special ? '[&_.p-menuitem-text]:text-orange-400' : '';

            if (chars.length === 0) {
              return {
                label: station.station_name,
                className: specialClass || undefined,
                items: [{ label: 'No online characters', disabled: true }],
              };
            }

            if (chars.length === 1) {
              return {
                label: station.station_name,
                className: specialClass || undefined,
                items: getStationWaypointItems(destinationId, chars.slice(0, 1)),
              };
            }

            return {
              label: station.station_name,
              className: `${specialClass} w-[500px]`.trim(),
              items: [
                {
                  label: 'All',
                  icon: PrimeIcons.USERS,
                  items: getStationWaypointItems(destinationId, chars),
                },
                ...chars.map(char => ({
                  label: char.name,
                  icon: PrimeIcons.USER,
                  items: getStationWaypointItems(destinationId, [char]),
                })),
              ],
            };
          }),
        },
      ];
    },
    [getOwnOnlineCharacters, getStationWaypointItems],
  );

  const items: MenuItem[] = useMemo(() => {
    const system = systemId ? systemStatics.get(parseInt(systemId)) : undefined;
    const systemOnMap = systemId ? getSystemById(systems, systemId) : undefined;

    if (!systemId || !system) {
      return [];
    }

    const route = routes.find(x => x.destination?.toString() === systemId);
    const stationItems = route?.stations?.length ? getStationsMenu(route.stations) : [];

    return [
      {
        className: classes.FastActions,
        template: () => {
          return (
            <FastSystemActions
              systemId={systemId}
              systemName={system.solar_system_name}
              regionName={system.region_name}
              isWH={isWormholeSpace(system.system_class)}
              onOpenSettings={onOpenSettings}
            />
          );
        },
      },

      { separator: true },
      ...getJumpPlannerMenu(system, routes),
      ...getWaypointMenu(systemId, system.system_class),
      ...stationItems,
      ...(toggleHubCommand
        ? [
            {
              label: !hubs.includes(systemId) ? 'Add Route' : 'Remove Route',
              icon: !hubs.includes(systemId) ? (
                <MapAddIcon className="mr-1 relative left-[-2px]" />
              ) : (
                <MapDeleteIcon className="mr-1 relative left-[-2px]" />
              ),
              command: onHubToggle,
            },
          ]
        : []),
      ...(!systemOnMap
        ? [
            {
              label: 'Add to map',
              icon: PrimeIcons.PLUS,
              command: onAddSystem,
            },
          ]
        : []),
    ];
  }, [
    systemId,
    systemStatics,
    systems,
    getJumpPlannerMenu,
    getWaypointMenu,
    getStationsMenu,
    hubs,
    onHubToggle,
    onAddSystem,
    onOpenSettings,
    toggleHubCommand,
    routes,
  ]);

  return (
    <>
      <ContextMenu className={classes.ContextMenu} model={items} ref={contextMenuRef} breakpoint="767px" />
    </>
  );
};
