import { Injectable } from '@nestjs/common';
import {
  BUSINESS_ENTITIES,
  BUSINESS_WORKFLOWS,
} from './business-context.registry';
import type {
  BusinessContextPrincipal,
  BusinessContextResult,
  BusinessEntity,
  BusinessWorkflow,
  BusinessWorkflowNextStep,
} from './business-context.types';

function hasPermission(
  principal: BusinessContextPrincipal,
  requiredPermissions: readonly string[],
): boolean {
  if (principal.isSuperAdmin) return true;
  return requiredPermissions.some((permission) => principal.permissions.includes(permission));
}

/**
 * 根据已完成阶段返回后续建议（按权限过滤），供 A2UI 提交回灌等场景直接使用。
 */
export function suggestNextStepsForPrincipal(
  principal: BusinessContextPrincipal,
  completedStageKeys: readonly string[],
): BusinessWorkflowNextStep[] {
  const completed = new Set(completedStageKeys);
  const steps: BusinessWorkflowNextStep[] = [];
  for (const workflow of BUSINESS_WORKFLOWS) {
    if (!hasPermission(principal, workflow.requiredPermissions)) continue;
    for (const step of workflow.nextSteps) {
      if (!step.after.every((stageKey) => completed.has(stageKey))) continue;
      if (step.permission && !hasPermission(principal, [step.permission])) continue;
      steps.push(step);
    }
  }
  return steps;
}

/**
 * 业务上下文服务：把代码内维护的实体字典与工作流元数据按权限暴露给
 * Agent（纯逻辑，不访问数据库）。
 */
@Injectable()
export class BusinessContextService {
  /**
   * 校验注册表引用完整性，返回所有问题；空数组表示合法。
   */
  validateRegistry(): string[] {
    const problems: string[] = [];
    const entityKeys = new Set(BUSINESS_ENTITIES.map((entity) => entity.key));
    const stageKeys = new Set(
      BUSINESS_WORKFLOWS.flatMap((workflow) => workflow.stages.map((stage) => stage.key)),
    );

    const duplicateEntities = BUSINESS_ENTITIES
      .map((entity) => entity.key)
      .filter((key, index, all) => all.indexOf(key) !== index);
    if (duplicateEntities.length) {
      problems.push(`实体 key 重复: ${duplicateEntities.join(', ')}`);
    }

    for (const entity of BUSINESS_ENTITIES) {
      if (!entity.name || !entity.description) {
        problems.push(`实体 ${entity.key} 缺少 name/description`);
      }
      if (entity.requiredPermissions.length === 0) {
        problems.push(`实体 ${entity.key} 缺少权限点`);
      }
      const fieldKeys = new Set<string>();
      for (const field of entity.fields) {
        if (fieldKeys.has(field.key)) {
          problems.push(`实体 ${entity.key} 字段重复: ${field.key}`);
        }
        fieldKeys.add(field.key);
        if (field.type === 'enum' && !field.enumFrom && !field.options) {
          problems.push(`实体 ${entity.key} 枚举字段 ${field.key} 缺少 enumFrom/options`);
        }
      }
      for (const relation of entity.relations) {
        if (!entityKeys.has(relation.entityKey)) {
          problems.push(`实体 ${entity.key} 关系引用未知实体: ${relation.entityKey}`);
        }
        for (const stageKey of relation.requiredFor) {
          if (!stageKeys.has(stageKey)) {
            problems.push(`实体 ${entity.key} 关系 ${relation.via} 引用未知阶段: ${stageKey}`);
          }
        }
      }
    }

    for (const workflow of BUSINESS_WORKFLOWS) {
      if (workflow.requiredPermissions.length === 0) {
        problems.push(`工作流 ${workflow.key} 缺少权限点`);
      }
      const workflowStageKeys = new Set(workflow.stages.map((stage) => stage.key));
      if (workflowStageKeys.size !== workflow.stages.length) {
        problems.push(`工作流 ${workflow.key} 存在重复阶段`);
      }
      for (const stage of workflow.stages) {
        for (const entityKey of stage.entities) {
          if (!entityKeys.has(entityKey)) {
            problems.push(`工作流 ${workflow.key} 阶段 ${stage.key} 引用未知实体: ${entityKey}`);
          }
        }
      }
      for (const [stageKey, prereqs] of Object.entries(workflow.prerequisites)) {
        if (!workflowStageKeys.has(stageKey)) {
          problems.push(`工作流 ${workflow.key} prerequisites 引用未知阶段: ${stageKey}`);
        }
        for (const prereq of prereqs) {
          if (!workflowStageKeys.has(prereq)) {
            problems.push(`工作流 ${workflow.key} 阶段 ${stageKey} 前置引用未知阶段: ${prereq}`);
          }
        }
      }
      for (const step of workflow.nextSteps) {
        for (const afterKey of step.after) {
          if (!workflowStageKeys.has(afterKey)) {
            problems.push(`工作流 ${workflow.key} 下一步 ${step.key} 引用未知阶段: ${afterKey}`);
          }
        }
      }
    }

    return [...new Set(problems)];
  }

  assertValidRegistry(): void {
    const problems = this.validateRegistry();
    if (problems.length > 0) {
      throw new Error(`业务上下文注册表无效: ${problems.join('; ')}`);
    }
  }

  /**
   * 返回当前主体可见的工作流，以及这些工作流阶段引用的实体集合。
   * 传 workflowKey 时只返回该工作流（不可见则返回空）。
   */
  getBusinessContext(
    principal: BusinessContextPrincipal,
    workflowKey?: string,
  ): BusinessContextResult {
    let workflows = BUSINESS_WORKFLOWS.filter((workflow) =>
      hasPermission(principal, workflow.requiredPermissions),
    );
    if (workflowKey) {
      workflows = workflows.filter((workflow) => workflow.key === workflowKey);
    }
    const entityKeys = new Set(
      workflows.flatMap((workflow) => workflow.stages.flatMap((stage) => stage.entities)),
    );
    const entities = BUSINESS_ENTITIES.filter(
      (entity) => entityKeys.has(entity.key) && hasPermission(principal, entity.requiredPermissions),
    );
    return { workflows, entities };
  }

  /** 返回指定实体的字段字典与关系；无权限或未知返回 null。 */
  getEntitySchema(principal: BusinessContextPrincipal, entityKey: string): BusinessEntity | null {
    const entity = BUSINESS_ENTITIES.find((item) => item.key === entityKey);
    if (!entity || !hasPermission(principal, entity.requiredPermissions)) return null;
    return entity;
  }

  /**
   * 根据已完成阶段返回后续建议（按权限过滤）。
   */
  suggestNextSteps(
    principal: BusinessContextPrincipal,
    completedStageKeys: readonly string[],
  ): BusinessWorkflowNextStep[] {
    return suggestNextStepsForPrincipal(principal, completedStageKeys);
  }
}

export { BUSINESS_ENTITIES, BUSINESS_WORKFLOWS };
export type { BusinessContextPrincipal, BusinessWorkflow };
