import { useState } from 'react';
import { FormProvider, useForm, useFormContext } from 'react-hook-form';

import { Handle, Position } from '@xyflow/react';
import {
  IconArrowsSplit2,
  IconBolt,
  IconCheck,
  IconClipboardCheck,
  IconClipboardList,
  IconKeyframeAlignVertical,
  IconReplace,
  IconUserEdit,
  IconX,
  type TablerIcon,
} from '@material-hu/icons/tabler';
import { Box, Stack } from '@material-hu/mui';
import { createHuGoTheme } from '@material-hu/theme/hugo';

import HuMenuList from '@material-hu/components/composed-components/MenuList';
import HuAvatar from '@material-hu/components/design-system/Avatar';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuFormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import HuPills from '@material-hu/components/design-system/Pills';
import HuTitle from '@material-hu/components/design-system/Title';

import { type FlowNode, NodeType } from 'src/types/workflows';
import { insertIf } from 'src/utils/arrayUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { type InvalidNodeInfo } from '../utils';

const getProps = (
  type: NodeType,
): {
  Icon: TablerIcon;
  color: 'primary' | 'warning' | 'highlight' | 'error' | 'success' | 'default';
} => {
  switch (type) {
    case NodeType.TRIGGER:
      return {
        Icon: IconBolt,
        color: 'success',
      };
    case NodeType.CONDITIONAL:
      return {
        Icon: IconArrowsSplit2,
        color: 'warning',
      };
    case NodeType.NEW:
      return {
        Icon: IconKeyframeAlignVertical,
        color: 'default',
      };
    case NodeType.CHANGE_STATE:
      return {
        Icon: IconReplace,
        color: 'highlight',
      };
    case NodeType.CHANGE_ASSIGNEE:
      return {
        Icon: IconUserEdit,
        color: 'highlight',
      };
    case NodeType.APPROVAL:
      return {
        Icon: IconClipboardCheck,
        color: 'highlight',
      };
    case NodeType.TASK:
    default:
      return {
        Icon: IconClipboardList,
        color: 'highlight',
      };
  }
};

type Props = {
  deleteNode: (nodeId: string) => void;
  updateNodeName: (nodeId: string, newName: string) => void;
  showChangeStatusDrawer: (node?: FlowNode) => void;
  showChangeAssigneeDrawer: (node?: FlowNode) => void;
  showBranchesDrawer: (node?: FlowNode) => void;
  showApprovalDrawer: (node?: FlowNode) => void;
  showTaskDrawer: (node?: FlowNode) => void;
  showSetTriggerDrawer: () => void;
  invalidNodes: InvalidNodeInfo[];
  data: {
    type: string;
    title: string;
    overlap: boolean;
  };
  id: string;
};

const CustomNode = ({
  showChangeStatusDrawer,
  showChangeAssigneeDrawer,
  showBranchesDrawer,
  showApprovalDrawer,
  showTaskDrawer,
  showSetTriggerDrawer,
  deleteNode,
  updateNodeName,
  data,
  invalidNodes,
  id,
}: Props) => {
  const { t } = useLokaliseTranslation('workflows');
  const { type, title, overlap } = data;
  const { palette } = createHuGoTheme();
  const { Icon, color } = getProps(type as NodeType);
  const [renaming, setRenaming] = useState(false);
  const [showMenu, setShowMenu] = useState(false);
  const [isMenuOpen, setIsMenuOpen] = useState(false);

  const isEnd = type === NodeType.END;
  const isTrigger = type === NodeType.TRIGGER;
  const isNew = type === NodeType.NEW;
  const isInvalid = invalidNodes?.some(node => node.id === id);

  const getBorder = () => {
    if (overlap) return '2px solid #D6D6DF';
    if (isNew) return `2px solid ${palette.ilustrations?.primaryIlus}`;
    return '1px solid #E0E0E0';
  };

  const form = useFormContext();
  const { trigger, body } = form.watch();
  const isUnsetTrigger = isTrigger && !trigger;

  const node =
    body?.tasks?.find((task: FlowNode) => task.id === id) ||
    body?.conditionals?.find((conditional: FlowNode) => conditional.id === id);

  const handleNodeClick = () => {
    if (overlap) return;
    if (isTrigger) {
      showSetTriggerDrawer();
      return;
    }
    switch (type) {
      case NodeType.CHANGE_ASSIGNEE:
        showChangeAssigneeDrawer(node);
        break;
      case NodeType.CONDITIONAL:
        showBranchesDrawer(node);
        break;
      case NodeType.APPROVAL:
        showApprovalDrawer(node);
        break;
      case NodeType.TASK:
        showTaskDrawer(node);
        break;
      default:
        showChangeStatusDrawer(node);
        break;
    }
  };

  const menuOptions = [
    {
      title: t('edit'),
      onClick: handleNodeClick,
    },
    ...insertIf(!isTrigger, {
      title: t('rename'),
      onClick: () => {
        renameForm.reset({ title: node?.name || title });
        setRenaming(true);
      },
    }),
    ...insertIf(!isTrigger, {
      title: t('delete'),
      onClick: () => deleteNode(id),
    }),
  ];

  const renameForm = useForm({
    defaultValues: {
      title: node?.name || title,
    },
  });

  const showMenuButton = !overlap && !isUnsetTrigger && !isNew;
  const handleRename = (save = true) => {
    if (save) {
      updateNodeName(id, renameForm.getValues('title'));
    } else {
      renameForm.reset({
        title: node?.name || title,
      });
    }
    setRenaming(false);
  };

  return (
    <>
      {isEnd && (
        <>
          <Handle
            type="target"
            position={Position.Top}
            style={{
              backgroundColor: 'transparent',
              borderColor: 'transparent',
            }}
          />
          <HuPills
            label={t('end')}
            hasIcon={false}
            type={overlap ? 'warning' : 'disabled'}
            sx={{ width: 128 }}
          />
        </>
      )}
      {!isEnd && (
        <>
          {!isTrigger && (
            <Handle
              type="target"
              position={Position.Top}
              style={{
                backgroundColor: 'transparent',
                borderColor: 'transparent',
              }}
            />
          )}
          <Box
            onClick={() => !renaming && handleNodeClick()}
            onMouseEnter={() => showMenuButton && setShowMenu(true)}
            onMouseLeave={() => !isMenuOpen && setShowMenu(false)}
          >
            <HuCardContainer
              sx={{
                width: 328,
                height: '100%',
                backgroundColor: th =>
                  overlap
                    ? th.palette.new.background.layout.default
                    : th.palette.new.background.layout.tertiary,
                borderColor: 'transparent',
                outline: getBorder(),
                ':hover': {
                  outline: th =>
                    `2px solid ${th.palette.new.border.neutral.brand}`,
                },
              }}
              noHover
              {...(isInvalid && {
                badge: {
                  label: t('pending_configuration'),
                  type: 'warning',
                },
              })}
            >
              <Stack
                sx={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  justifyContent: 'space-between',
                  cursor: !overlap ? 'pointer' : 'grab',
                  '&:active': { cursor: 'grabbing' },
                }}
              >
                <Stack
                  sx={{
                    flexDirection: 'row',
                    alignItems: 'center',
                    gap: 1.5,
                    minWidth: 0,
                  }}
                >
                  <HuAvatar
                    variant="square"
                    color={overlap ? 'default' : color}
                    Icon={Icon}
                  />
                  {!isTrigger && !renaming && (
                    <HuTitle
                      variant="M"
                      withEllipsis
                      title={title}
                      description={isNew && t('new_description')}
                      disabled={overlap}
                      sx={{ flex: 1, minWidth: 0, wordBreak: 'break-word' }}
                    />
                  )}
                  {!isTrigger && renaming && (
                    <Stack
                      sx={{
                        flexDirection: 'row',
                        alignItems: 'center',
                        justifyContent: 'space-between',
                        gap: 1,
                      }}
                    >
                      <Box
                        sx={{ flex: 1 }}
                        className="nodrag"
                        onClick={e => e.stopPropagation()}
                      >
                        <FormProvider {...renameForm}>
                          <HuFormInputClassic
                            name="title"
                            inputProps={{
                              sx: {
                                py: 0,
                                minHeight: 0,
                                height: 36,
                              },
                              maxLength: 35,
                              hasCounter: false,
                              showClear: false,
                              autoFocus: true,
                              onKeyDown: e => {
                                if (e.key === 'Enter') {
                                  handleRename();
                                }
                                if (e.key === 'Escape') {
                                  setRenaming(false);
                                }
                              },
                              onBlur: () => {
                                setTimeout(() => {
                                  setRenaming(false);
                                }, 200);
                              },
                            }}
                          />
                        </FormProvider>
                      </Box>
                      <Stack
                        sx={{
                          flexDirection: 'row',
                          alignItems: 'center',
                          gap: 1,
                        }}
                      >
                        <Button
                          variant="secondary"
                          sx={{
                            minWidth: 0,
                            px: 0.5,
                            height: 24,
                          }}
                          onClick={e => {
                            e.stopPropagation();
                            handleRename(false);
                          }}
                        >
                          <IconX
                            size={16}
                            style={{
                              margin: 0,
                              padding: 0,
                            }}
                          />
                        </Button>
                        <Button
                          variant="primary"
                          sx={{
                            minWidth: 0,
                            px: 0.5,
                            height: 24,
                          }}
                          onClick={e => {
                            e.stopPropagation();
                            handleRename();
                          }}
                        >
                          <IconCheck size={16} />
                        </Button>
                      </Stack>
                    </Stack>
                  )}
                  {isTrigger && (
                    <HuTitle
                      variant="M"
                      withEllipsis
                      title={trigger?.label || t('trigger')}
                      disabled={overlap}
                      sx={{ flex: 1, minWidth: 0, wordBreak: 'break-word' }}
                    />
                  )}
                </Stack>
                {isUnsetTrigger && (
                  <Box onClick={e => e.stopPropagation()}>
                    <Button
                      variant="contained"
                      onClick={() => showSetTriggerDrawer()}
                      sx={{ ml: 1 }}
                    >
                      {t('add')}
                    </Button>
                  </Box>
                )}
                {showMenu && showMenuButton && !renaming && (
                  <HuMenuList
                    options={menuOptions}
                    position="right"
                    minWidth="120px"
                    onClose={() => {
                      setShowMenu(false);
                      setIsMenuOpen(false);
                    }}
                    onClick={() => setIsMenuOpen(true)}
                  />
                )}
              </Stack>
            </HuCardContainer>
          </Box>
          <Handle
            type="source"
            position={Position.Bottom}
            style={{
              backgroundColor: 'transparent',
              borderColor: 'transparent',
            }}
            id="handler"
          />
        </>
      )}
    </>
  );
};

export default CustomNode;
