// @ts-strict-ignore
import React, { useRef } from 'react';
import type { CSSProperties, RefCallback } from 'react';
import { useTranslation } from 'react-i18next';

import { Button } from '@actual-app/components/button';
import { SvgAdd, SvgExpandArrow } from '@actual-app/components/icons/v0';
import { SvgCheveronDown } from '@actual-app/components/icons/v1';
import { Menu } from '@actual-app/components/menu';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import type {
  CategoryEntity,
  CategoryGroupEntity,
} from '@actual-app/core/types/models';
import { css, cx } from '@emotion/css';

import { NotesButton } from '#components/NotesButton';
import { InputCell } from '#components/table';
import { useContextMenu } from '#hooks/useContextMenu';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
import { useGlobalPref } from '#hooks/useGlobalPref';

type SidebarGroupProps = {
  group: CategoryGroupEntity;
  editing?: boolean;
  collapsed: boolean;
  dragPreview?: boolean;
  innerRef?: RefCallback<HTMLDivElement>;
  style?: CSSProperties;
  onEdit?: (id: CategoryGroupEntity['id']) => void;
  onSave?: (group: CategoryGroupEntity) => void;
  onDelete?: (id: CategoryGroupEntity['id']) => void;
  onApplyBudgetTemplatesInGroup?: (
    categories: Array<CategoryEntity['id']>,
  ) => void;
  onSortCategories?: (
    groupId: CategoryGroupEntity['id'],
    direction: 'asc' | 'desc',
  ) => void;
  onShowNewCategory?: (groupId: CategoryGroupEntity['id']) => void;
  onHideNewGroup?: () => void;
  onToggleCollapse?: (id: CategoryGroupEntity['id']) => void;
};

export function SidebarGroup({
  group,
  editing,
  collapsed,
  dragPreview,
  innerRef,
  style,
  onEdit,
  onSave,
  onDelete,
  onApplyBudgetTemplatesInGroup,
  onSortCategories,
  onShowNewCategory,
  onHideNewGroup,
  onToggleCollapse,
}: SidebarGroupProps) {
  const { t } = useTranslation();
  const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
  const [categoryExpandedStatePref] = useGlobalPref('categoryExpandedState');
  const categoryExpandedState = categoryExpandedStatePref ?? 0;

  const temporary = group.id === 'new';
  const canSortCategories =
    !!onSortCategories && (group.categories?.length ?? 0) > 1;
  const triggerRef = useRef(null);
  const { handleContextMenu } = useContextMenu({
    triggerRef,
    items: [
      onEdit && {
        name: 'rename',
        text: t('Rename'),
        onClick: () => onEdit(group.id),
      },
      onSave && {
        name: 'toggle-visibility',
        text: group.hidden ? t('Show') : t('Hide'),
        onClick: () => onSave({ ...group, hidden: !group.hidden }),
        hidden: group.is_income,
      },
      onDelete && {
        name: 'delete',
        text: t('Delete'),
        onClick: () => onDelete(group.id),
      },
      canSortCategories && Menu.line,
      canSortCategories && {
        name: 'sort-asc',
        text: t('Sort A to Z'),
        onClick: () => onSortCategories(group.id, 'asc'),
      },
      canSortCategories && {
        name: 'sort-desc',
        text: t('Sort Z to A'),
        onClick: () => onSortCategories(group.id, 'desc'),
      },
      isGoalTemplatesEnabled &&
        onApplyBudgetTemplatesInGroup && {
          name: 'apply-multiple-category-template',
          text: t('Overwrite with templates'),
          onClick: () =>
            onApplyBudgetTemplatesInGroup(
              group.categories.filter(c => !c.hidden).map(c => c.id),
            ),
        },
    ],
  });

  const displayed = (
    <View
      style={{
        flexDirection: 'row',
        alignItems: 'center',
        userSelect: 'none',
        WebkitUserSelect: 'none',
        height: 20,
      }}
      ref={triggerRef}
      onClick={() => {
        onToggleCollapse(group.id);
      }}
    >
      {!dragPreview && (
        <SvgExpandArrow
          width={8}
          height={8}
          style={{
            marginRight: 5,
            marginLeft: 5,
            flexShrink: 0,
            transition: 'transform .1s',
            transform: collapsed ? 'rotate(-90deg)' : '',
          }}
        />
      )}
      <div
        style={{
          textOverflow: 'ellipsis',
          whiteSpace: 'nowrap',
          overflow: 'hidden',
          minWidth: 0,
        }}
      >
        {dragPreview && <Text style={{ fontWeight: 500 }}>Group: </Text>}
        {group.name}
      </div>
      {!dragPreview && (
        <>
          <View style={{ marginLeft: 5, flexShrink: 0 }}>
            <Button
              variant="bare"
              className="hover-visible"
              style={{ padding: 3 }}
              onPress={handleContextMenu}
            >
              <SvgCheveronDown width={14} height={14} />
            </Button>
          </View>
          <View style={{ flex: 1 }} />
          <View
            style={{
              flexShrink: 0,
              flexDirection: 'row',
              alignItems: 'center',
            }}
          >
            <Tooltip content={t('Add category')} disablePointerEvents>
              <Button
                variant="bare"
                aria-label={t('Add category')}
                className={cx(
                  css({
                    color: theme.pageTextLight,
                  }),
                  'hover-visible',
                )}
                onPress={() => {
                  onShowNewCategory?.(group.id);
                }}
              >
                <SvgAdd style={{ width: 10, height: 10, flexShrink: 0 }} />
              </Button>
            </Tooltip>

            <NotesButton id={group.id} defaultColor={theme.pageTextLight} />
          </View>
        </>
      )}
    </View>
  );

  return (
    <View
      innerRef={innerRef}
      style={{
        ...style,
        width: 200 + 100 * categoryExpandedState,
        backgroundColor: theme.budgetHeaderCurrentMonth,
        overflow: 'hidden',
        '& .hover-visible': {
          display: 'none',
        },
        ...(!dragPreview && {
          '&:hover .hover-visible': {
            display: 'flex',
          },
        }),
        ...(dragPreview && {
          paddingLeft: 10,
          zIndex: 10000,
          borderRadius: 6,
          overflow: 'hidden',
        }),
      }}
      onKeyDown={e => {
        if (e.key === 'Enter') {
          onEdit(null);
          e.stopPropagation();
        }
      }}
    >
      <InputCell
        value={group.name}
        formatter={() => displayed}
        width="flex"
        exposed={editing}
        onUpdate={value => {
          if (temporary) {
            if (value === '') {
              onHideNewGroup();
            } else if (value !== '') {
              onSave({ id: group.id, name: value });
            }
          } else {
            onSave({ id: group.id, name: value });
          }
        }}
        onBlur={() => onEdit(null)}
        style={{ fontWeight: 600 }}
        inputProps={{
          style: { marginLeft: 20 },
          placeholder: temporary ? t('New group name') : '',
        }}
      />
    </View>
  );
}
