import {
  autoUpdate,
  FloatingPortal,
  flip,
  offset,
  shift,
  size,
  useClick,
  useDismiss,
  useFloating,
  useInteractions,
} from '@floating-ui/react';
import { useNavigate } from '@tanstack/react-router';
import clsx from 'clsx';
import { type HTMLProps, useMemo, useState } from 'react';
import { useGatewayWizardStore } from '../../../pages/GatewaySetupPage/useGatewayWizardStore';
import { m } from '../../../paraglide/messages';
import api from '../../api/api';
import type { GatewayInfo } from '../../api/types';
import { Badge } from '../../defguard-ui/components/Badge/Badge';
import type { BadgeVariantValue } from '../../defguard-ui/components/Badge/types';
import { Button } from '../../defguard-ui/components/Button/Button';
import { Divider } from '../../defguard-ui/components/Divider/Divider';
import { Icon } from '../../defguard-ui/components/Icon';
import type { IconKindValue } from '../../defguard-ui/components/Icon/icon-types';
import { InteractionBox } from '../../defguard-ui/components/InteractionBox/InteractionBox';
import { SizedBox } from '../../defguard-ui/components/SizedBox/SizedBox';
import { Snackbar } from '../../defguard-ui/providers/snackbar/snackbar';
import { ThemeSpacing } from '../../defguard-ui/types';
import { openModal } from '../../hooks/modalControls/modalsSubjects';
import { ModalName } from '../../hooks/modalControls/modalTypes';
import './style.scss';

type Status = 'all' | 'none' | 'some';

type Props = {
  data: GatewayInfo[];
  showDetails?: boolean;
};

export const GatewaysStatusBadge = ({ data, showDetails = false }: Props) => {
  const enableOpen = showDetails && data.length > 0;
  const [isOpen, setOpen] = useState(false);
  const { refs, floatingStyles, context } = useFloating({
    placement: 'bottom-start',
    open: isOpen,
    onOpenChange: setOpen,
    middleware: [
      flip(),
      shift(),
      offset(8),
      size({
        apply({ rects, elements }) {
          const refWidth = `${rects.reference.width}px`;
          elements.floating.style.minWidth = refWidth;
        },
      }),
    ],
    whileElementsMounted: autoUpdate,
  });

  const click = useClick(context, { toggle: true, enabled: enableOpen });

  const dismiss = useDismiss(context, {
    ancestorScroll: true,
    escapeKey: true,
    outsidePress: true,
  });

  const { getFloatingProps, getReferenceProps } = useInteractions([click, dismiss]);

  const connectedLength = useMemo(() => data.filter((gw) => gw.connected).length, [data]);

  const status = useMemo((): Status => {
    if (connectedLength === 0 || data.length === 0) {
      return 'none';
    }
    if (connectedLength === data.length) {
      return 'all';
    }
    return 'some';
  }, [data.length, connectedLength]);

  const text = () => {
    switch (status) {
      case 'all':
        return m.gateway_status_all_connected();
      case 'some':
        return m.gateway_status_connected_count({ count: connectedLength });
      case 'none':
        return m.gateway_status_none_connected();
    }
  };

  const icon = (): IconKindValue => {
    switch (status) {
      case 'all':
        return 'status-available';
      case 'some':
        return 'status-attention';
      case 'none':
        return 'status-important';
    }
  };

  const variant = (): BadgeVariantValue => {
    switch (status) {
      case 'all':
        return 'success';
      case 'none':
        return 'critical';
      case 'some':
        return 'warning';
    }
  };

  return (
    <>
      <Badge
        className={clsx('gateways-status-badge', {
          interactive: enableOpen,
        })}
        text={text()}
        icon={icon()}
        variant={variant()}
        showIcon
        ref={refs.setReference}
        {...getReferenceProps()}
      >
        {enableOpen && <Icon icon="arrow-small" rotationDirection="down" size={16} />}
      </Badge>
      {isOpen && (
        <FloatingPortal>
          <FloatingMenu
            ref={refs.setFloating}
            status={data}
            style={{ ...floatingStyles }}
            {...getFloatingProps()}
          />
        </FloatingPortal>
      )}
    </>
  );
};

const FloatingMenu = ({
  status,
  className,
  ...rest
}: { status: GatewayInfo[] } & HTMLProps<HTMLDivElement>) => {
  const locationId = status[0].location_id as number;
  const connected = useMemo(() => status.filter((gw) => gw.connected), [status]);
  const disconnected = useMemo(() => status.filter((gw) => !gw.connected), [status]);
  const navigate = useNavigate();

  return (
    <div className={clsx('gateways-status-floating', className)} {...rest}>
      {connected.length > 0 && (
        <div className="connected">
          <p>{m.gateway_status_connected()}</p>
          <ul>
            {connected.map((gw) => (
              <li key={gw.id}>
                <Badge
                  showIcon
                  removeBackground
                  variant="success"
                  icon="status-attention"
                  text={gw.name}
                />
              </li>
            ))}
          </ul>
        </div>
      )}
      {connected.length > 0 && disconnected.length > 0 && (
        <Divider spacing={ThemeSpacing.Md} />
      )}
      {disconnected.length > 0 && (
        <div className="disconnected">
          <p>{m.gateway_status_disconnected()}</p>
          <ul>
            {disconnected.map((gw) => (
              <li key={gw.id}>
                <Badge
                  removeBackground
                  showIcon
                  icon="status-important"
                  variant="critical"
                  text={gw.name}
                />
                <InteractionBox
                  icon="close"
                  iconSize={20}
                  onClick={() => {
                    const getDeleteModalContent = () => {
                      if (!gw.enabled) {
                        return m.modal_delete_gateway_disabled_body({ name: gw.name });
                      }
                      if (!gw.connected) {
                        return m.modal_delete_gateway_disconnected_body({
                          name: gw.name,
                        });
                      }
                      return m.modal_delete_gateway_body({
                        name: gw.name,
                        locationName: gw.location_name,
                      });
                    };
                    openModal(ModalName.ConfirmAction, {
                      title: m.modal_delete_gateway_title(),
                      contentMd: getDeleteModalContent(),
                      actionPromise: () => api.gateway.deleteGateway(gw.id),
                      invalidateKeys: [['gateway'], ['network']],
                      submitProps: { text: m.controls_delete(), variant: 'critical' },
                      onSuccess: () => Snackbar.default(m.gateway_delete_success()),
                      onError: () => Snackbar.error(m.gateway_delete_failed()),
                    });
                  }}
                />
              </li>
            ))}
          </ul>
        </div>
      )}
      <SizedBox height={ThemeSpacing.Lg} />
      <Button
        iconLeft="network-settings"
        size="big"
        variant="outlined"
        text={m.gateway_add_more()}
        onClick={() => {
          useGatewayWizardStore.getState().start({ network_id: locationId });
          navigate({ to: '/setup-gateway', replace: true });
        }}
      />
    </div>
  );
};
