import type { BackMenu } from '@vben/types';

export const PERMISSION_SWITCH_KEYS = ['standingSwitch', 'orgPositionRoleSwitch', 'orgPermissionSwitch', 'permissionGroupSwitch'] as const;

export type PermissionSwitchKey = (typeof PERMISSION_SWITCH_KEYS)[number];
export type PermissionSwitches = Record<PermissionSwitchKey, number>;

type PositionPermissionSourceSwitches = Partial<Record<'orgPermissionSwitch' | 'orgPositionRoleSwitch', unknown>>;

interface PermissionSourceGroup {
  id: string;
}

export const DEFAULT_PERMISSION_SWITCHES: PermissionSwitches = {
  standingSwitch: 0,
  orgPositionRoleSwitch: 0,
  orgPermissionSwitch: 0,
  permissionGroupSwitch: 0,
};

export function isPermissionSwitchEnabled(value: unknown): boolean {
  return Number(value) === 1;
}

export function normalizePermissionSwitches(
  source: Partial<Record<PermissionSwitchKey, unknown>> = {},
  fallback: PermissionSwitches = DEFAULT_PERMISSION_SWITCHES,
): PermissionSwitches {
  return PERMISSION_SWITCH_KEYS.reduce(
    (result, key) => {
      const value = source[key] ?? fallback[key];
      result[key] = isPermissionSwitchEnabled(value) ? 1 : 0;
      return result;
    },
    { ...DEFAULT_PERMISSION_SWITCHES },
  );
}

export function filterPermissionMenus(menuList: BackMenu[], switches: PermissionSwitches): BackMenu[] {
  const hiddenMenuCodes = new Set<string>();
  if (!isPermissionSwitchEnabled(switches.standingSwitch)) hiddenMenuCodes.add('permission.identity');
  if (!isPermissionSwitchEnabled(switches.permissionGroupSwitch)) hiddenMenuCodes.add('permission.authGroup');

  const filterMenus = (menus: BackMenu[]): BackMenu[] =>
    menus.reduce<BackMenu[]>((result, menu) => {
      if (hiddenMenuCodes.has(menu.enCode)) return result;
      result.push({
        ...menu,
        children: menu.children ? filterMenus(menu.children) : menu.children,
      });
      return result;
    }, []);

  return filterMenus(menuList);
}

export function filterPermissionSourceGroups<T extends PermissionSourceGroup>(groupList: T[], switches: PositionPermissionSourceSwitches): T[] {
  const showPositionSource = isPermissionSwitchEnabled(switches.orgPermissionSwitch) || isPermissionSwitchEnabled(switches.orgPositionRoleSwitch);
  return showPositionSource ? groupList : groupList.filter((group) => group.id !== 'position');
}
