import { describe, expect, it } from '@jest/globals';
import { BusinessContextService } from './business-context.service';

function principal(permissions: string[] = [], isSuperAdmin = false) {
  return { permissions, isSuperAdmin };
}

describe('BusinessContextService', () => {
  it('registry 中所有工作流/实体/权限引用都有效', () => {
    const service = new BusinessContextService();
    expect(service.validateRegistry()).toEqual([]);
    expect(() => service.assertValidRegistry()).not.toThrow();
  });

  it('超级管理员可查看全部工作流与实体', () => {
    const service = new BusinessContextService();
    const result = service.getBusinessContext(principal([], true));
    expect(result.workflows.length).toBeGreaterThanOrEqual(3);
    expect(result.entities.length).toBeGreaterThanOrEqual(10);
    expect(result.workflows.map((item) => item.key)).toEqual(
      expect.arrayContaining(['student_teaching', 'dormitory_billing', 'classroom_rental']),
    );
  });

  it('按权限过滤实体，且只暴露有权限的工作流', () => {
    const service = new BusinessContextService();
    const result = service.getBusinessContext(principal(['student:view', 'class:view']));
    const entityKeys = result.entities.map((item) => item.key);
    expect(entityKeys).toContain('student');
    expect(entityKeys).toContain('class');
    expect(entityKeys).not.toContain('bill');
    expect(result.workflows.map((item) => item.key)).toEqual(['student_teaching']);
  });

  it('workflowKey 聚焦时只返回对应工作流与实体', () => {
    const service = new BusinessContextService();
    const result = service.getBusinessContext(
      principal(['room:view', 'occupancy:view', 'expense:view', 'bill:view', 'student:view'], false),
      'dormitory_billing',
    );
    expect(result.workflows.map((item) => item.key)).toEqual(['dormitory_billing']);
    expect(result.entities.map((item) => item.key)).toEqual(
      expect.arrayContaining(['room', 'occupancy', 'expense', 'bill', 'student']),
    );
  });

  it('未知或不可见 workflowKey 返回空结果', () => {
    const service = new BusinessContextService();
    expect(service.getBusinessContext(principal([], false), 'unknown_loop').workflows).toEqual([]);
    expect(
      service.getBusinessContext(principal(['student:view'], false), 'dormitory_billing').workflows,
    ).toEqual([]);
  });

  it('getEntitySchema 返回字段字典与关系，未知/无权限实体返回 null', () => {
    const service = new BusinessContextService();
    const student = service.getEntitySchema(principal(['student:view']), 'student');
    expect(student?.fields.map((field) => field.key)).toEqual(
      expect.arrayContaining(['name', 'phone', 'gender', 'studentNo']),
    );
    expect(student?.relations.some((relation) => relation.entityKey === 'class')).toBe(true);
    expect(service.getEntitySchema(principal(['student:view']), 'bill')).toBeNull();
    expect(service.getEntitySchema(principal(['student:view']), 'unknown')).toBeNull();
  });

  it('suggestNextSteps 只返回已完成阶段对应的下一步建议', () => {
    const service = new BusinessContextService();
    const steps = service.suggestNextSteps(principal([], true), ['profile', 'checkin']);
    const labels = steps.map((item) => item.label);
    expect(labels).toEqual(
      expect.arrayContaining([expect.stringContaining('费用')]),
    );
    expect(labels.some((item) => item.includes('账单'))).toBe(false);
    expect(service.suggestNextSteps(principal([], true), ['profile']).some((item) => item.after.includes('checkin'))).toBe(false);
    const afterExpense = service.suggestNextSteps(principal([], true), [
      'profile',
      'room',
      'checkin',
      'expense',
    ]);
    expect(afterExpense.map((item) => item.label)).toEqual(
      expect.arrayContaining([expect.stringContaining('账单')]),
    );
  });
});
