/**
 * SF-02 Requirement Engineering Factory — Entry Point
 *
 * Part P：Requirement Package 统一输出
 * Part Q：Factory Integration（注册到 PR-36 Factory Registry）
 * Part R：Artifacts（13 种需求产物）
 *
 * 输入：SF-01 Product Strategy Package
 * 输出：完整 Requirement Package
 *
 * 流程：
 *   1. 接收 SF-01 Strategy Package
 *   2. Strategy → Requirement Conversion (Part B)
 *   3. Epic Generation (Part C)
 *   4. Feature Generation (Part D)
 *   5. User Story Generation (Part E)
 *   6. Acceptance Criteria Generation (Part F)
 *   7. Business Rules Generation (Part G)
 *   8. Permission Requirements (Part H)
 *   9. NFR Generation (Part I)
 *   10. Integration Requirements (Part J)
 *   11. Data Requirements (Part K)
 *   12. Dependency Graph (Part L)
 *   13. Priority Matrix (Part M)
 *   14. MVP Scope (Part N)
 *   15. Traceability Matrix (Part O)
 *   16. Requirement Package Assembly (Part P)
 *   17. Factory Registration (Part Q)
 *   18. Artifacts Registration (Part R)
 *
 * 禁止：代码生成、数据库设计、架构设计、UI 设计
 * 只负责：产品战略 → 完整需求体系
 *
 * @module sf-02-requirement-engineering
 * @since SF-02
 */

import {
  createRequirementPackage,
} from "./domain-model.mjs";

import {
  convertStrategyToRequirements,
} from "./strategy-to-requirement.mjs";

import {
  buildDependencyGraph, buildPriorityMatrix, generateMVPScope,
  buildTraceabilityMatrix,
} from "./dependency-engine.mjs";

import {
  createFactoryArtifact, createFactoryMetric, createFactoryOutput,
} from "../software-factory-core/factory-contract.mjs";

// ═══════════════════════════════════════════════════════
// SF-02 Artifact Constants (Part R)
// ═══════════════════════════════════════════════════════

export const SF02_ARTIFACTS = Object.freeze({
  REQUIREMENT_PACKAGE:           "requirement-package",
  EPIC_CATALOG:                  "epic-catalog",
  FEATURE_CATALOG:               "feature-catalog",
  USER_STORY_CATALOG:            "user-story-catalog",
  ACCEPTANCE_CRITERIA_PACKAGE:   "acceptance-criteria-package",
  BUSINESS_RULES_CATALOG:        "business-rules-catalog",
  PERMISSION_REQUIREMENTS:       "permission-requirements",
  NFR_PACKAGE:                   "nfr-package",
  INTEGRATION_REQUIREMENTS:      "integration-requirements",
  DATA_REQUIREMENTS:             "data-requirements",
  DEPENDENCY_GRAPH:              "dependency-graph",
  PRIORITY_MATRIX:               "priority-matrix",
  MVP_SCOPE:                     "mvp-scope",
  TRACEABILITY_MATRIX:           "traceability-matrix",
});

// ═══════════════════════════════════════════════════════
// Requirement Package Report Generator
// ═══════════════════════════════════════════════════════

/**
 * 生成 Requirement Package 的 Executive Summary Markdown。
 *
 * @param {object} pkg — RequirementPackage
 * @returns {string}
 */
export function generateRequirementReport(pkg) {
  const es = pkg.executiveSummary || {};
  const sp = pkg.strategyPackage || {};
  const mvp = pkg.mvpScope || {};

  const formatB = (v) => v >= 1e9 ? `$${(v / 1e9).toFixed(1)}B` : `$${(v / 1e6).toFixed(0)}M`;

  const lines = [
    `# Requirement Package: ${pkg.productName || "New Product"}`,
    "",
    "## Executive Summary",
    "",
    `- **Product:** ${pkg.productName}`,
    `- **Strategy Source:** SF-01 Product Strategy Factory`,
    `- **Generated:** ${new Date().toISOString().slice(0, 10)}`,
    `- **Viability:** ${sp.executiveSummary?.viabilityVerdict || "N/A"} (${sp.executiveSummary?.viabilityScore || 0}/100)`,
    `- **Priority:** ${sp.executiveSummary?.priorityLevel || "N/A"}`,
    "",
    "## Requirement Statistics",
    "",
    "| Category | Count |",
    "|----------|-------|",
    `| Epics | **${(pkg.epics || []).length}** |`,
    `| Features | **${(pkg.features || []).length}** |`,
    `| User Stories | **${(pkg.userStories || []).length}** |`,
    `| Acceptance Criteria | **${(pkg.acceptanceCriteria || []).length}** |`,
    `| Business Rules | **${(pkg.businessRules || []).length}** |`,
    `| NFRs | **${(pkg.nonFunctionalReqs || []).length}** |`,
    `| Integration Reqs | **${(pkg.integrationReqs || []).length}** |`,
    `| Data Reqs | **${(pkg.dataReqs || []).length}** |`,
    `| Dependencies | **${(pkg.dependencies || []).length}** |`,
    `| Traceability Links | **${(pkg.traceabilityLinks || []).length}** |`,
    "",
    "## Epic Catalog",
    "",
    ...((pkg.epics || []).map((e, i) => `| ${i + 1} | **${e.title}** | ${e.category} | ${e.objective || ""} | ${(pkg.features || []).filter(f => f.epicId === e.id).length} Features |`)),
    "",
    "| # | Epic | Category | Objective | Features |",
    "|---|------|----------|-----------|----------|",

    ...((pkg.epics || []).map((e, i) => `| ${i + 1} | **${e.title}** | ${e.category} | ${e.objective || ""} | ${(pkg.features || []).filter(f => f.epicId === e.id).length} |`)),
    "",
    "## Feature Catalog (Sample)",
    "",
    "| # | Feature | Epic | Type |",
    "|---|---------|------|------|",
    ...((pkg.features || []).slice(0, 20).map((f, i) => {
      const epic = (pkg.epics || []).find(e => e.id === f.epicId);
      return `| ${i + 1} | ${f.title} | ${epic?.title || "—"} | ${f.featureType} |`;
    })),
    ...((pkg.features || []).length > 20 ? [`| ... | _${(pkg.features || []).length - 20} more features_ | ... | ... |`] : []),
    "",
    "## User Story Catalog (Sample)",
    "",
    "| # | Story | Priority | Points |",
    "|---|-------|----------|--------|",
    ...((pkg.userStories || []).slice(0, 15).map((s, i) => {
      const priorityIcon = s.priority === "Must Have" ? "🔴" : s.priority === "Should Have" ? "🟡" : s.priority === "Could Have" ? "🟢" : "⚪";
      return `| ${i + 1} | ${s.statement} | ${priorityIcon} ${s.priority} | ${s.storyPoints} |`;
    })),
    ...((pkg.userStories || []).length > 15 ? [`| ... | _${(pkg.userStories || []).length - 15} more stories_ | ... | ... |`] : []),
    "",
    "## Acceptance Criteria (Sample)",
    "",
    ...((pkg.acceptanceCriteria || []).slice(0, 10).map((ac, i) => (
      `**AC #${i + 1}** ${ac.scenario ? `[${ac.scenario}]` : ""}\n> Given ${ac.given}, When ${ac.when}, Then ${ac.then}.\n`
    ))),
    "",
    "## Business Rules",
    "",
    "| # | Rule | Type | Condition |",
    "|---|------|------|-----------|",
    ...((pkg.businessRules || []).map((br, i) => `| ${i + 1} | ${br.name} | ${br.ruleType} | ${br.condition || "—"} |`)),
    "",
    "## Non-Functional Requirements",
    "",
    "| # | NFR | Category | Metric | Target |",
    "|---|-----|----------|--------|--------|",
    ...((pkg.nonFunctionalReqs || []).map((nfr, i) => `| ${i + 1} | ${nfr.name} | ${nfr.category} | ${nfr.metric || "—"} | ${nfr.target || "—"} |`)),
    "",
    "## Integration Requirements",
    "",
    "| # | Integration | Category | Necessity | Providers |",
    "|---|-------------|----------|-----------|-----------|",
    ...((pkg.integrationReqs || []).map((ir, i) => `| ${i + 1} | ${ir.name} | ${ir.category} | ${ir.necessity} | ${(ir.providers || []).join(", ") || "—"} |`)),
    "",
    "## Data Requirements",
    "",
    "| # | Entity | Classification | Owner | Lifecycle |",
    "|---|--------|----------------|-------|-----------|",
    ...((pkg.dataReqs || []).map((dr, i) => `| ${i + 1} | ${dr.entityName} | ${dr.dataClassification} | ${dr.owner} | ${(dr.lifecycle || []).join(" → ")} |`)),
    "",
    "## Permission Model",
    "",
    `- **Access Model:** ${pkg.permissionReqs?.[0]?.accessModel || "N/A"}`,
    `- **Roles:** ${(pkg.permissionReqs?.[0]?.roles || []).map(r => r.name).join(", ")}`,
    `- **Resource Types:** ${(pkg.permissionReqs?.[0]?.resourceTypes || []).join(", ")}`,
    "",
    "## MVP Scope",
    "",
    "| Phase | Epics | Features | Stories | Story Points |",
    "|-------|-------|----------|---------|--------------|",
    `| MVP | ${mvp.mvp?.epics || 0} | ${mvp.mvp?.features || 0} | ${mvp.mvp?.userStories || 0} | ${mvp.mvp?.totalStoryPoints || 0} |`,
    `| V1  | ${mvp.v1?.epics || 0} | ${mvp.v1?.features || 0} | ${mvp.v1?.userStories || 0} | ${mvp.v1?.totalStoryPoints || 0} |`,
    `| V2  | ${mvp.v2?.epics || 0} | ${mvp.v2?.features || 0} | ${mvp.v2?.userStories || 0} | ${mvp.v2?.totalStoryPoints || 0} |`,
    "",
    "## Priority Distribution",
    "",
    "| Category | Epic Count | Feature Count | Story Count |",
    "|----------|-----------|---------------|-------------|",
    ...(["Must Have", "Should Have", "Could Have", "Won't Have"].map(cat => {
      const eCount = (pkg.priorities || []).filter(p => p.itemType === "epic" && p.category === cat).length;
      const fCount = (pkg.priorities || []).filter(p => p.itemType === "feature" && p.category === cat).length;
      const sCount = (pkg.priorities || []).filter(p => p.itemType === "story" && p.category === cat).length;
      return `| ${cat} | ${eCount} | ${fCount} | ${sCount} |`;
    })),
    "",
    "## Traceability Coverage",
    "",
    "| Link Type | Count |",
    "|-----------|-------|",
    ...(Object.entries(pkg.traceabilityLinks?.[0]?.matrix || pkg.traceabilityLinks || {}).slice(0, 10).map(([k, v]) => {
      if (typeof v === "object") return "";
      return `| ${k} | ${v} |`;
    }).filter(Boolean)),
    `| **Total Links** | **${(pkg.traceabilityLinks || []).length}** |`,
    "",
    "---",
    `_Generated by SF-02 Requirement Engineering Factory at ${new Date().toISOString()}_`,
    "_Source: SF-01 Product Strategy Factory → SF-02 Requirement Engineering Factory → SF-03 Product Design Factory_",
    "",
  ];

  return lines.join("\n");
}

// ═══════════════════════════════════════════════════════
// Strategy Data Extraction Helper
// ═══════════════════════════════════════════════════════

/**
 * Extract structured strategy data from SF-01 Markdown report + metadata.
 * SF-01 artifacts store reports as Markdown content, not JSON.
 */
function _extractStrategyFromMarkdown(artifact) {
  const content = artifact?.content || "";
  const meta = artifact?.metadata || {};

  // Extract product name from artifact name
  const nameMatch = artifact?.name?.match(/Strategy:\s*(.+)/);
  const productName = nameMatch ? nameMatch[1] : (meta.productName || "Unknown");

  // Extract viability score
  const viabilityMatch = content.match(/Viability.*?\((\d+)\/100\)/);
  const viabilityScore = viabilityMatch ? parseInt(viabilityMatch[1]) : 50;

  // Extract viability verdict
  const verdictMatch = content.match(/\*\*Viability:\*\*\s*(\S+)/);
  const verdict = verdictMatch ? verdictMatch[1].replace(/\*/g, "") : "UNKNOWN";

  // Extract priority
  const priorityMatch = content.match(/\*\*Priority:\*\*\s*(\S+)/);
  const priorityLevel = priorityMatch ? priorityMatch[1].replace(/\*/g, "") : "P2";

  // Extract recommendation
  const recMatch = content.match(/\*\*Recommendation:\*\*\s*(.+)/);
  const recommendation = recMatch ? recMatch[1].trim() : "";

  // Extract category from metadata or artifact content
  const category = meta.category || meta._category || "通用";

  // Estimate roadmap duration
  const durationMatch = content.match(/Total Duration.*?(\d+)\s*months/);
  const totalDurationMonths = durationMatch ? parseInt(durationMatch[1]) : 12;

  // Estimate budget
  const budgetMatch = content.match(/Total Budget.*?\$([0-9,]+)/);
  const totalBudget = budgetMatch ? parseInt(budgetMatch[1].replace(/,/g, "")) : 1_000_000;

  return {
    executiveSummary: {
      title: `Product Strategy: ${productName}`,
      viabilityVerdict: verdict,
      viabilityScore,
      priorityLevel,
      recommendation,
    },
    productName,
    roadmap: {
      totalDurationMonths,
      totalBudget,
      phases: [
        { phase: "mvp", scope: "最小可行产品", durationMonths: Math.ceil(totalDurationMonths * 0.3), budget: Math.round(totalBudget * 0.25) },
        { phase: "v1", scope: "第一完整版本", durationMonths: Math.ceil(totalDurationMonths * 0.35), budget: Math.round(totalBudget * 0.35) },
        { phase: "v2", scope: "功能增强版本", durationMonths: Math.ceil(totalDurationMonths * 0.25), budget: Math.round(totalBudget * 0.25) },
        { phase: "enterprise", scope: "企业版功能", durationMonths: Math.ceil(totalDurationMonths * 0.1), budget: Math.round(totalBudget * 0.15) },
      ],
    },
    metadata: { factoryId: "SF-01", category },
  };
}

// ═══════════════════════════════════════════════════════
// SF-02 Factory Implementation (Part Q)
// ═══════════════════════════════════════════════════════

/**
 * SF-02 Factory 实现函数。
 *
 * 遵循 PR-36 Factory Contract：
 *   入参：FactoryInput（包含 upstreamArtifacts 中的 SF-01 Strategy Package）
 *   出参：FactoryOutput（包含完整 Requirement Package）
 *
 * @param {object} input — FactoryInput
 * @returns {object} FactoryOutput
 */
export function sf02RequirementEngineeringFactory(input) {
  const startTime = Date.now();

  // ── 1. 从 upstreamArtifacts 中提取 SF-01 Strategy Package ──
  const upstreamArtifacts = input?.upstreamArtifacts || [];
  const strategyArtifact = upstreamArtifacts.find(
    a => a.metadata?.artifactType === "product-strategy-package" || a.kind === "requirement"
  );

  if (!strategyArtifact) {
    // Fallback: try parameters
    const rawIdea = input?.parameters?.idea || input?.parameters?.raw || "";
    if (!rawIdea) {
      return createFactoryOutput({
        factoryId: "SF-02",
        status: "failed",
        error: "No SF-01 Strategy Package found in upstreamArtifacts. Provide product-strategy-package artifact or parameters.idea.",
      });
    }
    return createFactoryOutput({
      factoryId: "SF-02",
      status: "blocked",
      error: "SF-02 requires SF-01 output. Run SF-01 Product Strategy Factory first.",
    });
  }

  try {
    // ── 2. 提取策略数据 ──
    // SF-01 content is Markdown, not JSON. Extract data from content + metadata.
    let strategyPackage = strategyArtifact.metadata?.strategyPackage || null;
    if (!strategyPackage && strategyArtifact.content) {
      // Try JSON parse, fallback to content-based extraction
      try {
        strategyPackage = JSON.parse(strategyArtifact.content);
      } catch {
        // Extract structured data from Markdown report
        strategyPackage = _extractStrategyFromMarkdown(strategyArtifact);
      }
    }
    if (!strategyPackage || Object.keys(strategyPackage).length === 0) {
      strategyPackage = _extractStrategyFromMarkdown(strategyArtifact);
    }
    // Also merge any additional metadata from input.parameters
    if (input?.parameters) {
      strategyPackage = { ...strategyPackage, _parameters: input.parameters };
    }

    const productName = strategyPackage?.executiveSummary?.title?.replace("Product Strategy: ", "")
      || strategyPackage?.productName
      || input?.product?.name
      || "New Product";

    // ── 3. Strategy → Requirement Conversion ──
    const req = convertStrategyToRequirements(strategyPackage);

    // ── 4. Dependency Graph ──
    const { dependencies, graph: depGraph } = buildDependencyGraph(req);

    // ── 5. Priority Matrix ──
    const epicPri = buildPriorityMatrix(req.epics, "epic", strategyPackage);
    const featurePri = buildPriorityMatrix(req.features, "feature", strategyPackage);
    const storyPri = buildPriorityMatrix(req.userStories, "story", strategyPackage);

    const allPriorities = [
      ...epicPri.priorities,
      ...featurePri.priorities,
      ...storyPri.priorities,
    ];

    const priorityMatrix = {
      epic: epicPri.matrix,
      feature: featurePri.matrix,
      story: storyPri.matrix,
      combined: {
        mustHave: allPriorities.filter(p => p.category === "Must Have").length,
        shouldHave: allPriorities.filter(p => p.category === "Should Have").length,
        couldHave: allPriorities.filter(p => p.category === "Could Have").length,
        wontHave: allPriorities.filter(p => p.category === "Won't Have").length,
      },
    };

    // ── 6. MVP Scope ──
    const mvpScope = generateMVPScope({
      strategyPackage,
      epicPriorities: epicPri.priorities,
      featurePriorities: featurePri.priorities,
      storyPriorities: storyPri.priorities,
      epics: req.epics,
      features: req.features,
      userStories: req.userStories,
    });

    // ── 7. Traceability Matrix ──
    const { links: traceabilityLinks, matrix: traceMatrix } = buildTraceabilityMatrix({
      epics: req.epics,
      features: req.features,
      userStories: req.userStories,
      acceptanceCriteria: req.acceptanceCriteria,
      businessRules: req.businessRules,
      nonFunctionalReqs: req.nonFunctionalReqs,
      permissionReqs: req.permissionReqs,
      integrationReqs: req.integrationReqs,
      dataReqs: req.dataReqs,
    });

    // ── 8. Assemble Requirement Package ──
    const reqPackage = createRequirementPackage({
      productName,
      strategyPackage,
      executiveSummary: {
        productName,
        strategyVerdict: strategyPackage?.executiveSummary?.viabilityVerdict || "N/A",
        strategyScore: strategyPackage?.executiveSummary?.viabilityScore || 0,
        epicCount: req.epics.length,
        featureCount: req.features.length,
        storyCount: req.userStories.length,
        acCount: req.acceptanceCriteria.length,
        mvpStoryCount: mvpScope.mvp.userStories,
        totalStoryPoints: mvpScope.mvp.totalStoryPoints,
      },
      epics: req.epics,
      features: req.features,
      userStories: req.userStories,
      acceptanceCriteria: req.acceptanceCriteria,
      businessRules: req.businessRules,
      constraints: [],
      nonFunctionalReqs: req.nonFunctionalReqs,
      permissionReqs: [req.permissionReqs],
      integrationReqs: req.integrationReqs,
      dataReqs: req.dataReqs,
      riskReqs: [],
      traceabilityLinks,
      dependencies,
      priorities: allPriorities,
      mvpScope,
    });

    // ── 9. Build Artifacts ──
    const reportContent = generateRequirementReport(reqPackage);

    const artifacts = [
      createFactoryArtifact({
        kind: "requirement",
        name: `Requirement Package: ${productName}`,
        factoryId: "SF-02",
        content: reportContent,
        metadata: {
          artifactType: SF02_ARTIFACTS.REQUIREMENT_PACKAGE,
          strategySource: "SF-01",
          ...req.summary,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Epic Catalog: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.epics, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.EPIC_CATALOG,
          count: req.epics.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Feature Catalog: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.features, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.FEATURE_CATALOG,
          count: req.features.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `User Story Catalog: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.userStories, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.USER_STORY_CATALOG,
          count: req.userStories.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Acceptance Criteria Package: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.acceptanceCriteria, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.ACCEPTANCE_CRITERIA_PACKAGE,
          count: req.acceptanceCriteria.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Business Rules Catalog: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.businessRules, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.BUSINESS_RULES_CATALOG,
          count: req.businessRules.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Permission Requirements: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.permissionReqs, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.PERMISSION_REQUIREMENTS,
          accessModel: req.permissionReqs?.accessModel || "RBAC",
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `NFR Package: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.nonFunctionalReqs, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.NFR_PACKAGE,
          count: req.nonFunctionalReqs.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Integration Requirements: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.integrationReqs, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.INTEGRATION_REQUIREMENTS,
          count: req.integrationReqs.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Data Requirements: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(req.dataReqs, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.DATA_REQUIREMENTS,
          count: req.dataReqs.length,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Dependency Graph: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(depGraph, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.DEPENDENCY_GRAPH,
          nodeCount: depGraph.nodes?.length || 0,
          edgeCount: depGraph.edges?.length || 0,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Priority Matrix: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(priorityMatrix, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.PRIORITY_MATRIX,
          ...priorityMatrix.combined,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `MVP Scope: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(mvpScope, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.MVP_SCOPE,
          mvpStories: mvpScope.mvp.userStories,
          mvpPoints: mvpScope.mvp.totalStoryPoints,
        },
      }),
      createFactoryArtifact({
        kind: "requirement",
        name: `Traceability Matrix: ${productName}`,
        factoryId: "SF-02",
        content: JSON.stringify(traceMatrix, null, 2),
        metadata: {
          artifactType: SF02_ARTIFACTS.TRACEABILITY_MATRIX,
          totalLinks: traceMatrix.totalLinks,
        },
      }),
    ];

    // ── 10. Metrics ──
    const durationMs = Date.now() - startTime;
    const metrics = [
      createFactoryMetric({ factoryId: "SF-02", name: "epic.count", value: req.epics.length, kind: "count", unit: "epics" }),
      createFactoryMetric({ factoryId: "SF-02", name: "feature.count", value: req.features.length, kind: "count", unit: "features" }),
      createFactoryMetric({ factoryId: "SF-02", name: "story.count", value: req.userStories.length, kind: "count", unit: "stories" }),
      createFactoryMetric({ factoryId: "SF-02", name: "ac.count", value: req.acceptanceCriteria.length, kind: "count", unit: "ac" }),
      createFactoryMetric({ factoryId: "SF-02", name: "dependency.count", value: dependencies.length, kind: "count", unit: "deps" }),
      createFactoryMetric({ factoryId: "SF-02", name: "traceability.count", value: traceabilityLinks.length, kind: "count", unit: "links" }),
      createFactoryMetric({ factoryId: "SF-02", name: "mvp.stories", value: mvpScope.mvp.userStories, kind: "count", unit: "stories" }),
      createFactoryMetric({ factoryId: "SF-02", name: "mvp.points", value: mvpScope.mvp.totalStoryPoints, kind: "count", unit: "points" }),
      createFactoryMetric({ factoryId: "SF-02", name: "coverage.epicToFeature", value: req.features.length / Math.max(1, req.epics.length), kind: "ratio", unit: "ratio" }),
      createFactoryMetric({ factoryId: "SF-02", name: "coverage.acToStory", value: req.acceptanceCriteria.length / Math.max(1, req.userStories.length), kind: "ratio", unit: "ratio" }),
      createFactoryMetric({ factoryId: "SF-02", name: "duration.ms", value: durationMs, kind: "duration", unit: "ms" }),
    ];

    return createFactoryOutput({
      factoryId: "SF-02",
      status: "passed",
      artifacts,
      metrics,
      decisions: [
        { title: "Epic Decomposition", description: `${req.epics.length} epics identified for ${productName}` },
        { title: "MVP Scope", description: `${mvpScope.mvp.userStories} Must Have stories (${mvpScope.mvp.totalStoryPoints} pts)` },
        { title: "Traceability", description: `${traceabilityLinks.length} traceability links established` },
      ],
      nextActions: [
        "Proceed to SF-03 Product Design Factory with Requirement Package",
        "Review Epic Catalog with stakeholders",
        "Validate User Stories with target customers",
        "Register all artifacts in SF-02 Artifact Graph",
      ],
      metadata: {
        strategySource: strategyPackage?.metadata?.factoryId || "SF-01",
        generatedAt: new Date().toISOString(),
        inputArtifactId: strategyArtifact.id,
        ...req.summary,
      },
    });
  } catch (err) {
    return createFactoryOutput({
      factoryId: "SF-02",
      status: "failed",
      error: `SF-02 requirement engineering error: ${err.message}`,
      metrics: [
        createFactoryMetric({ factoryId: "SF-02", name: "duration.ms", value: Date.now() - startTime, kind: "duration", unit: "ms" }),
      ],
    });
  }
}

/**
 * 将 SF-02 注册到给定的 Factory Registry。
 *
 * @param {object} registry — PR-36 FactoryRegistry
 */
export function registerSF02(registry) {
  registry.registerImplementation("SF-02", sf02RequirementEngineeringFactory);
}

// ═══════════════════════════════════════════════════════
// Barrel Re-exports
// ═══════════════════════════════════════════════════════

// Domain Model
export * from "./domain-model.mjs";

// Conversion Engine
export {
  convertStrategyToRequirements,
  generateEpicsFromStrategy,
  generateFeaturesFromEpic,
  generateUserStoriesFromFeature,
  generateAcceptanceCriteriaForStory,
  generateIntegrationRequirements,
  generateNFRs,
  generatePermissionRequirements,
  generateBusinessRules,
  generateDataRequirements,
} from "./strategy-to-requirement.mjs";

// Dependency & Priority & MVP & Traceability
export {
  buildDependencyGraph,
  buildPriorityMatrix,
  generateMVPScope,
  buildTraceabilityMatrix,
  prioritizeByMoSCoW,
  prioritizeByRICE,
  prioritizeByWSJF,
} from "./dependency-engine.mjs";
