import { Widget } from '@/hooks/Mapper/components/mapInterface/components';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import {
  LayoutEventBlocker,
  LoadingWrapper,
  SystemViewStandalone,
  TooltipPosition,
  WdCheckbox,
  WdImgButton,
} from '@/hooks/Mapper/components/ui-kit';
import { useLoadSystemStatic } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
import { forwardRef, MouseEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { getSystemById } from '@/hooks/Mapper/helpers/getSystemById.ts';
import classes from './RoutesWidget.module.scss';
import { useLoadRoutes } from './hooks';
import { RoutesList } from './RoutesList';
import clsx from 'clsx';
import { Route } from '@/hooks/Mapper/types/routes.ts';
import { PrimeIcons } from 'primereact/api';
import { RoutesSettingsDialog } from './RoutesSettingsDialog';
import { RoutesProvider, useRouteProvider } from './RoutesProvider.tsx';
import { ContextMenuSystemInfo, useContextMenuSystemInfoHandlers } from '@/hooks/Mapper/components/contexts';
import useMaxWidth from '@/hooks/Mapper/hooks/useMaxWidth.ts';
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
import {
  AddSystemDialog,
  SearchOnSubmitCallback,
} from '@/hooks/Mapper/components/mapInterface/components/AddSystemDialog';
import {
  RoutesImperativeHandle,
  RoutesWidgetProps,
} from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/types.ts';

const sortByDist = (a: Route, b: Route) => {
  const distA = a.has_connection ? a.systems?.length || 0 : Infinity;
  const distB = b.has_connection ? b.systems?.length || 0 : Infinity;

  return distA - distB;
};

export const RoutesWidgetContent = () => {
  const {
    data: { selectedSystems, systems, isSubscriptionActive },
  } = useMapRootState();
  const { hubs = [], routesList, isRestricted } = useRouteProvider();

  const [systemId] = selectedSystems;

  const { loading } = useLoadRoutes();

  const { systems: systemStatics, loadSystems, lastUpdateKey } = useLoadSystemStatic({ systems: hubs ?? [] });
  const { open, ...systemCtxProps } = useContextMenuSystemInfoHandlers();

  const preparedHubs = useMemo(() => {
    return hubs.map(x => {
      const sys = getSystemById(systems, x.toString());

      return { ...systemStatics.get(parseInt(x))!, ...(sys && { customName: sys.name ?? '' }) };
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [hubs, systems, systemStatics, lastUpdateKey]);

  const preparedRoutes: Route[] = useMemo(() => {
    return (
      routesList?.routes
        .sort(sortByDist)
        // .filter(x => x.destination.toString() !== systemId)
        .map(route => ({
          ...route,
          mapped_systems:
            route.systems?.map(solar_system_id =>
              routesList?.systems_static_data.find(
                system_static_data => system_static_data.solar_system_id === solar_system_id,
              ),
            ) ?? [],
        })) ?? []
    );
  }, [routesList?.routes, routesList?.systems_static_data, systemId]);

  const refData = useRef({ open, loadSystems, preparedRoutes });
  refData.current = { open, loadSystems, preparedRoutes };

  useEffect(() => {
    (async () => await refData.current.loadSystems(hubs))();
  }, [hubs]);

  const handleClick = useCallback((e: MouseEvent, systemId: string) => {
    const route = refData.current.preparedRoutes.find(x => x.destination.toString() === systemId);

    refData.current.open(e, systemId, route?.mapped_systems ?? []);
  }, []);

  const handleContextMenu = useCallback(
    async (e: MouseEvent, systemId: string) => {
      await refData.current.loadSystems([systemId]);
      handleClick(e, systemId);
    },
    [handleClick],
  );

  if (isRestricted && !isSubscriptionActive) {
    return (
      <div className="w-full h-full flex items-center justify-center">
        <span className="select-none text-center text-stone-400/80 text-sm">
          User Routes available with &#39;Active&#39; map subscription only (contact map administrators)
        </span>
      </div>
    );
  }

  if (!systemId) {
    return (
      <div className="w-full h-full flex justify-center items-center select-none text-center text-stone-400/80 text-sm">
        System is not selected
      </div>
    );
  }

  if (hubs.length === 0) {
    return <div className="w-full h-full flex justify-center items-center select-none">Routes not set</div>;
  }

  return (
    <>
      <LoadingWrapper loading={loading}>
        <div className={clsx(classes.RoutesGrid, 'px-2 py-2')}>
          {preparedRoutes.map(route => {
            const sys = preparedHubs.find(x => x.solar_system_id === route.destination)!;

            // TODO do not delte this console log
            // eslint-disable-next-line no-console
            // console.log('JOipP', `Check sys [${route.destination}]:`, sys);

            return (
              <>
                <div className="flex gap-2 items-center">
                  <WdImgButton
                    className={clsx(PrimeIcons.BARS, classes.RemoveBtn)}
                    onClick={e => handleClick(e, route.destination.toString())}
                    tooltip={{
                      content: 'Click here to open system menu',
                      position: TooltipPosition.top,
                      offset: 10,
                    }}
                  />

                  <SystemViewStandalone
                    key={route.destination}
                    className={clsx('select-none text-center cursor-context-menu')}
                    hideRegion
                    compact
                    {...sys}
                  />
                </div>
                <div className="text-right pl-1">{route.has_connection ? route.systems?.length ?? 2 : ''}</div>
                <div className="pl-2 pb-0.5">
                  <RoutesList data={route} onContextMenu={handleContextMenu} />
                </div>
              </>
            );
          })}
        </div>
      </LoadingWrapper>

      <ContextMenuSystemInfo
        hubs={hubs}
        routes={preparedRoutes}
        systems={systems}
        systemStatics={systemStatics}
        systemIdFrom={systemId}
        {...systemCtxProps}
      />
    </>
  );
};

type RoutesWidgetCompProps = {
  title: ReactNode | string;
};

export const RoutesWidgetComp = ({ title }: RoutesWidgetCompProps) => {
  const [routeSettingsVisible, setRouteSettingsVisible] = useState(false);
  const { data, update, addHubCommand } = useRouteProvider();

  const isSecure = data.path_type === 'secure';
  const handleSecureChange = useCallback(() => {
    update({
      ...data,
      path_type: data.path_type === 'secure' ? 'shortest' : 'secure',
    });
  }, [data, update]);

  const ref = useRef<HTMLDivElement>(null);
  const compact = useMaxWidth(ref, 170);
  const [openAddSystem, setOpenAddSystem] = useState<boolean>(false);

  const onAddSystem = useCallback(() => setOpenAddSystem(true), []);

  const handleSubmitAddSystem: SearchOnSubmitCallback = useCallback(
    async item => addHubCommand(item.value.toString()),
    [addHubCommand],
  );

  return (
    <Widget
      label={
        <div className="flex justify-between items-center text-xs w-full" ref={ref}>
          <span className="select-none">{title}</span>
          <LayoutEventBlocker className="flex items-center gap-2">
            <WdImgButton
              className={PrimeIcons.PLUS_CIRCLE}
              onClick={onAddSystem}
              tooltip={{
                content: 'Click here to add new system to routes',
              }}
            />

            <WdTooltipWrapper content="Show shortest route" position={TooltipPosition.top}>
              <WdCheckbox
                size="xs"
                labelSide="left"
                label={compact ? '' : 'Show shortest'}
                value={!isSecure}
                onChange={handleSecureChange}
                classNameLabel="text-red-400 whitespace-nowrap"
              />
            </WdTooltipWrapper>
            <WdImgButton
              className={PrimeIcons.SLIDERS_H}
              onClick={() => setRouteSettingsVisible(true)}
              tooltip={{
                position: TooltipPosition.top,
                content: 'Click here to open Routes settings',
              }}
            />
          </LayoutEventBlocker>
        </div>
      }
    >
      <RoutesWidgetContent />
      <RoutesSettingsDialog visible={routeSettingsVisible} setVisible={setRouteSettingsVisible} />

      <AddSystemDialog
        title="Add system to routes"
        visible={openAddSystem}
        setVisible={() => setOpenAddSystem(false)}
        onSubmit={handleSubmitAddSystem}
      />
    </Widget>
  );
};

export const RoutesWidget = forwardRef<RoutesImperativeHandle, RoutesWidgetProps & RoutesWidgetCompProps>(
  ({ title, ...props }, ref) => {
    return (
      <RoutesProvider {...props} ref={ref}>
        <RoutesWidgetComp title={title} />
      </RoutesProvider>
    );
  },
);
RoutesWidget.displayName = 'RoutesWidget';
