/**
 * 组织范围(标准数据权限)—— 不建表,内存树 + 登录时展开。
 *
 * 数据权限 = 用户的「org 范围」(一组组织节点,任意层级:集团/品牌/诊所)。
 * 登录时 expandOrgScope() 把 org 范围**展开**成两个过滤维度,塞进 token:
 *   - sourceUnits:范围覆盖的「患者归属层」(jvs-dw = 品牌)→ 过滤患者粒度
 *   - clinicIds:范围覆盖的诊所 → 过滤 plan(target_clinic_id)
 * 过滤层(patient.sourceUnit / plan.targetClinicId)已实现,这里只做"范围→两维"。
 *
 * 树本身是 host 配置(通用态放 manifest yaml org_tree;此处先内置 jvs-dw)。
 * source_unit/品牌只是树上一层 —— 别的 host 患者按诊所发号时,归属层就是诊所,同套机制。
 */

export interface OrgTree {
  groupId: string;
  /** 品牌(= patients.source_unit)→ 其下诊所 id */
  brands: Record<string, { clinics: string[] }>;
}

/**
 * 从「品牌 → 诊所 id 列表」构建组织树。**不 hardcode** —— 调用方从已有配置/数据派生:
 *   - mock/contract:从 MOCK_PRESETS(品牌→诊所)派生;
 *   - 通用态:从摄入数据派生(clinic→brand = patient_transactions.clinic_id JOIN patients.source_unit)。
 * 实现对所有 host 通用,差异只在「树数据」,而树数据 3 层(集团/品牌/诊所)本就在数据里。
 * 仅「区域」等数据外的额外层才需 manifest yaml 声明。
 */
export function buildOrgTree(groupId: string, brandClinics: Record<string, string[]>): OrgTree {
  const brands: OrgTree['brands'] = {};
  for (const [brand, clinics] of Object.entries(brandClinics)) brands[brand] = { clinics };
  return { groupId, brands };
}

export interface ExpandedScope {
  /** 患者归属层范围(品牌)。空数组 = 不限(集团级,看全集团所有品牌) */
  sourceUnits: string[];
  /** 诊所范围。空数组 = 不限(集团级,看全集团所有诊所) */
  clinicIds: string[];
}

/**
 * 把一组 org 节点 ref 展开成 { sourceUnits, clinicIds }。
 * ref 可以是任意层级:
 *   - 集团 id(groupId)→ 不限(sourceUnits=[], clinicIds=[]):看全集团
 *   - 品牌名(source_unit,如 '瑞尔')→ 该品牌 + 其下全部诊所
 *   - 诊所 id → 该诊所 + 其所属品牌
 * 多个 ref 取并集。集团级一旦出现,即整体不限。
 */
export function expandOrgScope(tree: OrgTree, refs: string[]): ExpandedScope {
  if (refs.length === 0) return { sourceUnits: [], clinicIds: [] }; // 空范围 = 不限(集团级)

  const clinicToBrand = new Map<string, string>();
  for (const [brand, b] of Object.entries(tree.brands)) {
    for (const c of b.clinics) clinicToBrand.set(c, brand);
  }

  const sourceUnits = new Set<string>();
  const clinicIds = new Set<string>();

  for (const ref of refs) {
    if (ref === tree.groupId) {
      return { sourceUnits: [], clinicIds: [] }; // 集团级 → 整体不限
    }
    const brand = tree.brands[ref];
    if (brand) {
      // 品牌级
      sourceUnits.add(ref);
      for (const c of brand.clinics) clinicIds.add(c);
      continue;
    }
    const ownerBrand = clinicToBrand.get(ref);
    if (ownerBrand) {
      // 诊所级
      sourceUnits.add(ownerBrand);
      clinicIds.add(ref);
      continue;
    }
    // 未知 ref:当诊所 id 透传(品牌未知则不加 sourceUnit,靠 clinic 圈)
    clinicIds.add(ref);
  }

  return { sourceUnits: [...sourceUnits], clinicIds: [...clinicIds] };
}
