import {
  type ButtonProps,
  Flex,
  Menu,
  MenuList,
  Box,
  Radio,
  useOutsideClick,
  HStack,
  MenuButton,
  Checkbox
} from '@chakra-ui/react';
import React, { useMemo, useRef, useState } from 'react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { type PermissionValueType } from '@fastgpt/global/support/permission/type';
import { useContextSelector } from 'use-context-selector';
import { Permission } from '@fastgpt/global/support/permission/controller';
import { CollaboratorContext } from './context';
import { useTranslation } from 'next-i18next';
import MyDivider from '@fastgpt/web/components/common/MyDivider';

export type PermissionSelectProps = {
  value?: PermissionValueType;
  onChange: (value: PermissionValueType) => void;
  trigger?: 'hover' | 'click';
  offset?: [number, number];
  Button: React.ReactNode;

  onDelete?: () => void;
} & Omit<ButtonProps, 'onChange' | 'value'>;

const MenuStyle = {
  py: 2,
  px: 3,
  _hover: {
    bg: 'myGray.50'
  },
  borderRadius: 'md',
  cursor: 'pointer',
  fontSize: 'sm'
};

function PermissionSelect({
  value,
  onChange,
  trigger = 'click',
  offset = [0, 5],
  Button,
  width = 'auto',
  onDelete
}: PermissionSelectProps) {
  const { t } = useTranslation();
  const ref = useRef<HTMLButtonElement>(null);
  const closeTimer = useRef<NodeJS.Timeout>();

  const { permission, permissionList } = useContextSelector(CollaboratorContext, (v) => v);

  const [isOpen, setIsOpen] = useState(false);

  const permissionSelectList = useMemo(() => {
    if (!permissionList) return { singleCheckBoxList: [], multipleCheckBoxList: [] };

    const list = Object.entries(permissionList).map(([_, value]) => {
      return {
        name: value.name,
        value: value.value,
        description: value.description,
        checkBoxType: value.checkBoxType
      };
    });

    return {
      singleCheckBoxList: list
        .filter((item) => item.checkBoxType === 'single')
        .filter((item) => {
          if (permission.isOwner) return true;
          if (item.value === permissionList['manage'].value) return false;
          return true;
        }),
      multipleCheckBoxList: list.filter((item) => item.checkBoxType === 'multiple')
    };
  }, [permission.isOwner, permissionList]);
  const selectedSingleValue = useMemo(() => {
    if (!permissionList) return undefined;

    const per = new Permission({ per: value, permissionList });

    if (per.hasManagePer) return permissionList['manage'].value;
    if (per.hasWritePer) return permissionList['write'].value;

    return permissionList['read'].value;
  }, [permissionList, value]);
  const selectedMultipleValues = useMemo(() => {
    const per = new Permission({ per: value, permissionList });

    return permissionSelectList.multipleCheckBoxList
      .filter((item) => {
        return per.checkPer(item.value);
      })
      .map((item) => item.value);
  }, [permissionList, permissionSelectList.multipleCheckBoxList, value]);

  const onSelectPer = (perValue: PermissionValueType) => {
    if (perValue === value) return;
    const per = new Permission({ per: perValue, permissionList });
    per.addPer(...selectedMultipleValues);
    onChange(per.value);
  };

  useOutsideClick({
    ref: ref,
    handler: () => {
      setIsOpen(false);
    }
  });

  return selectedSingleValue !== undefined ? (
    <Menu offset={offset} isOpen={isOpen} autoSelect={false} direction={'ltr'}>
      <Box
        w="fit-content"
        onMouseEnter={() => {
          if (trigger === 'hover') {
            setIsOpen(true);
          }
          clearTimeout(closeTimer.current);
        }}
        onMouseLeave={() => {
          if (trigger === 'hover') {
            closeTimer.current = setTimeout(() => {
              setIsOpen(false);
            }, 100);
          }
        }}
      >
        <MenuButton
          ref={ref}
          position={'relative'}
          onClickCapture={() => {
            if (trigger === 'click') {
              setIsOpen(!isOpen);
            }
          }}
        >
          {Button}
        </MenuButton>
        <MenuList
          minW={isOpen ? `${width}px !important` : 0}
          p="3"
          border={'1px solid #fff'}
          boxShadow={
            '0px 2px 4px rgba(161, 167, 179, 0.25), 0px 0px 1px rgba(121, 141, 159, 0.25);'
          }
          zIndex={99}
          overflowY={'auto'}
          whiteSpace={'pre-wrap'}
        >
          {/* The list of single select permissions */}
          {permissionSelectList.singleCheckBoxList.map((item) => {
            const change = () => {
              const per = new Permission({ per: value, permissionList });
              per.removePer(selectedSingleValue);
              per.addPer(item.value);
              onSelectPer(per.value);
            };

            return (
              <Flex
                key={item.value}
                {...(selectedSingleValue === item.value
                  ? {
                      color: 'primary.600'
                    }
                  : {})}
                {...MenuStyle}
                onClick={change}
                maxW={['70vw', '260px']}
              >
                <Radio isChecked={selectedSingleValue === item.value} />
                <Box ml={4}>
                  <Box>{t(item.name as any)}</Box>
                  <Box color={'myGray.500'} fontSize={'mini'}>
                    {t(item.description as any)}
                  </Box>
                </Box>
              </Flex>
            );
          })}

          {permissionSelectList.multipleCheckBoxList.length > 0 && (
            <>
              <MyDivider my={2} />
              {permissionSelectList.multipleCheckBoxList.map((item) => {
                const isChecked = selectedMultipleValues.includes(item.value);
                const isDisabled = new Permission({
                  per: selectedSingleValue,
                  permissionList
                }).checkPer(item.value);
                const change = () => {
                  if (isDisabled) return;
                  const per = new Permission({ per: value, permissionList });
                  if (isChecked) {
                    per.removePer(item.value);
                  } else {
                    per.addPer(item.value);
                  }
                  onChange(per.value);
                };
                return (
                  <Flex
                    key={item.value}
                    {...(isChecked
                      ? {
                          color: 'primary.600'
                        }
                      : {})}
                    {...MenuStyle}
                    maxW={['70vw', '260px']}
                    {...(isDisabled
                      ? {
                          cursor: 'not-allowed'
                        }
                      : {
                          cursor: 'pointer'
                        })}
                    onClick={change}
                  >
                    <Checkbox
                      size="lg"
                      isChecked={isChecked}
                      // onChange={(e) => {
                      //   e.stopPropagation();
                      //   e.preventDefault();
                      // }}
                      isDisabled={isDisabled}
                    />
                    <Box ml={4}>
                      <Box>{t(item.name as any)}</Box>
                      <Box color={'myGray.500'} fontSize={'mini'}>
                        {t(item.description as any)}
                      </Box>
                    </Box>
                  </Flex>
                );
              })}
            </>
          )}

          {onDelete && (
            <>
              <MyDivider my={2} h={'2px'} borderColor={'myGray.200'} />
              <HStack
                {...MenuStyle}
                onClick={() => {
                  onDelete();
                  setIsOpen(false);
                }}
              >
                <MyIcon name="delete" w="20px" color="red.600" />
                <Box color="red.600">{t('common:Remove')}</Box>
              </HStack>
            </>
          )}
        </MenuList>
      </Box>
    </Menu>
  ) : null;
}

export default React.memo(PermissionSelect);
