import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import * as roleResourceTree from '../src/views/system/role/modules/role-resource-tree';

type MenuNode = {
  id: string;
  children?: MenuNode[];
};

type NormalizeRoleMenuCheckedIds = (input: { menuTree: MenuNode[]; checkedIds: string[] }) => string[];

const menuTree: MenuNode[] = [
  {
    id: 'personal',
    children: [
      {
        id: 'weekly',
        children: [{ id: 'weeklyDetail' }]
      },
      {
        id: 'monthly',
        children: [{ id: 'monthlyDetail' }]
      }
    ]
  },
  {
    id: 'infra',
    children: [{ id: 'stateMachine' }, { id: 'cmd' }]
  }
];

const normalizeRoleMenuCheckedIds = (roleResourceTree as { normalizeRoleMenuCheckedIds?: NormalizeRoleMenuCheckedIds })
  .normalizeRoleMenuCheckedIds;

const { resolveRoleMenuSubmitIds } = roleResourceTree;

describe('resolveRoleMenuSubmitIds', () => {
  it('keeps original ids when there is no user interaction', () => {
    const result = resolveRoleMenuSubmitIds({
      menuTree,
      baselineIds: ['weekly', 'monthly'],
      dirtyIds: [],
      checkedIds: ['personal', 'weekly', 'monthly']
    });

    assert.deepEqual(result, ['weekly', 'monthly']);
  });

  it('preserves untouched branches when another branch changes', () => {
    const result = resolveRoleMenuSubmitIds({
      menuTree,
      baselineIds: ['weekly', 'monthly'],
      dirtyIds: ['stateMachine'],
      checkedIds: ['personal', 'weekly', 'monthly', 'stateMachine']
    });

    assert.deepEqual(result, ['weekly', 'monthly', 'stateMachine']);
  });

  it('recomputes the whole dirty branch instead of expanding unrelated baseline ids', () => {
    const result = resolveRoleMenuSubmitIds({
      menuTree,
      baselineIds: ['personal'],
      dirtyIds: ['weekly'],
      checkedIds: ['personal', 'weekly', 'weeklyDetail']
    });

    assert.deepEqual(result, ['personal', 'weekly', 'weeklyDetail']);
  });

  it('does not expand untouched sibling branches under the same ancestor', () => {
    const result = resolveRoleMenuSubmitIds({
      menuTree,
      baselineIds: ['monthly'],
      dirtyIds: ['weeklyDetail'],
      checkedIds: ['personal', 'weekly', 'weeklyDetail', 'monthly', 'monthlyDetail']
    });

    assert.deepEqual(result, ['weeklyDetail', 'monthly']);
  });

  it('does not submit half-checked parent ids when a fully authorized branch becomes partial', () => {
    const result = resolveRoleMenuSubmitIds({
      menuTree,
      baselineIds: ['personal'],
      dirtyIds: ['monthlyDetail'],
      checkedIds: ['weekly', 'weeklyDetail']
    });

    assert.deepEqual(result, ['weekly', 'weeklyDetail']);
  });
});

describe('normalizeRoleMenuCheckedIds', () => {
  it('removes partially covered parent ids before tree rendering', () => {
    assert.equal(typeof normalizeRoleMenuCheckedIds, 'function');

    const result = normalizeRoleMenuCheckedIds?.({
      menuTree,
      checkedIds: ['personal', 'weekly', 'weeklyDetail']
    });

    assert.deepEqual(result, ['weekly', 'weeklyDetail']);
  });

  it('keeps parent ids when the backend uses a parent-only full-branch representation', () => {
    assert.equal(typeof normalizeRoleMenuCheckedIds, 'function');

    const result = normalizeRoleMenuCheckedIds?.({
      menuTree,
      checkedIds: ['personal']
    });

    assert.deepEqual(result, ['personal']);
  });
});
